gnome-control-center r8673 - trunk/capplets/keyboard



Author: svu
Date: Sun Apr 27 15:13:32 2008
New Revision: 8673
URL: http://svn.gnome.org/viewvc/gnome-control-center?rev=8673&view=rev

Log:
Support for countries and languages

Added:
   trunk/capplets/keyboard/gnome-keyboard-properties-iso.c
Modified:
   trunk/capplets/keyboard/ChangeLog
   trunk/capplets/keyboard/gnome-keyboard-properties-xkb.h
   trunk/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c
   trunk/capplets/keyboard/gnome-keyboard-properties-xkbpv.c
   trunk/capplets/keyboard/gnome-keyboard-properties.glade

Added: trunk/capplets/keyboard/gnome-keyboard-properties-iso.c
==============================================================================
--- (empty file)
+++ trunk/capplets/keyboard/gnome-keyboard-properties-iso.c	Sun Apr 27 15:13:32 2008
@@ -0,0 +1,203 @@
+/* -*- mode: c; style: linux -*- */
+
+/* gnome-keyboard-properties-xkbltadd.c
+ * Copyright (C) 2007 Sergey V. Udaltsov
+ *
+ * Written by: Sergey V. Udaltsov <svu gnome 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 2, 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <gnome.h>
+#include <glib/gi18n.h>
+#include <glade/glade.h>
+
+#include <gnome-keyboard-properties-xkb.h>
+
+#define ISO_CODES_DATADIR    ISO_CODES_PREFIX "/share/xml/iso-codes"
+#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
+
+static GHashTable *country_code_names = NULL;
+static GHashTable *lang_code_names = NULL;
+
+typedef struct {
+	const gchar *domain;
+	const gchar *attr_names[];
+} LookupParams;
+
+typedef struct {
+	GHashTable *code_names;
+	const gchar *tag_name;
+	LookupParams *params;
+} CodeBuildStruct;
+
+static LookupParams countryLookup = { "iso_3166", {"alpha_2_code", NULL} };
+static LookupParams languageLookup =
+    { "iso_639", {"iso_639_2B_code", "iso_639_2T_code", NULL} };
+
+static void
+iso_codes_parse_start_tag (GMarkupParseContext * ctx,
+			   const gchar * element_name,
+			   const gchar ** attr_names,
+			   const gchar ** attr_values,
+			   gpointer user_data, GError ** error)
+{
+	const gchar *name;
+	const gchar **san = attr_names, **sav = attr_values;
+	CodeBuildStruct *cbs = (CodeBuildStruct *) user_data;
+
+	/* Is this the tag we are looking for? */
+	if (!g_str_equal (element_name, cbs->tag_name) ||
+	    attr_names == NULL || attr_values == NULL) {
+		return;
+	}
+
+	name = NULL;
+
+	/* What would be the value? */
+	while (*attr_names && *attr_values) {
+		if (g_str_equal (*attr_names, "name")) {
+			name = *attr_values;
+			break;
+		}
+
+		attr_names++;
+		attr_values++;
+	}
+
+	if (!name) {
+		return;
+	}
+
+	attr_names = san;
+	attr_values = sav;
+
+	/* Walk again the attributes */
+	while (*attr_names && *attr_values) {
+		const gchar **attr = cbs->params->attr_names;
+		/* Look through all the attributess we are interested in */
+		while (*attr) {
+			if (g_str_equal (*attr_names, *attr)) {
+				if (**attr_values) {
+					g_hash_table_insert (cbs->
+							     code_names,
+							     g_strdup
+							     (*attr_values),
+							     g_strdup
+							     (name));
+				}
+			}
+			attr++;
+		}
+
+		attr_names++;
+		attr_values++;
+	}
+}
+
+static GHashTable *
+iso_code_names_init (LookupParams * params)
+{
+	GError *err = NULL;
+	gchar *buf, *filename, *tag_name;
+	gsize buf_len;
+	CodeBuildStruct cbs;
+
+	GHashTable *ht = g_hash_table_new_full (g_str_hash, g_str_equal,
+						g_free, g_free);
+
+	tag_name = g_strdup_printf ("%s_entry", params->domain);
+
+	cbs.code_names = ht;
+	cbs.tag_name = tag_name;
+	cbs.params = params;
+
+	bindtextdomain (params->domain, ISO_CODES_LOCALESDIR);
+	bind_textdomain_codeset (params->domain, "UTF-8");
+
+	filename =
+	    g_strdup_printf ("%s/%s.xml", ISO_CODES_DATADIR,
+			     params->domain);
+	if (g_file_get_contents (filename, &buf, &buf_len, &err)) {
+		GMarkupParseContext *ctx;
+		GMarkupParser parser = {
+			iso_codes_parse_start_tag,
+			NULL, NULL, NULL, NULL
+		};
+
+		ctx = g_markup_parse_context_new (&parser, 0, &cbs, NULL);
+		if (!g_markup_parse_context_parse
+		    (ctx, buf, buf_len, &err)) {
+			g_warning ("Failed to parse '%s/%s.xml': %s",
+				   ISO_CODES_DATADIR,
+				   params->domain, err->message);
+			g_error_free (err);
+		}
+
+		g_markup_parse_context_free (ctx);
+		g_free (buf);
+	} else {
+		g_warning ("Failed to load '%s/%s.xml': %s",
+			   ISO_CODES_DATADIR, params->domain,
+			   err->message);
+		g_error_free (err);
+	}
+	g_free (filename);
+	g_free (tag_name);
+
+	return ht;
+}
+
+const char *
+get_language_iso_code (const char *code)
+{
+	const gchar *name;
+
+	if (!lang_code_names) {
+		lang_code_names = iso_code_names_init (&languageLookup);
+	}
+
+	name = g_hash_table_lookup (lang_code_names, code);
+	if (!name) {
+		return NULL;
+	}
+
+	return dgettext ("iso_639", name);
+}
+
+const char *
+get_country_iso_code (const char *code)
+{
+	const gchar *name;
+
+	if (!country_code_names) {
+		country_code_names = iso_code_names_init (&countryLookup);
+	}
+
+	name = g_hash_table_lookup (country_code_names, code);
+	if (!name) {
+		return NULL;
+	}
+
+	return dgettext ("iso_3166", name);
+}

