[gtk/file-chooser-api-cleanups] filechooser: Add gtk_file_chooser_get_filters



commit a2fed5020f0e5cdf39e8aec90695b479a555a7bc
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 4 12:15:47 2020 -0400

    filechooser: Add gtk_file_chooser_get_filters
    
    Replace gtk_file_chooser_list_filters with a new
    api that returns a list model.
    
    Update all callers.

 docs/reference/gtk/gtk4-sections.txt |  2 +-
 gtk/gtkfilechooser.c                 | 19 +++++++-------
 gtk/gtkfilechooser.h                 |  8 +++---
 gtk/gtkfilechoosernativeportal.c     | 29 +++++++++++++--------
 gtk/gtkfilechoosernativequartz.c     | 50 ++++++++++++++++++++++++++----------
 gtk/gtkfilechoosernativewin32.c      | 45 +++++++++++++++++++++++---------
 gtk/gtkfilechooserprivate.h          | 48 +++++++++++++++++-----------------
 gtk/gtkfilechooserutils.c            | 10 ++++----
 gtk/gtkfilechooserwidget.c           | 21 ++++-----------
 tests/testgtk.c                      | 14 ++++++----
 10 files changed, 146 insertions(+), 100 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 208151976c..88d4e4d46d 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -1306,7 +1306,7 @@ gtk_file_chooser_get_current_folder
 <SUBSECTION>
 gtk_file_chooser_add_filter
 gtk_file_chooser_remove_filter
-gtk_file_chooser_list_filters
+gtk_file_chooser_get_filters
 gtk_file_chooser_set_filter
 gtk_file_chooser_get_filter
 <SUBSECTION>
diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c
index 985a18a1ca..4b11b975b3 100644
--- a/gtk/gtkfilechooser.c
+++ b/gtk/gtkfilechooser.c
@@ -682,23 +682,24 @@ gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
 }
 
 /**
- * gtk_file_chooser_list_filters:
+ * gtk_file_chooser_get_filters:
  * @chooser: a #GtkFileChooser
  * 
- * Lists the current set of user-selectable filters; see
+ * Gets the current set of user-selectable filters, as a list model; see
  * gtk_file_chooser_add_filter(), gtk_file_chooser_remove_filter().
  *
- * Returns: (element-type GtkFileFilter) (transfer container): a
- *  #GSList containing the current set of user selectable filters. The
- *  contents of the list are owned by GTK+, but you must free the list
- *  itself with g_slist_free() when you are done with it.
+ * You should not modify the returned list model. Future changes to
+ * filechooser may or may not affect the returned model.
+ *
+ * Returns: (transfer full): a #GListModel containing the current set
+ *     of user-selectable filters.
  **/
-GSList *
-gtk_file_chooser_list_filters  (GtkFileChooser *chooser)
+GListModel *
+gtk_file_chooser_get_filters (GtkFileChooser *chooser)
 {
   g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
 
-  return GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_filters (chooser);
+  return GTK_FILE_CHOOSER_GET_IFACE (chooser)->get_filters (chooser);
 }
 
 /**
diff --git a/gtk/gtkfilechooser.h b/gtk/gtkfilechooser.h
index 2aff129c5d..1f3381b993 100644
--- a/gtk/gtkfilechooser.h
+++ b/gtk/gtkfilechooser.h
@@ -145,18 +145,18 @@ GFile *  gtk_file_chooser_get_current_folder      (GtkFileChooser  *chooser);
  */
 GDK_AVAILABLE_IN_ALL
 void    gtk_file_chooser_add_filter    (GtkFileChooser *chooser,
-                                       GtkFileFilter  *filter);
+                                        GtkFileFilter  *filter);
 GDK_AVAILABLE_IN_ALL
 void    gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
-                                       GtkFileFilter  *filter);
+                                        GtkFileFilter  *filter);
 GDK_AVAILABLE_IN_ALL
-GSList *gtk_file_chooser_list_filters  (GtkFileChooser *chooser);
+GListModel *gtk_file_chooser_get_filters  (GtkFileChooser *chooser);
 
 /* Current filter
  */
 GDK_AVAILABLE_IN_ALL
 void           gtk_file_chooser_set_filter (GtkFileChooser *chooser,
-                                           GtkFileFilter  *filter);
+                                            GtkFileFilter  *filter);
 GDK_AVAILABLE_IN_ALL
 GtkFileFilter *gtk_file_chooser_get_filter (GtkFileChooser *chooser);
 
