[gimp] app: add GimpTranslationStore class
- From: Sven Neumann <neo src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gimp] app: add GimpTranslationStore class
- Date: Tue, 5 Jan 2010 21:44:24 +0000 (UTC)
commit 50c2ba45ec5ca23322442d5cc6491ab6a627ce20
Author: Sven Neumann <sven gimp org>
Date: Wed Dec 30 23:55:26 2009 +0100
app: add GimpTranslationStore class
Derive GimpTranslationStore from GimpLanguageStore. It lists the
installed GIMP translations. Also sort the list alphabetically
instead of relying on the XML file being sorted.
app/app.c | 2 -
app/widgets/Makefile.am | 2 +
app/widgets/gimplanguagecombobox.c | 6 +-
app/widgets/gimplanguageentry.c | 3 +-
app/widgets/gimplanguagestore-parser.c | 54 ++++++----
app/widgets/gimplanguagestore-parser.h | 6 +-
app/widgets/gimplanguagestore.c | 113 ++++++++++++++++--
app/widgets/gimplanguagestore.h | 17 ++-
app/widgets/gimptranslationstore.c | 196 ++++++++++++++++++++++++++++++++
app/widgets/gimptranslationstore.h | 44 +++++++
app/widgets/widgets-types.h | 1 +
11 files changed, 396 insertions(+), 48 deletions(-)
---
diff --git a/app/app.c b/app/app.c
index 0c9bd87..64c85b3 100644
--- a/app/app.c
+++ b/app/app.c
@@ -280,8 +280,6 @@ app_init_language (const gchar *language)
if (! language)
return;
- g_printerr ("Setting language to %s\n", language);
-
g_setenv ("LANGUAGE", language, TRUE);
setlocale (LC_ALL, "");
}
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index 1bc7db3..a595be1 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -314,6 +314,8 @@ libappwidgets_a_sources = \
gimptooloptionseditor.h \
gimptooloverlay.c \
gimptooloverlay.h \
+ gimptranslationstore.c \
+ gimptranslationstore.h \
gimpuimanager.c \
gimpuimanager.h \
gimpundoeditor.c \
diff --git a/app/widgets/gimplanguagecombobox.c b/app/widgets/gimplanguagecombobox.c
index a8a767b..4411c6b 100644
--- a/app/widgets/gimplanguagecombobox.c
+++ b/app/widgets/gimplanguagecombobox.c
@@ -31,7 +31,7 @@
#include "widgets-types.h"
#include "gimplanguagecombobox.h"
-#include "gimplanguagestore.h"
+#include "gimptranslationstore.h"
struct _GimpLanguageComboBox
@@ -60,7 +60,7 @@ gimp_language_combo_box_init (GimpLanguageComboBox *combo)
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
- "text", GIMP_LANGUAGE_STORE_LANGUAGE,
+ "text", GIMP_LANGUAGE_STORE_LANGUAGE,
NULL);
}
@@ -70,7 +70,7 @@ gimp_language_combo_box_new (void)
GtkWidget *combo;
GtkListStore *store;
- store = gimp_language_store_new ();
+ store = gimp_translation_store_new ();
combo = g_object_new (GIMP_TYPE_LANGUAGE_COMBO_BOX,
"model", store,
diff --git a/app/widgets/gimplanguageentry.c b/app/widgets/gimplanguageentry.c
index a296777..303f8f5 100644
--- a/app/widgets/gimplanguageentry.c
+++ b/app/widgets/gimplanguageentry.c
@@ -165,8 +165,7 @@ gimp_language_entry_set_property (GObject *object,
switch (property_id)
{
case PROP_MODEL:
- if (entry->store)
- g_object_unref (entry->store);
+ g_return_if_fail (entry->store == NULL);
entry->store = g_value_dup_object (value);
break;
diff --git a/app/widgets/gimplanguagestore-parser.c b/app/widgets/gimplanguagestore-parser.c
index 1796925..59c31ea 100644
--- a/app/widgets/gimplanguagestore-parser.c
+++ b/app/widgets/gimplanguagestore-parser.c
@@ -2,7 +2,7 @@
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplanguagestore-parser.c
- * Copyright (C) 2008 Sven Neumann <sven gimp org>
+ * Copyright (C) 2008, 2009 Sven Neumann <sven gimp org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,28 +68,13 @@ static void iso_codes_parser_start_unknown (IsoCodesParser *parser);
static void iso_codes_parser_end_unknown (IsoCodesParser *parser);
-static const GMarkupParser markup_parser =
-{
- iso_codes_parser_start_element,
- iso_codes_parser_end_element,
- NULL, /* characters */
- NULL, /* passthrough */
- NULL /* error */
-};
-
-
-gboolean
-gimp_language_store_populate (GimpLanguageStore *store,
- GError **error)
+static void
+iso_codes_parser_init (void)
{
-#ifdef HAVE_ISO_CODES
- GimpXmlParser *xml_parser;
- gchar *filename;
- gboolean success;
- IsoCodesParser parser = { 0, };
+ static gboolean initialized = FALSE;
- g_return_val_if_fail (GIMP_IS_LANGUAGE_STORE (store), FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ if (initialized)
+ return;
#ifdef G_OS_WIN32
/* on Win32, assume iso-codes is installed in the same location as GIMP */
@@ -100,6 +85,33 @@ gimp_language_store_populate (GimpLanguageStore *store,
bind_textdomain_codeset ("iso_639", "UTF-8");
+ initialized = TRUE;
+}
+
+gboolean
+gimp_language_store_parse_iso_codes (GimpLanguageStore *store,
+ GError **error)
+{
+#ifdef HAVE_ISO_CODES
+ static const GMarkupParser markup_parser =
+ {
+ iso_codes_parser_start_element,
+ iso_codes_parser_end_element,
+ NULL, /* characters */
+ NULL, /* passthrough */
+ NULL /* error */
+ };
+
+ GimpXmlParser *xml_parser;
+ gchar *filename;
+ gboolean success;
+ IsoCodesParser parser = { 0, };
+
+ g_return_val_if_fail (GIMP_IS_LANGUAGE_STORE (store), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ iso_codes_parser_init ();
+
parser.store = g_object_ref (store);
xml_parser = gimp_xml_parser_new (&markup_parser, &parser);
diff --git a/app/widgets/gimplanguagestore-parser.h b/app/widgets/gimplanguagestore-parser.h
index 5fa091c..d84edd1 100644
--- a/app/widgets/gimplanguagestore-parser.h
+++ b/app/widgets/gimplanguagestore-parser.h
@@ -2,7 +2,7 @@
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplanguagestore-parser.h
- * Copyright (C) 2008 Sven Neumann <sven gimp org>
+ * Copyright (C) 2008, 2009 Sven Neumann <sven gimp org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,8 +22,8 @@
#define __GIMP_LANGUAGE_STORE_PARSER_H__
-gboolean gimp_language_store_populate (GimpLanguageStore *store,
- GError **error);
+gboolean gimp_language_store_parse_iso_codes (GimpLanguageStore *store,
+ GError **error);
#endif /* __GIMP_LANGUAGE_STORE_PARSER_H__ */
diff --git a/app/widgets/gimplanguagestore.c b/app/widgets/gimplanguagestore.c
index cb90ca1..198f3cd 100644
--- a/app/widgets/gimplanguagestore.c
+++ b/app/widgets/gimplanguagestore.c
@@ -2,7 +2,7 @@
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplanguagestore.c
- * Copyright (C) 2008 Sven Neumann <sven gimp org>
+ * Copyright (C) 2008, 2009 Sven Neumann <sven gimp org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,11 +30,33 @@
#include "gimplanguagestore-parser.h"
+static GObject * gimp_language_store_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params);
+
+static void gimp_language_store_real_add (GimpLanguageStore *store,
+ const gchar *lang,
+ const gchar *code);
+
+static gint gimp_language_store_sort (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer userdata);
+
+
G_DEFINE_TYPE (GimpLanguageStore, gimp_language_store, GTK_TYPE_LIST_STORE)
+#define parent_class gimp_language_store_parent_class
+
+
static void
gimp_language_store_class_init (GimpLanguageStoreClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = gimp_language_store_constructor;
+
+ klass->add = gimp_language_store_real_add;
}
static void
@@ -45,7 +67,81 @@ gimp_language_store_init (GimpLanguageStore *store)
gtk_list_store_set_column_types (GTK_LIST_STORE (store),
G_N_ELEMENTS (column_types), column_types);
- gimp_language_store_populate (store, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
+ GIMP_LANGUAGE_STORE_LANGUAGE,
+ gimp_language_store_sort, NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+ GIMP_LANGUAGE_STORE_LANGUAGE,
+ GTK_SORT_ASCENDING);
+}
+
+static GObject *
+gimp_language_store_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
+{
+ GObject *object;
+
+ object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
+
+ gimp_language_store_parse_iso_codes (GIMP_LANGUAGE_STORE (object), NULL);
+
+ return object;
+}
+
+static void
+gimp_language_store_real_add (GimpLanguageStore *store,
+ const gchar *lang,
+ const gchar *code)
+{
+ GtkTreeIter iter;
+
+ gtk_list_store_append (GTK_LIST_STORE (store), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (store), &iter,
+ GIMP_LANGUAGE_STORE_LANGUAGE, lang,
+ GIMP_LANGUAGE_STORE_ISO_639_1, code,
+ -1);
+}
+
+static gint
+gimp_language_store_sort (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer userdata)
+{
+ GValue avalue = { 0, };
+ GValue bvalue = { 0, };
+ gint cmp = 0;
+
+ /* keep system language at the top of the list */
+ gtk_tree_model_get_value (model, a,
+ GIMP_LANGUAGE_STORE_ISO_639_1, &avalue);
+ gtk_tree_model_get_value (model, b,
+ GIMP_LANGUAGE_STORE_ISO_639_1, &bvalue);
+
+ if (! g_value_get_string (&avalue))
+ cmp = -1;
+
+ if (! g_value_get_string (&bvalue))
+ cmp = 1;
+
+ g_value_unset (&avalue);
+ g_value_unset (&bvalue);
+
+ if (cmp)
+ return cmp;
+
+ /* sort lanugages alphabetically */
+ gtk_tree_model_get_value (model, a, GIMP_LANGUAGE_STORE_LANGUAGE, &avalue);
+ gtk_tree_model_get_value (model, b, GIMP_LANGUAGE_STORE_LANGUAGE, &bvalue);
+
+ cmp = g_utf8_collate (g_value_get_string (&avalue),
+ g_value_get_string (&bvalue));
+
+ g_value_unset (&avalue);
+ g_value_unset (&bvalue);
+
+ return cmp;
}
GtkListStore *
@@ -59,17 +155,10 @@ gimp_language_store_add (GimpLanguageStore *store,
const gchar *lang,
const gchar *code)
{
- GtkTreeIter iter;
-
g_return_if_fail (GIMP_IS_LANGUAGE_STORE (store));
- g_return_if_fail (lang != NULL && code != NULL);
-
- gtk_list_store_append (GTK_LIST_STORE (store), &iter);
+ g_return_if_fail (lang != NULL);
- gtk_list_store_set (GTK_LIST_STORE (store), &iter,
- GIMP_LANGUAGE_STORE_LANGUAGE, lang,
- GIMP_LANGUAGE_STORE_ISO_639_1, code,
- -1);
+ GIMP_LANGUAGE_STORE_GET_CLASS (store)->add (store, lang, code);
}
gboolean
@@ -108,7 +197,7 @@ gimp_language_store_lookup (GimpLanguageStore *store,
GIMP_LANGUAGE_STORE_ISO_639_1, &value,
-1);
- if (strncmp (code, value, len) == 0)
+ if (value && strncmp (code, value, len) == 0)
{
g_free (value);
break;
diff --git a/app/widgets/gimplanguagestore.h b/app/widgets/gimplanguagestore.h
index e316466..51e9b8d 100644
--- a/app/widgets/gimplanguagestore.h
+++ b/app/widgets/gimplanguagestore.h
@@ -2,7 +2,7 @@
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplanguagestore.h
- * Copyright (C) 2008 Sven Neumann <sven gimp org>
+ * Copyright (C) 2008, 2009 Sven Neumann <sven gimp org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,23 +42,30 @@ typedef struct _GimpLanguageStoreClass GimpLanguageStoreClass;
struct _GimpLanguageStoreClass
{
GtkListStoreClass parent_class;
+
+ void (* add) (GimpLanguageStore *store,
+ const gchar *lang,
+ const gchar *code);
};
struct _GimpLanguageStore
{
- GtkListStore parent_instance;
+ GtkListStore parent_instance;
};
GType gimp_language_store_get_type (void) G_GNUC_CONST;
GtkListStore * gimp_language_store_new (void);
-void gimp_language_store_add (GimpLanguageStore *store,
- const gchar *lang,
- const gchar *code);
+
gboolean gimp_language_store_lookup (GimpLanguageStore *store,
const gchar *code,
GtkTreeIter *iter);
+/* used from gimplanguagestore-parser.c */
+void gimp_language_store_add (GimpLanguageStore *store,
+ const gchar *lang,
+ const gchar *code);
+
#endif /* __GIMP_LANGUAGE_STORE_H__ */
diff --git a/app/widgets/gimptranslationstore.c b/app/widgets/gimptranslationstore.c
new file mode 100644
index 0000000..f56c10b
--- /dev/null
+++ b/app/widgets/gimptranslationstore.c
@@ -0,0 +1,196 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptranslationstore.c
+ * Copyright (C) 2008, 2009 Sven Neumann <sven gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "widgets-types.h"
+
+#include "gimptranslationstore.h"
+
+#include "gimp-intl.h"
+
+
+struct _GimpTranslationStoreClass
+{
+ GimpLanguageStoreClass parent_class;
+};
+
+struct _GimpTranslationStore
+{
+ GimpLanguageStore parent_instance;
+
+ GHashTable *map;
+};
+
+
+static GObject * gimp_translation_store_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params);
+
+static void gimp_translation_store_add (GimpLanguageStore *store,
+ const gchar *lang,
+ const gchar *code);
+
+static void gimp_translation_store_populate (GimpTranslationStore *store);
+
+
+G_DEFINE_TYPE (GimpTranslationStore,
+ gimp_translation_store, GIMP_TYPE_LANGUAGE_STORE)
+
+#define parent_class gimp_translation_store_parent_class
+
+
+static void
+gimp_translation_store_class_init (GimpTranslationStoreClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpLanguageStoreClass *store_class = GIMP_LANGUAGE_STORE_CLASS (klass);
+
+ object_class->constructor = gimp_translation_store_constructor;
+
+ store_class->add = gimp_translation_store_add;
+}
+
+static void
+gimp_translation_store_init (GimpTranslationStore *store)
+{
+ store->map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+}
+
+static GObject *
+gimp_translation_store_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
+{
+ GimpTranslationStore *store;
+ GObject *object;
+ gchar *label;
+
+ object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
+ store = GIMP_TRANSLATION_STORE (object);
+
+ gimp_translation_store_populate (store);
+
+ /* we don't need the map any longer */
+ g_hash_table_unref (store->map);
+ store->map = NULL;
+
+ /* add special entries for system locale and for "C" */
+ GIMP_LANGUAGE_STORE_CLASS (parent_class)->add (GIMP_LANGUAGE_STORE (store),
+ _("System Language"),
+ NULL);
+ label = g_strdup_printf ("%s [%s]", _("English"), "en_US");
+ GIMP_LANGUAGE_STORE_CLASS (parent_class)->add (GIMP_LANGUAGE_STORE (store),
+ label, "en_US");
+ g_free (label);
+
+ return object;
+}
+
+static const gchar *
+gimp_translation_store_map (GimpTranslationStore *store,
+ const gchar *locale)
+{
+ const gchar *lang;
+
+ /* A locale directory name is typically of the form language[_territory] */
+ lang = g_hash_table_lookup (store->map, locale);
+
+ if (! lang)
+ {
+ /* strip off the territory suffix */
+ const gchar *delimiter = strchr (locale, '_');
+
+ if (delimiter)
+ {
+ gchar *copy;
+
+ copy = g_strndup (locale, delimiter - locale);
+ lang = g_hash_table_lookup (store->map, copy);
+ g_free (copy);
+ }
+ }
+
+ return lang;
+}
+
+static void
+gimp_translation_store_populate (GimpTranslationStore *store)
+{
+ /* FIXME: this should better be done asynchronously */
+ GDir *dir = g_dir_open (gimp_locale_directory (), 0, NULL);
+ const gchar *dirname;
+
+ if (! dir)
+ return;
+
+ while ((dirname = g_dir_read_name (dir)) != NULL)
+ {
+ gchar *filename = g_build_filename (gimp_locale_directory (),
+ dirname,
+ "LC_MESSAGES",
+ GETTEXT_PACKAGE ".mo",
+ NULL);
+ if (g_file_test (filename, G_FILE_TEST_EXISTS))
+ {
+ const gchar *lang = gimp_translation_store_map (store, dirname);
+
+ if (lang)
+ {
+ GimpLanguageStore *language_store = GIMP_LANGUAGE_STORE (store);
+ gchar *label;
+
+ label = g_strdup_printf ("%s [%s]", lang, dirname);
+
+ GIMP_LANGUAGE_STORE_CLASS (parent_class)->add (language_store,
+ label, dirname);
+ g_free (label);
+ }
+ }
+
+ g_free (filename);
+ }
+
+ g_dir_close (dir);
+}
+
+static void
+gimp_translation_store_add (GimpLanguageStore *store,
+ const gchar *lang,
+ const gchar *code)
+{
+ g_hash_table_replace (GIMP_TRANSLATION_STORE (store)->map,
+ g_strdup (code),
+ g_strdup (lang));
+}
+
+GtkListStore *
+gimp_translation_store_new (void)
+{
+ return g_object_new (GIMP_TYPE_TRANSLATION_STORE, NULL);
+}
diff --git a/app/widgets/gimptranslationstore.h b/app/widgets/gimptranslationstore.h
new file mode 100644
index 0000000..83fb509
--- /dev/null
+++ b/app/widgets/gimptranslationstore.h
@@ -0,0 +1,44 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptranslationstore.h
+ * Copyright (C) 2009 Sven Neumann <sven gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_TRANSLATION_STORE_H__
+#define __GIMP_TRANSLATION_STORE_H__
+
+
+#include "gimplanguagestore.h"
+
+
+#define GIMP_TYPE_TRANSLATION_STORE (gimp_translation_store_get_type ())
+#define GIMP_TRANSLATION_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TRANSLATION_STORE, GimpTranslationStore))
+#define GIMP_TRANSLATION_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TRANSLATION_STORE, GimpTranslationStoreClass))
+#define GIMP_IS_TRANSLATION_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TRANSLATION_STORE))
+#define GIMP_IS_TRANSLATION_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TRANSLATION_STORE))
+#define GIMP_TRANSLATION_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TRANSLATION_STORE, GimpTranslationStoreClass))
+
+
+typedef struct _GimpTranslationStoreClass GimpTranslationStoreClass;
+
+
+GType gimp_translation_store_get_type (void) G_GNUC_CONST;
+
+GtkListStore * gimp_translation_store_new (void);
+
+
+#endif /* __GIMP_TRANSLATION_STORE_H__ */
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index 5301955..bd7be48 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -188,6 +188,7 @@ typedef struct _GimpTagEntry GimpTagEntry;
typedef struct _GimpTagPopup GimpTagPopup;
typedef struct _GimpTemplateEditor GimpTemplateEditor;
typedef struct _GimpThumbBox GimpThumbBox;
+typedef struct _GimpTranslationStore GimpTranslationStore;
typedef struct _GimpUnitStore GimpUnitStore;
typedef struct _GimpUnitComboBox GimpUnitComboBox;
typedef struct _GimpWindow GimpWindow;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]