Modified: trunk/capplets/keyboard/gnome-keyboard-properties-xkb.h
==============================================================================
--- trunk/capplets/keyboard/gnome-keyboard-properties-xkb.h	(original)
+++ trunk/capplets/keyboard/gnome-keyboard-properties-xkb.h	Sun Apr 27 15:13:32 2008
@@ -50,13 +50,13 @@
 
 extern void xkb_options_load_options (GladeXML * dialog);
 
-extern void xkb_options_popup_dialog(GladeXML * dialog);
+extern void xkb_options_popup_dialog (GladeXML * dialog);
 
 extern void clear_xkb_elements_list (GSList * list);
 
 extern char *xci_desc_to_utf8 (XklConfigItem * ci);
 
-extern gchar *xkb_layout_description_utf8 (const gchar *visible);
+extern gchar *xkb_layout_description_utf8 (const gchar * visible);
 
 extern void enable_disable_restoring (GladeXML * dialog);
 
@@ -88,8 +88,8 @@
 
 extern void xkb_layout_preview_update (GladeXML * chooser_dialog);
 
-extern void xkb_layout_preview_set_drawing_layout (GtkWidget   *kbdraw,
-                                                   const gchar *id);
+extern void xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw,
+						   const gchar * id);
 
 extern gchar *xkb_layout_chooser_get_selected_id (GladeXML *
 						  chooser_dialog);

Modified: trunk/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c
==============================================================================
--- trunk/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c	(original)
+++ trunk/capplets/keyboard/gnome-keyboard-properties-xkbltadd.c	Sun Apr 27 15:13:32 2008
@@ -40,78 +40,148 @@
 #define DEFAULT_GROUP_SWITCH "grp:alts_toggle"
 #define DEFAULT_VARIANT_ID "__default__"
 
+#define LANG_THRESHOLD_1 15
+#define LANG_THRESHOLD_2 5
+
 enum {
 	COMBO_BOX_MODEL_COL_DESCRIPTION,
-	COMBO_BOX_MODEL_COL_ID,
-	COMBO_BOX_MODEL_COL_IS_DEFAULT
+	COMBO_BOX_MODEL_COL_XKB_ID,
+	COMBO_BOX_MODEL_COL_REAL_ID,
+	COMBO_BOX_MODEL_COL_COUNTER
 };
 
+typedef void (*LayoutIterFunc) (XklConfigRegistry * config,
+				ConfigItemProcessFunc func, gpointer data);
+
 typedef struct {
 	GtkListStore *list_store;
-	guint n_items;
+	const gchar *lang_id;
 } AddVariantData;
 
 static void
- xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog);
-
-static void
- xkb_layout_chooser_available_variants_fill (GladeXML * chooser_dialog);
-
-static void
-xkb_layout_chooser_add_variant_to_available_variants (XklConfigRegistry *
-						      config_registry,
-						      XklConfigItem *
-						      config_item,
-						      AddVariantData *
-						      data)
-{
-	char *utf_variant_name = xci_desc_to_utf8 (config_item);
+ xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog,
+					    const gchar cblid[],
+					    const gchar cbvid[],
+					    LayoutIterFunc layout_iterator,
+					    ConfigItemProcessFunc
+					    layout_handler,
+					    gint sort_column_id,
+					    GtkTreeIterCompareFunc
+					    sort_func,
+					    GCallback
+					    combo_changed_notify);
+
+static void
+ xkb_layout_chooser_available_language_variants_fill (GladeXML *
+						      chooser_dialog);
+
+static void
+ xkb_layout_chooser_available_country_variants_fill (GladeXML *
+						     chooser_dialog);
+
+static void
+ xkb_layout_chooser_add_variant_to_available_country_variants
+    (XklConfigRegistry * config_registry,
+     XklConfigItem * parent_config_item, XklConfigItem * config_item,
+     AddVariantData * data) {
+	gchar *utf_variant_name = config_item ?
+	    xkb_layout_description_utf8 (gkbd_keyboard_config_merge_items
+					 (parent_config_item->name,
+					  config_item->name)) :
+	    xci_desc_to_utf8 (parent_config_item);
 	GtkTreeIter iter;
+	const gchar *xkb_id =
+	    config_item ?
+	    gkbd_keyboard_config_merge_items (parent_config_item->name,
+					      config_item->
+					      name) : parent_config_item->
+	    name;
 
 	gtk_list_store_insert_with_values (data->list_store, &iter, -1,
 					   COMBO_BOX_MODEL_COL_DESCRIPTION,
 					   utf_variant_name,
-					   COMBO_BOX_MODEL_COL_ID,
-					   config_item->name,
-					   COMBO_BOX_MODEL_COL_IS_DEFAULT,
-					   FALSE, -1);
+					   COMBO_BOX_MODEL_COL_XKB_ID,
+					   xkb_id, -1);
 	g_free (utf_variant_name);