diff --git a/gtk/gtkfilechoosernativeportal.c b/gtk/gtkfilechoosernativeportal.c
index db992b9b5b..d14a28cb34 100644
--- a/gtk/gtkfilechoosernativeportal.c
+++ b/gtk/gtkfilechoosernativeportal.c
@@ -126,7 +126,7 @@ response_cb (GDBusConnection  *connection,
   if (current_filter)
     {
       GtkFileFilter *filter = gtk_file_filter_new_from_gvariant (current_filter);
-      const gchar *current_filter_name = gtk_file_filter_get_name (filter);
+      const char *current_filter_name = gtk_file_filter_get_name (filter);
 
       /* Try to find  the given filter in the list of filters.
        * Since filters are compared by pointer value, using the passed
@@ -137,18 +137,24 @@ response_cb (GDBusConnection  *connection,
        * If there is no match, just set the filter as it was retrieved.
        */
       GtkFileFilter *filter_to_select = filter;
-      GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self));
-      for (GSList *l = filters; l; l = l->next)
+      GListModel *filters;
+      guint j, n;
+
+      filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (self));
+      n = g_list_model_get_n_items (filters);
+      for (j = 0; j < n; j++)
         {
-          GtkFileFilter *f = l->data;
+          GtkFileFilter *f = g_list_model_get_item (filters, j);
           if (g_strcmp0 (gtk_file_filter_get_name (f), current_filter_name) == 0)
             {
               filter_to_select = f;
               break;
             }
+          g_object_unref (f);
         }
-      g_slist_free (filters);
+      g_object_unref (filters);
       gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (self), filter_to_select);
+      g_object_unref (filter_to_select);
     }
 
   g_slist_free_full (self->custom_files, g_object_unref);
@@ -264,17 +270,20 @@ open_file_msg_cb (GObject *source_object,
 static GVariant *
 get_filters (GtkFileChooser *self)
 {
-  GSList *list, *l;
+  GListModel *filters;
+  guint n, i;
   GVariantBuilder builder;
 
   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sa(us))"));
-  list = gtk_file_chooser_list_filters (self);
-  for (l = list; l; l = l->next)
+  filters = gtk_file_chooser_get_filters (self);
+  n = g_list_model_get_n_items (filters);
+  for (i = 0; i < n; i++)
     {
-      GtkFileFilter *filter = l->data;
+      GtkFileFilter *filter = g_list_model_get_item (filters, i);
       g_variant_builder_add (&builder, "@(sa(us))", gtk_file_filter_to_gvariant (filter));
+      g_object_unref (filter);
     }
-  g_slist_free (list);
+  g_object_unref (filters);
 
   return g_variant_builder_end (&builder);
 }
diff --git a/gtk/gtkfilechoosernativequartz.c b/gtk/gtkfilechoosernativequartz.c
index 6ce0e936f7..d7cf4113a4 100644
--- a/gtk/gtkfilechoosernativequartz.c
+++ b/gtk/gtkfilechoosernativequartz.c
@@ -99,9 +99,10 @@ typedef struct {
   else
     [data->panel setAllowedFileTypes:filter];
 
-  GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (data->self));
-  data->self->current_filter = g_slist_nth_data (filters, selected_index);
-  g_slist_free (filters);
+  GListModel *filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self));
+  data->self->current_filter = g_list_model_get_item (filters, selected_index);
+  g_object_unref (data->self->current_filter);
+  g_object_unref (filters);
   g_object_notify (G_OBJECT (data->self), "filter");
 }
 @end
@@ -307,13 +308,28 @@ filechooser_quartz_launch (FileChooserQuartzData *data)
 
       if (data->self->current_filter)
         {
-          GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (data->self));
-         gint current_filter_index = g_slist_index (filters, data->self->current_filter);
-         g_slist_free (filters);
+          GListModel *filters;
+          guint i, n;
+          guint current_filter_index = GTK_INVALID_LIST_POSITION;
 
-         if (current_filter_index >= 0)
+          filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self));
+          n = g_list_model_get_n_items (filters);
+          for (i = 0; i < n; i++)
+            {
+              gpointer item = g_list_model_get_item (filters, i);
+              if (item == data->self->current_filter)
+                {
+                  g_object_unref (item);
+                  current_filter_index = i;
+                  break;
+                }
+              g_object_unref (item);
+            }
+          g_object_unref (filters);
+
+          if (current_filter_index != GTK_INVALID_LIST_POSITION)
             [data->filter_combo_box selectItemAtIndex:current_filter_index];
-         else
+          else
             [data->filter_combo_box selectItemAtIndex:0];
         }
       else