+}
 
-	data->n_items++;
+static void
+ xkb_layout_chooser_add_variant_to_available_language_variants
+    (XklConfigRegistry * config_registry,
+     XklConfigItem * parent_config_item, XklConfigItem * config_item,
+     AddVariantData * data) {
+	xkb_layout_chooser_add_variant_to_available_country_variants
+	    (config_registry, parent_config_item, config_item, data);
 }
 
 static void
-xkb_layout_chooser_add_layout_to_available_layouts (XklConfigRegistry *
-						    config_registry,
-						    XklConfigItem *
-						    config_item,
-						    GtkListStore *
-						    list_store)
-{
-	char *utf_layout_name = xci_desc_to_utf8 (config_item);
-	GtkTreeIter iter;
+inc_counter (XklConfigRegistry * config_registry, XklConfigItem *
+	     layout, XklConfigItem * variant, gint * counter)
+{
+	(*counter)++;
+}
+
+static void
+xkb_layout_chooser_add_language_to_available_languages (XklConfigRegistry *
+							config_registry,
+							XklConfigItem *
+							config_item,
+							GtkListStore *
+							list_store)
+{
+	gint counter = 0;
+	gchar *descr;
+	gchar *size;
+	xkl_config_registry_foreach_language_variant
+	    (config_registry, config_item->name,
+	     (TwoConfigItemsProcessFunc)
+	     inc_counter, &counter);
+	size =
+	    counter > LANG_THRESHOLD_1 ? "x-large" : counter >
+	    LANG_THRESHOLD_2 ? "large" : "medium";
+	descr =
+	    g_strdup_printf ("<span size=\"%s\">%s</span>", size,
+			     config_item->description);
+	gtk_list_store_insert_with_values (list_store, NULL, -1,
+					   COMBO_BOX_MODEL_COL_DESCRIPTION,
+					   descr,
+					   COMBO_BOX_MODEL_COL_REAL_ID,
+					   config_item->name,
+					   COMBO_BOX_MODEL_COL_COUNTER,
+					   counter, -1);
+	g_free (descr);
+}
 
-	gtk_list_store_insert_with_values (list_store, &iter, -1,
+static void
+xkb_layout_chooser_add_country_to_available_countries (XklConfigRegistry *
+						       config_registry,
+						       XklConfigItem *
+						       config_item,
+						       GtkListStore *
+						       list_store)
+{
+	gtk_list_store_insert_with_values (list_store, NULL, -1,
 					   COMBO_BOX_MODEL_COL_DESCRIPTION,
-					   utf_layout_name,
-					   COMBO_BOX_MODEL_COL_ID,
+					   config_item->description,
+					   COMBO_BOX_MODEL_COL_REAL_ID,
 					   config_item->name, -1);
-	g_free (utf_layout_name);
 }
 
 static void
 xkb_layout_chooser_enable_disable_buttons (GladeXML * chooser_dialog)
 {
-	GtkWidget *cbel = CWID ("xkb_layouts_available");
-	GtkWidget *cbev = CWID ("xkb_variants_available");
-	GtkTreeIter liter, viter;
-	gboolean enable_ok =
-	    gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbel), &liter)
-	    && gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbev),
+	GtkWidget *cbv =
+	    CWID (gtk_notebook_get_current_page
+		  (GTK_NOTEBOOK (CWID ("choosers_nb"))) ?
+		  "xkb_language_variants_available" :
+		  "xkb_country_variants_available");
+	GtkTreeIter viter;
+	gboolean enable_ok = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbv),
 					      &viter);
 
 	gtk_dialog_set_response_sensitive (GTK_DIALOG
-					   (CWID ("xkb_layout_chooser")),
+					   (CWID
+					    ("xkb_layout_chooser")),
 					   GTK_RESPONSE_OK, enable_ok);
 	gtk_widget_set_sensitive (CWID ("btnPrint"), enable_ok);
 }
@@ -124,12 +194,70 @@
 }
 
 static void
-xkb_layout_chooser_available_layout_changed (GladeXML * chooser_dialog)
+xkb_layout_chooser_available_language_changed (GladeXML * chooser_dialog)
 {
-	xkb_layout_chooser_available_variants_fill (chooser_dialog);
+	xkb_layout_chooser_available_language_variants_fill
+	    (chooser_dialog);
 	xkb_layout_chooser_available_variant_changed (chooser_dialog);
 }
 
+static void
+xkb_layout_chooser_available_country_changed (GladeXML * chooser_dialog)
+{
+	xkb_layout_chooser_available_country_variants_fill
+	    (chooser_dialog);
+	xkb_layout_chooser_available_variant_changed (chooser_dialog);
+}
+
+static void
+xkb_layout_chooser_page_changed (GtkWidget* notebook, GtkWidget * page, gint page_num, GladeXML * chooser_dialog)
+{
+	xkb_layout_chooser_available_variant_changed (chooser_dialog);
+}
+
+static gint
+xkb_layout_chooser_language_compare_func (GtkTreeModel * model,
+					  GtkTreeIter * a,
+					  GtkTreeIter * b,
+					  gpointer user_data)
+{
+	gchar *desc_a = NULL, *desc_b = NULL;
+	gint a_cnt = 0, b_cnt = 0;
+	gint retval;
+
+	gtk_tree_model_get (model, a,
+			    COMBO_BOX_MODEL_COL_DESCRIPTION,
+			    &desc_a,
+			    COMBO_BOX_MODEL_COL_COUNTER, &a_cnt, -1);
+	gtk_tree_model_get (model, b,
+			    COMBO_BOX_MODEL_COL_DESCRIPTION,
+			    &desc_b,
+			    COMBO_BOX_MODEL_COL_COUNTER, &b_cnt, -1);
+	/* Compare languages, using scopes 0-5, 6-15, 16-... */
+	if ((a_cnt > LANG_THRESHOLD_1 && b_cnt <= LANG_THRESHOLD_1)
+	    || (a_cnt > LANG_THRESHOLD_2 && b_cnt <= LANG_THRESHOLD_2))
+		retval = -1;
+	else if ((a_cnt <= LANG_THRESHOLD_1 && b_cnt > LANG_THRESHOLD_1)
+		 || (a_cnt <= LANG_THRESHOLD_2
+		     && b_cnt > LANG_THRESHOLD_2))
+		retval = 1;
+	else if (desc_a != NULL && desc_b != NULL)
+		retval = g_utf8_collate (desc_a, desc_b);
+	else if (desc_a != NULL)
+		/* desc_b == NULL hence b is the separator, and a is not the default => b < a */
+		retval = 1;
+	else if (desc_b != NULL)
+		/* desc_a == NULL hence a is the separator, and b is not the default => a < b */
+		retval = -1;
+	else
+		retval = 0;
+
+	g_free (desc_a);
+	g_free (desc_b);
+
+	return retval;
+}
+
 static gint
 xkb_layout_chooser_variant_compare_func (GtkTreeModel * model,
 					 GtkTreeIter * a,
@@ -137,21 +265,14 @@
 					 gpointer user_data)
 {
 	gchar *desc_a = NULL, *desc_b = NULL;
-	gboolean a_is_default, b_is_default;
 	gint retval;
 
 	gtk_tree_model_get (model, a,
-			    COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_a,
-			    COMBO_BOX_MODEL_COL_IS_DEFAULT, &a_is_default,
-			    -1);
+			    COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_a, -1);
 	gtk_tree_model_get (model, b,
-			    COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_b,
-			    COMBO_BOX_MODEL_COL_IS_DEFAULT, &b_is_default,
-			    -1);
+			    COMBO_BOX_MODEL_COL_DESCRIPTION, &desc_b, -1);
 
-	if (a_is_default || b_is_default)
-		retval = b_is_default - a_is_default;
-	else if (desc_a != NULL && desc_b != NULL)
+	if (desc_a != NULL && desc_b != NULL)
 		retval = g_utf8_collate (desc_a, desc_b);
 	else if (desc_a != NULL)
 		/* desc_b == NULL hence b is the separator, and a is not the default => b < a */
@@ -168,136 +289,163 @@
 	return retval;
 }
 
-static gboolean
-xkl_layout_chooser_separate_default_variant (GtkTreeModel * model,
-					     GtkTreeIter * iter,
-					     GladeXML * chooser_dialog)
+static void
+xkb_layout_chooser_available_language_variants_fill (GladeXML *
+						     chooser_dialog)
 {
-	gchar *id;
+	GtkWidget *cbl = CWID ("xkb_languages_available");
+	GtkWidget *cbv = CWID ("xkb_language_variants_available");
+	GtkListStore *list_store;
+	GtkTreeIter liter;
+
+	list_store = gtk_list_store_new
+	    (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
+
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbl), &liter)) {
+		GtkTreeModel *lm =
+		    gtk_combo_box_get_model (GTK_COMBO_BOX (cbl));
+		gchar *lang_id;
+		AddVariantData data = { list_store, 0 };
 
-	/* Rows with COMBO_BOX_MODEL_COL_DESCRIPTION value NULL are separators */
-	gtk_tree_model_get (model, iter, COMBO_BOX_MODEL_COL_DESCRIPTION,
-			    &id, -1);
-	g_free (id);
+		/* Now the variants of the selected layout */
+		gtk_tree_model_get (lm, &liter,
+				    COMBO_BOX_MODEL_COL_REAL_ID,
+				    &lang_id, -1);
+		data.lang_id = lang_id;
+
+		xkl_config_registry_foreach_language_variant
+		    (config_registry, lang_id, (TwoConfigItemsProcessFunc)
+		     xkb_layout_chooser_add_variant_to_available_language_variants,
+		     &data);
+		g_free (lang_id);
+	}
 