@@ -437,15 +453,15 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self)
   GtkWindow *transient_for;
   GtkFileChooserAction action;
 
-  GSList *filters, *l;
-  int n_filters, i;
+  GListModel *filters;
+  guint n_filters, i;
   char *message = NULL;
 
   data = g_new0 (FileChooserQuartzData, 1);
 
   // examine filters!
-  filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self));
-  n_filters = g_slist_length (filters);
+  filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (self));
+  n_filters = g_list_model_get_n_items (filters);
   if (n_filters > 0)
     {
       data->filters = [NSMutableArray arrayWithCapacity:n_filters];
@@ -453,13 +469,17 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self)
       data->filter_names = [NSMutableArray arrayWithCapacity:n_filters];
       [data->filter_names retain];
 
-      for (l = filters, i = 0; l != NULL; l = l->next, i++)
+      for (i = 0; i < n; i++)
         {
-          if (!file_filter_to_quartz (l->data, data->filters, data->filter_names))
+          GtkFileFilter *filter = g_list_model_get_item (filters, i);
+          if (!file_filter_to_quartz (filter, data->filters, data->filter_names))
             {
               filechooser_quartz_data_free (data);
+              g_object_unref (filter);
+              g_object_unref (filters);
               return FALSE;
             }
+          g_object_unref (filter);
         }
       self->current_filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self));
     }
@@ -467,6 +487,8 @@ gtk_file_chooser_native_quartz_show (GtkFileChooserNative *self)
     {
       self->current_filter = NULL;
     }
+  g_object_unref (filters);
+
   self->mode_data = data;
   data->self = g_object_ref (self);
 
diff --git a/gtk/gtkfilechoosernativewin32.c b/gtk/gtkfilechoosernativewin32.c
index 026fcd862b..722f324ae8 100644
--- a/gtk/gtkfilechoosernativewin32.c
+++ b/gtk/gtkfilechoosernativewin32.c
@@ -244,9 +244,11 @@ ifiledialogevents_OnTypeChange (IFileDialogEvents * self,
       return S_OK;
     }
   fileType--; // fileTypeIndex starts at 1 
-  GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (events->data->self));
-  events->data->self->current_filter = g_slist_nth_data (filters, fileType);
-  g_slist_free (filters);
+  GListModel *filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (events->data->self));
+  GtkFileFilter *filter = g_list_model_get_item (filters, fileType);
+  events->data->self->current_filter = filter;
+  g_object_unref (filter);
+  g_object_unref (filters);
   g_object_notify (G_OBJECT (events->data->self), "filter");
   return S_OK;
 }
@@ -591,9 +593,24 @@ filechooser_win32_thread (gpointer _data)
 
       if (data->self->current_filter)
         {
-          GSList *filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (data->self));
-         gint current_filter_index = g_slist_index (filters, data->self->current_filter);
-         g_slist_free (filters);
+          GListModel *filters;
+          guint n_items, i;
+          guint current_filter_index = GTK_INVALID_LIST_POSITION;
+
+          filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (data->self));
+          n_items = g_list_model_get_n_items (filters);
+          for (i = 0; i < n_items; i++)
+            {
+              gpointer item = g_list_model_get_item (filters, i);
+              if (item == data->self->current_filter)
+                {
+                  current_filter_index = i;
+                  g_object_unref (item);
+                  break;
+                }
+              g_object_unref (item);
+            }
+         g_object_unref (filters);
 
          if (current_filter_index >= 0)
            hr = IFileDialog_SetFileTypeIndex (pfd, current_filter_index + 1);
@@ -864,21 +881,24 @@ gtk_file_chooser_native_win32_show (GtkFileChooserNative *self)
   FilechooserWin32ThreadData *data;
   GtkWindow *transient_for;
   GtkFileChooserAction action;
-  GSList *filters, *l;
-  int n_filters, i;
+  GListModel *filters;
+  guint n_filters, i;
 
   data = g_new0 (FilechooserWin32ThreadData, 1);
 