-	return id == NULL;
+	/* Turn on sorting after filling the store, since that's faster */
+	gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list_store),
+					 COMBO_BOX_MODEL_COL_DESCRIPTION,
+					 (GtkTreeIterCompareFunc)
+					 xkb_layout_chooser_variant_compare_func,
+					 NULL, NULL);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE
+					      (list_store),
+					      COMBO_BOX_MODEL_COL_DESCRIPTION,
+					      GTK_SORT_ASCENDING);
+
+	gtk_combo_box_set_model (GTK_COMBO_BOX (cbv),
+				 GTK_TREE_MODEL (list_store));
+
+	/* Select the default variant */
+	/* TODO
+	   if (set_default) {
+	   gtk_combo_box_set_active_iter (GTK_COMBO_BOX
+	   (cbev), &vdefault_iter);
+	   }
+	 */
 }
 
 static void
-xkb_layout_chooser_available_variants_fill (GladeXML * chooser_dialog)
+xkb_layout_chooser_available_country_variants_fill (GladeXML *
+						    chooser_dialog)
 {
-	GtkWidget *cbel = CWID ("xkb_layouts_available");
-	GtkWidget *cbev = CWID ("xkb_variants_available");
-	GtkTreeModel *model =
-	    gtk_combo_box_get_model (GTK_COMBO_BOX (cbev));
+	GtkWidget *cbl = CWID ("xkb_countries_available");
+	GtkWidget *cbv = CWID ("xkb_country_variants_available");
+	GtkListStore *list_store;
 	GtkTreeIter liter, vdefault_iter;
 	gboolean set_default = FALSE;
 
-	model = GTK_TREE_MODEL (gtk_list_store_new
-				(3, G_TYPE_STRING, G_TYPE_STRING,
-				 G_TYPE_BOOLEAN));
+	list_store = gtk_list_store_new
+	    (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
 
-	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbel), &liter)) {
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbl), &liter)) {
 		GtkTreeModel *lm =
-		    gtk_combo_box_get_model (GTK_COMBO_BOX (cbel));
-		GtkTreeIter viter;
-		gchar *value;
-		AddVariantData data = { GTK_LIST_STORE (model), 0 };
-
-		/* The 'Default' row */
-		gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
-						   &vdefault_iter, -1,
-						   COMBO_BOX_MODEL_COL_DESCRIPTION,
-						   _("Default"),
-						   COMBO_BOX_MODEL_COL_ID,
-						   DEFAULT_VARIANT_ID,
-						   COMBO_BOX_MODEL_COL_IS_DEFAULT,
-						   TRUE, -1);
-		set_default = TRUE;
+		    gtk_combo_box_get_model (GTK_COMBO_BOX (cbl));
+		gchar *country_id;
+		AddVariantData data = { list_store, 0 };
 
-		/* Now the variants of the selected lang */
+		/* Now the variants of the selected layout */
 		gtk_tree_model_get (lm, &liter,
-				    COMBO_BOX_MODEL_COL_ID, &value, -1);
-		g_assert (value != NULL);
-
-		xkl_config_registry_foreach_layout_variant
-		    (config_registry, value, (ConfigItemProcessFunc)
-		     xkb_layout_chooser_add_variant_to_available_variants,
+				    COMBO_BOX_MODEL_COL_REAL_ID,
+				    &country_id, -1);
+		xkl_config_registry_foreach_country_variant
+		    (config_registry, country_id,
+		     (TwoConfigItemsProcessFunc)
+		     xkb_layout_chooser_add_variant_to_available_country_variants,
 		     &data);
-		g_free (value);
-
-		/* Add a separator row, but only if we have any non-default items */
-		if (data.n_items > 0)
-			gtk_list_store_insert_with_values (GTK_LIST_STORE
-							   (model), &viter,
-							   -1,
-							   COMBO_BOX_MODEL_COL_DESCRIPTION,
-							   NULL,
-							   COMBO_BOX_MODEL_COL_ID,
-							   NULL,
-							   COMBO_BOX_MODEL_COL_IS_DEFAULT,
-							   FALSE, -1);
+		g_free (country_id);
 	}
 
 	/* Turn on sorting after filling the store, since that's faster */
-	gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model),
+	gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (list_store),
 					 COMBO_BOX_MODEL_COL_DESCRIPTION,
 					 (GtkTreeIterCompareFunc)
 					 xkb_layout_chooser_variant_compare_func,
 					 NULL, NULL);
-	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE
+					      (list_store),
 					      COMBO_BOX_MODEL_COL_DESCRIPTION,
 					      GTK_SORT_ASCENDING);
 
-	gtk_combo_box_set_model (GTK_COMBO_BOX (cbev), model);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (cbv),
+				 GTK_TREE_MODEL (list_store));
 
 	/* Select the default variant */
 	if (set_default) {
-		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (cbev),
-					       &vdefault_iter);
+		gtk_combo_box_set_active_iter (GTK_COMBO_BOX
+					       (cbv), &vdefault_iter);
 	}
 }
 
 static void
-xkb_layout_chooser_available_layouts_fill (GladeXML * chooser_dialog)
+xkb_layout_chooser_available_layouts_fill (GladeXML *
+					   chooser_dialog,
+					   const gchar cblid[],
+					   const gchar cbvid[],
+					   LayoutIterFunc layout_iterator,
+					   ConfigItemProcessFunc
+					   layout_handler,
+					   gint sort_column_id,
+					   GtkTreeIterCompareFunc
+					   sort_func,
+					   GCallback combo_changed_notify)
 {
-	GtkWidget *cbe = CWID ("xkb_layouts_available");
-	GtkWidget *cbev = CWID ("xkb_variants_available");
+	GtkWidget *cbl = CWID (cblid);
+	GtkWidget *cbev = CWID (cbvid);
 	GtkCellRenderer *renderer;
-	GtkTreeModel *model =
-	    GTK_TREE_MODEL (gtk_list_store_new
-			    (2, G_TYPE_STRING, G_TYPE_STRING));
+	GtkListStore *list_store =
+	    gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING,
+				G_TYPE_STRING, G_TYPE_INT);
 
-	gtk_combo_box_set_model (GTK_COMBO_BOX (cbe), model);
+	gtk_combo_box_set_model (GTK_COMBO_BOX (cbl),
+				 GTK_TREE_MODEL (list_store));
 
 	renderer = gtk_cell_renderer_text_new ();
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbe), renderer, TRUE);
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbe), renderer,
-					"text",
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbl), renderer, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbl),
+					renderer, "markup",
 					COMBO_BOX_MODEL_COL_DESCRIPTION,
 					NULL);
 
-	xkl_config_registry_foreach_layout (config_registry,
-					    (ConfigItemProcessFunc)
-					    xkb_layout_chooser_add_layout_to_available_layouts,
-					    model);
+	layout_iterator (config_registry, layout_handler, list_store);
 
 	/* Turn on sorting after filling the model since that's faster */
-	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-					      COMBO_BOX_MODEL_COL_DESCRIPTION,
+	if (sort_func)
+		gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE
+						 (list_store),
+						 sort_column_id, sort_func,
+						 NULL, NULL);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE
+					      (list_store), sort_column_id,
 					      GTK_SORT_ASCENDING);
 
-	g_signal_connect_swapped (G_OBJECT (cbe), "changed",
-				  G_CALLBACK
-				  (xkb_layout_chooser_available_layout_changed),
-				  chooser_dialog);
+	g_signal_connect_swapped (G_OBJECT (cbl), "changed",
+				  combo_changed_notify, chooser_dialog);
 
 	/* Setup the variants combo */
 	renderer = gtk_cell_renderer_text_new ();
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbev), renderer,
-				    TRUE);
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbev), renderer,
-					"text",
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cbev),
+				    renderer, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cbev),
+					renderer, "markup",
 					COMBO_BOX_MODEL_COL_DESCRIPTION,
 					NULL);
 
@@ -305,10 +453,6 @@
 				  G_CALLBACK
 				  (xkb_layout_chooser_available_variant_changed),
 				  chooser_dialog);
-	gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (cbev),
-					      (GtkTreeViewRowSeparatorFunc)
-					      xkl_layout_chooser_separate_default_variant,
-					      chooser_dialog, NULL);
 }
 
 void
@@ -364,7 +508,8 @@
 	const char *id =
 	    xkb_layout_chooser_get_selected_id (chooser_dialog);
 	char *descr = xkb_layout_description_utf8 (id);
-	gkbd_keyboard_drawing_print (GKBD_KEYBOARD_DRAWING (kbdraw),
+	gkbd_keyboard_drawing_print (GKBD_KEYBOARD_DRAWING
+				     (kbdraw),
 				     GTK_WINDOW (CWID
 						 ("xkb_layout_chooser")),
 				     descr);
@@ -424,20 +569,47 @@
 				      GTK_WINDOW (WID
 						  ("keyboard_dialog")));
 