-  filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (self));
-  n_filters = g_slist_length (filters);
+  filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (self));
+  n_filters = g_list_model_get_n_items (filters);
   if (n_filters > 0)
     {
       data->filters = g_new0 (COMDLG_FILTERSPEC, n_filters + 1);
 
-      for (l = filters, i = 0; l != NULL; l = l->next, i++)
+      for (i = 0; i < n_filters; i++)
         {
-          if (!file_filter_to_win32 (l->data, &data->filters[i]))
+          GtkFileFilter *filter = g_list_model_get_item (filters, i);
+          if (!file_filter_to_win32 (filter, &data->filters[i]))
             {
+              g_object_unref (filter);
+              g_object_unref (filters);
               filechooser_win32_thread_data_free (data);
               return FALSE;
             }
@@ -889,6 +909,7 @@ gtk_file_chooser_native_win32_show (GtkFileChooserNative *self)
     {
       self->current_filter = NULL;
     }
+  g_object_unref (filters);
 
   self->mode_data = data;
   data->self = g_object_ref (self);
diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
index 06a49dea03..d0f2b53910 100644
--- a/gtk/gtkfilechooserprivate.h
+++ b/gtk/gtkfilechooserprivate.h
@@ -58,33 +58,33 @@ struct _GtkFileChooserIface
 
   /* Methods
    */
-  gboolean       (*set_current_folder)            (GtkFileChooser    *chooser,
-                                           GFile             *file,
-                                           GError           **error);
-  GFile *        (*get_current_folder)            (GtkFileChooser    *chooser);
-  void           (*set_current_name)              (GtkFileChooser    *chooser,
-                                           const gchar       *name);
+  gboolean       (*set_current_folder)     (GtkFileChooser    *chooser,
+                                            GFile             *file,
+                                            GError           **error);
+  GFile *        (*get_current_folder)     (GtkFileChooser    *chooser);
+  void           (*set_current_name)       (GtkFileChooser    *chooser,
+                                            const gchar       *name);
   gchar *        (*get_current_name)       (GtkFileChooser    *chooser);
-  gboolean       (*select_file)                   (GtkFileChooser    *chooser,
-                                           GFile             *file,
-                                           GError           **error);
-  void           (*unselect_file)                 (GtkFileChooser    *chooser,
-                                           GFile             *file);
-  void           (*select_all)                    (GtkFileChooser    *chooser);
-  void           (*unselect_all)                  (GtkFileChooser    *chooser);
-  GSList *       (*get_files)                     (GtkFileChooser    *chooser);
-  GtkFileSystem *(*get_file_system)               (GtkFileChooser    *chooser);
-  void           (*add_filter)                    (GtkFileChooser    *chooser,
-                                           GtkFileFilter     *filter);
-  void           (*remove_filter)                 (GtkFileChooser    *chooser,
-                                           GtkFileFilter     *filter);
-  GSList *       (*list_filters)                  (GtkFileChooser    *chooser);
+  gboolean       (*select_file)            (GtkFileChooser    *chooser,
+                                            GFile             *file,
+                                            GError           **error);
+  void           (*unselect_file)          (GtkFileChooser    *chooser,
+                                            GFile             *file);
+  void           (*select_all)             (GtkFileChooser    *chooser);
+  void           (*unselect_all)           (GtkFileChooser    *chooser);
+  GSList *       (*get_files)              (GtkFileChooser    *chooser);
+  GtkFileSystem *(*get_file_system)        (GtkFileChooser    *chooser);
+  void           (*add_filter)             (GtkFileChooser    *chooser,
+                                            GtkFileFilter     *filter);
+  void           (*remove_filter)          (GtkFileChooser    *chooser,
+                                            GtkFileFilter     *filter);
+  GListModel *   (*get_filters)            (GtkFileChooser    *chooser);
   gboolean       (*add_shortcut_folder)    (GtkFileChooser    *chooser,
-                                           GFile             *file,
-                                           GError           **error);
+                                            GFile             *file,
+                                            GError           **error);
   gboolean       (*remove_shortcut_folder) (GtkFileChooser    *chooser,
-                                           GFile             *file,
-                                           GError           **error);
+                                            GFile             *file,
+                                            GError           **error);
   GSList *       (*list_shortcut_folders)  (GtkFileChooser    *chooser);
 
   /* Signals
diff --git a/gtk/gtkfilechooserutils.c b/gtk/gtkfilechooserutils.c
index afa166056e..71713a49ff 100644
--- a/gtk/gtkfilechooserutils.c
+++ b/gtk/gtkfilechooserutils.c
@@ -45,7 +45,7 @@ static void           delegate_add_filter             (GtkFileChooser    *choose
                                                       GtkFileFilter     *filter);
 static void           delegate_remove_filter          (GtkFileChooser    *chooser,
                                                       GtkFileFilter     *filter);
-static GSList *       delegate_list_filters           (GtkFileChooser    *chooser);
+static GListModel *   delegate_get_filters            (GtkFileChooser    *chooser);
 static gboolean       delegate_add_shortcut_folder    (GtkFileChooser    *chooser,
                                                       GFile             *file,
                                                       GError           **error);
@@ -131,7 +131,7 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface)
   iface->get_file_system = delegate_get_file_system;
   iface->add_filter = delegate_add_filter;
   iface->remove_filter = delegate_remove_filter;
-  iface->list_filters = delegate_list_filters;
+  iface->get_filters = delegate_get_filters;
   iface->add_shortcut_folder = delegate_add_shortcut_folder;
   iface->remove_shortcut_folder = delegate_remove_shortcut_folder;
   iface->list_shortcut_folders = delegate_list_shortcut_folders;
@@ -241,10 +241,10 @@ delegate_remove_filter (GtkFileChooser *chooser,
   gtk_file_chooser_remove_filter (get_delegate (chooser), filter);
 }
 
-static GSList *
-delegate_list_filters (GtkFileChooser *chooser)
+static GListModel *
+delegate_get_filters (GtkFileChooser *chooser)
 {
-  return gtk_file_chooser_list_filters (get_delegate (chooser));
+  return gtk_file_chooser_get_filters (get_delegate (chooser));
 }
 
 static gboolean
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 48d3185868..1c2d2619ed 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -485,7 +485,7 @@ static void           gtk_file_chooser_widget_add_filter                   (GtkF
                                                                             GtkFileFilter     *filter);
 static void           gtk_file_chooser_widget_remove_filter                (GtkFileChooser    *chooser,
                                                                             GtkFileFilter     *filter);
-static GSList *       gtk_file_chooser_widget_list_filters                 (GtkFileChooser    *chooser);
+static GListModel *   gtk_file_chooser_widget_get_filters                  (GtkFileChooser    *chooser);
 static gboolean       gtk_file_chooser_widget_add_shortcut_folder    (GtkFileChooser    *chooser,
                                                                        GFile             *file,
                                                                        GError           **error);
@@ -619,7 +619,7 @@ gtk_file_chooser_widget_iface_init (GtkFileChooserIface *iface)
   iface->get_current_name = gtk_file_chooser_widget_get_current_name;
   iface->add_filter = gtk_file_chooser_widget_add_filter;
   iface->remove_filter = gtk_file_chooser_widget_remove_filter;
-  iface->list_filters = gtk_file_chooser_widget_list_filters;
+  iface->get_filters = gtk_file_chooser_widget_get_filters;
   iface->add_shortcut_folder = gtk_file_chooser_widget_add_shortcut_folder;
   iface->remove_shortcut_folder = gtk_file_chooser_widget_remove_shortcut_folder;
   iface->list_shortcut_folders = gtk_file_chooser_widget_list_shortcut_folders;
@@ -5599,23 +5599,12 @@ gtk_file_chooser_widget_remove_filter (GtkFileChooser *chooser,
     show_filters (impl, FALSE);
 }
 
-static GSList *
-gtk_file_chooser_widget_list_filters (GtkFileChooser *chooser)
+static GListModel *
+gtk_file_chooser_widget_get_filters (GtkFileChooser *chooser)
 {
   GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (chooser);
-  GSList *filters;
-  guint i;
-
-  filters = NULL;
-
-  for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (impl->filters)); i++)
-    {
-      GtkFileFilter *filter = g_list_model_get_item (G_LIST_MODEL (impl->filters), i);
-      filters = g_slist_append (filters, filter);
-      g_object_unref (filter);
-    }
 
-  return filters;
+  return G_LIST_MODEL (g_object_ref (impl->filters));
 }
 
 static gboolean
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 791ea10f46..c79d4ad53e 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -5672,15 +5672,19 @@ native_filter_changed (GtkWidget *combo,
                        GtkFileChooserNative *native)
 {
   int i;
-  GSList *filters, *l;
+  GListModel *filters;
   GtkFileFilter *filter;
 
   i = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
 
-  filters = gtk_file_chooser_list_filters (GTK_FILE_CHOOSER (native));
-  for (l = filters; l != NULL; l = l->next)
-    gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (native), l->data);
-  g_slist_free (filters);
+  filters = gtk_file_chooser_get_filters (GTK_FILE_CHOOSER (native));
+  while (g_list_model_get_n_items (filters) > 0)
+    {
+      GtkFileFilter *f = g_list_model_get_item (filters, 0);
+      gtk_file_chooser_remove_filter (GTK_FILE_CHOOSER (native), f);
+      g_object_unref (f);
+    }
+  g_object_unref (filters);
 
   switch (i)
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]