-	xkb_layout_chooser_available_layouts_fill (chooser_dialog);
-	xkb_layout_chooser_available_layout_changed (chooser_dialog);
+	xkb_layout_chooser_available_layouts_fill (chooser_dialog,
+						   "xkb_countries_available",
+						   "xkb_country_variants_available",
+						   xkl_config_registry_foreach_country,
+						   (ConfigItemProcessFunc)
+						   xkb_layout_chooser_add_country_to_available_countries,
+						   COMBO_BOX_MODEL_COL_DESCRIPTION,
+						   NULL,
+						   G_CALLBACK
+						   (xkb_layout_chooser_available_country_changed));
+	xkb_layout_chooser_available_layouts_fill (chooser_dialog,
+						   "xkb_languages_available",
+						   "xkb_language_variants_available",
+						   xkl_config_registry_foreach_language,
+						   (ConfigItemProcessFunc)
+						   xkb_layout_chooser_add_language_to_available_languages,
+						   COMBO_BOX_MODEL_COL_COUNTER,
+						   xkb_layout_chooser_language_compare_func,
+						   G_CALLBACK
+						   (xkb_layout_chooser_available_language_changed));
+
+	g_signal_connect_after (G_OBJECT (CWID("choosers_nb")), "switch_page",
+				  G_CALLBACK
+				  (xkb_layout_chooser_page_changed),
+				  chooser_dialog);
+
+	xkb_layout_chooser_available_country_changed (chooser_dialog);
+	xkb_layout_chooser_available_language_changed (chooser_dialog);
 
 #ifdef HAVE_X11_EXTENSIONS_XKB_H
 	if (!strcmp (xkl_engine_get_backend_name (engine), "XKB")) {
 		kbdraw = xkb_layout_preview_create_widget (chooser_dialog);
 		g_object_set_data (G_OBJECT (chooser), "kbdraw", kbdraw);
-		gtk_container_add (GTK_CONTAINER (CWID ("previewFrame")),
-				   kbdraw);
+		gtk_container_add (GTK_CONTAINER
+				   (CWID ("previewFrame")), kbdraw);
 		gtk_widget_show_all (kbdraw);
 		gtk_button_box_set_child_secondary (GTK_BUTTON_BOX
-						    (CWID ("hbtnBox")),
-						    CWID ("btnPrint"),
-						    TRUE);
+						    (CWID
+						     ("hbtnBox")),
+						    CWID
+						    ("btnPrint"), TRUE);
 	} else
 #endif
 	{
@@ -454,8 +626,8 @@
 	if (GTK_WIDGET_TOPLEVEL (toplevel)) {
 		GdkRectangle *rect = gkbd_preview_load_position ();
 		if (rect != NULL) {
-			gtk_window_move (GTK_WINDOW (toplevel), rect->x,
-					 rect->y);
+			gtk_window_move (GTK_WINDOW (toplevel),
+					 rect->x, rect->y);
 			gtk_window_resize (GTK_WINDOW (toplevel),
 					   rect->width, rect->height);
 			g_free (rect);
@@ -469,34 +641,20 @@
 gchar *
 xkb_layout_chooser_get_selected_id (GladeXML * chooser_dialog)
 {
-	GtkWidget *cbel = CWID ("xkb_layouts_available");
-	GtkWidget *cbev = CWID ("xkb_variants_available");
-	GtkTreeModel *lm = gtk_combo_box_get_model (GTK_COMBO_BOX (cbel));
-	GtkTreeModel *vm = gtk_combo_box_get_model (GTK_COMBO_BOX (cbev));
-	GtkTreeIter liter, viter;
-	gchar *lname, *vname;
-	gchar *retval;
-
-	if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbel), &liter)
-	    || !gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbev),
-					       &viter))
-		return NULL;
+	GtkWidget *cbv =
+	    CWID (gtk_notebook_get_current_page
+		  (GTK_NOTEBOOK (CWID ("choosers_nb"))) ?
+		  "xkb_language_variants_available" :
+		  "xkb_country_variants_available");
+	GtkTreeModel *vm = gtk_combo_box_get_model (GTK_COMBO_BOX (cbv));
+	GtkTreeIter viter;
+	gchar *v_id;
 
-	gtk_tree_model_get (lm, &liter,
-			    COMBO_BOX_MODEL_COL_ID, &lname, -1);
+	if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (cbv), &viter))
+		return NULL;
 
 	gtk_tree_model_get (vm, &viter,
-			    COMBO_BOX_MODEL_COL_ID, &vname, -1);
-
-	if (strcmp (vname, DEFAULT_VARIANT_ID))
-		retval =
-		    g_strdup (gkbd_keyboard_config_merge_items
-			      (lname, vname));
-	else
-		retval = g_strdup (lname);
+			    COMBO_BOX_MODEL_COL_XKB_ID, &v_id, -1);
 
-	g_free (lname);
-	g_free (vname);
-
-	return retval;
+	return v_id;
 }

Modified: trunk/capplets/keyboard/gnome-keyboard-properties-xkbpv.c
==============================================================================
--- trunk/capplets/keyboard/gnome-keyboard-properties-xkbpv.c	(original)
+++ trunk/capplets/keyboard/gnome-keyboard-properties-xkbpv.c	Sun Apr 27 15:13:32 2008
@@ -81,50 +81,59 @@
 }
 
 void
-xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw, const gchar * id)
+xkb_layout_preview_set_drawing_layout (GtkWidget * kbdraw,
+				       const gchar * id)
 {
 #ifdef HAVE_X11_EXTENSIONS_XKB_H
-	if (kbdraw != NULL && id != NULL) {
-		XklConfigRec *data;
-		char **p, *layout, *variant;
-		XkbComponentNamesRec component_names;
-
-		data = xkl_config_rec_new ();
-		if (xkl_config_rec_get_from_server (data, engine)) {
-			if ((p = data->layouts) != NULL)
-				g_strfreev (data->layouts);
-
-			if ((p = data->variants) != NULL)
-				g_strfreev (data->variants);
-
-			data->layouts = g_new0 (char *, 2);
-			data->variants = g_new0 (char *, 2);
-			if (gkbd_keyboard_config_split_items
-			    (id, &layout, &variant)
-			    && variant != NULL) {
-				data->layouts[0] =
-				    (layout ==
-				     NULL) ? NULL : g_strdup (layout);
-				data->variants[0] =
-				    (variant ==
-				     NULL) ? NULL : g_strdup (variant);
-			} else {
-				data->layouts[0] =
-				    (id == NULL) ? NULL : g_strdup (id);
-				data->variants[0] = NULL;
+	if (kbdraw != NULL) {
+		if (id != NULL) {
+			XklConfigRec *data;
+			char **p, *layout, *variant;
+			XkbComponentNamesRec component_names;
+
+			data = xkl_config_rec_new ();
+			if (xkl_config_rec_get_from_server (data, engine)) {
+				if ((p = data->layouts) != NULL)
+					g_strfreev (data->layouts);
+
+				if ((p = data->variants) != NULL)
+					g_strfreev (data->variants);
+
+				data->layouts = g_new0 (char *, 2);
+				data->variants = g_new0 (char *, 2);
+				if (gkbd_keyboard_config_split_items
+				    (id, &layout, &variant)
+				    && variant != NULL) {
+					data->layouts[0] =
+					    (layout ==
+					     NULL) ? NULL :
+					    g_strdup (layout);
+					data->variants[0] =
+					    (variant ==
+					     NULL) ? NULL :
+					    g_strdup (variant);
+				} else {
+					data->layouts[0] =
+					    (id ==
+					     NULL) ? NULL : g_strdup (id);
+					data->variants[0] = NULL;
+				}
+
+				if (xkl_xkb_config_native_prepare
+				    (engine, data, &component_names)) {
+					gkbd_keyboard_drawing_set_keyboard
+					    (GKBD_KEYBOARD_DRAWING
+					     (kbdraw), &component_names);
+
+					xkl_xkb_config_native_cleanup
+					    (engine, &component_names);
+				}
 			}
+			g_object_unref (G_OBJECT (data));
+		} else
+			gkbd_keyboard_drawing_set_keyboard
+			    (GKBD_KEYBOARD_DRAWING (kbdraw), NULL);
 
-			if (xkl_xkb_config_native_prepare
-			    (engine, data, &component_names)) {
-				gkbd_keyboard_drawing_set_keyboard
-				    (GKBD_KEYBOARD_DRAWING (kbdraw),
-				     &component_names);
-
-				xkl_xkb_config_native_cleanup (engine,
-							       &component_names);
-			}
-		}
-		g_object_unref (G_OBJECT (data));
 	}
 #endif
 }

Modified: trunk/capplets/keyboard/gnome-keyboard-properties.glade
==============================================================================
--- trunk/capplets/keyboard/gnome-keyboard-properties.glade	(original)
+++ trunk/capplets/keyboard/gnome-keyboard-properties.glade	Sun Apr 27 15:13:32 2008
@@ -1714,67 +1714,179 @@
             <property name="border_width">5</property>
             <property name="spacing">6</property>
             <child>
-              <widget class="GtkTable" id="table1">
+              <widget class="GtkNotebook" id="choosers_nb">
                 <property name="visible">True</property>
-                <property name="n_rows">2</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">12</property>
-                <property name="row_spacing">6</property>
+                <property name="can_focus">True</property>
                 <child>
-                  <widget class="GtkLabel" id="label3">
+                  <widget class="GtkAlignment" id="alignment1">
                     <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Layouts:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">xkb_layouts_available</property>
+                    <property name="top_padding">6</property>
+                    <property name="bottom_padding">6</property>
+                    <property name="left_padding">6</property>
+                    <property name="right_padding">6</property>
+                    <child>
+                      <widget class="GtkTable" id="table1">
+                        <property name="visible">True</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">12</property>
+                        <property name="row_spacing">6</property>
+                        <child>
+                          <widget class="GtkComboBox" id="xkb_country_variants_available">
+                            <property name="visible">True</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkComboBox" id="xkb_countries_available">
+                            <property name="visible">True</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label4">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Variants:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">xkb_country_variants_available</property>
+                          </widget>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label3">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Country:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">xkb_countries_available</property>
+                          </widget>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
                   </widget>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
                 </child>
                 <child>
-                  <widget class="GtkLabel" id="label4">
+                  <widget class="GtkLabel" id="label22">
                     <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Variants:</property>
+                    <property name="label" translatable="yes">By _country</property>
                     <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">xkb_variants_available</property>
                   </widget>
                   <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
+                    <property name="type">tab</property>
+                    <property name="tab_fill">False</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="GtkComboBox" id="xkb_layouts_available">
+                  <widget class="GtkAlignment" id="alignment2">
                     <property name="visible">True</property>
+                    <property name="top_padding">6</property>
+                    <property name="bottom_padding">6</property>
+                    <property name="left_padding">6</property>
+                    <property name="right_padding">6</property>
+                    <child>
+                      <widget class="GtkTable" id="table3">
+                        <property name="visible">True</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">12</property>
+                        <property name="row_spacing">6</property>
+                        <child>
+                          <widget class="GtkComboBox" id="xkb_language_variants_available">
+                            <property name="visible">True</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkComboBox" id="xkb_languages_available">
+                            <property name="visible">True</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label13">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Variants:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">xkb_country_variants_available</property>
+                          </widget>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label12">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Language:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">xkb_countries_available</property>
+                          </widget>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
                   </widget>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="position">1</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="GtkComboBox" id="xkb_variants_available">
+                  <widget class="GtkLabel" id="label9">
                     <property name="visible">True</property>
+                    <property name="label" translatable="yes">By _language</property>
+                    <property name="use_underline">True</property>
                   </widget>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="type">tab</property>
+                    <property name="position">1</property>
+                    <property name="tab_fill">False</property>
                   </packing>
                 </child>
               </widget>
               <packing>
                 <property name="expand">False</property>
+                <property name="fill">False</property>
               </packing>
             </child>
             <child>



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