summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@jhu.edu>2007-09-18 22:05:38 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2007-09-18 22:05:38 +0000
commitb795ca868483ef8a19a85d17b9b193150724a85d (patch)
tree3ab1b35dfad619fb26853b583c56cbb6592da0db
parent50803f76e340468dc4a3b4ff7fd7740e5fe62ce9 (diff)
downloadgdm-b795ca868483ef8a19a85d17b9b193150724a85d.tar.gz
First shot at a language chooser widget that uses locale archives and
2007-09-18 William Jon McCann <mccann@jhu.edu> * configure.ac: * gui/simple-greeter/Makefile.am: * gui/simple-greeter/gdm-language-chooser-dialog.c: (gdm_language_chooser_dialog_get_current_language_name), (gdm_language_chooser_dialog_set_property), (gdm_language_chooser_dialog_get_property), (gdm_language_chooser_dialog_constructor), (gdm_language_chooser_dialog_dispose), (gdm_language_chooser_dialog_class_init), (on_response), (gdm_language_chooser_dialog_init), (gdm_language_chooser_dialog_finalize), (gdm_language_chooser_dialog_new): * gui/simple-greeter/gdm-language-chooser-dialog.h: * gui/simple-greeter/gdm-language-chooser-widget.c: (chooser_locale_free), (gdm_language_chooser_widget_get_current_language_name), (gdm_language_chooser_widget_set_property), (gdm_language_chooser_widget_get_property), (gdm_language_chooser_widget_constructor), (gdm_language_chooser_widget_dispose), (gdm_language_chooser_widget_class_init), (on_language_selected), (locale_exists), (utf8_convert), (get_lc_identification), (get_short_name_for_locale), (parse_short_name), (nameentcmp), (collect_locales_from_archive), (select_dirs), (collect_locales_from_directory), (collect_locales_from_aliases), (collect_locales), (on_row_activated), (get_translated_language), (get_language), (get_territory), (get_translated_territory), (languages_parse_start_tag), (territories_parse_start_tag), (languages_init), (territories_init), (add_locale_to_model), (populate_model), (gdm_language_chooser_widget_init), (gdm_language_chooser_widget_finalize), (gdm_language_chooser_widget_new): * gui/simple-greeter/gdm-language-chooser-widget.h: * gui/simple-greeter/langinfo.h: * gui/simple-greeter/libnotificationarea/Makefile.am: * gui/simple-greeter/locarchive.h: * gui/simple-greeter/test-language-chooser.c: (main): First shot at a language chooser widget that uses locale archives and iso-codes. svn path=/branches/mccann-gobject/; revision=5283
-rw-r--r--ChangeLog42
-rw-r--r--configure.ac15
-rw-r--r--gui/simple-greeter/Makefile.am21
-rw-r--r--gui/simple-greeter/gdm-language-chooser-dialog.c197
-rw-r--r--gui/simple-greeter/gdm-language-chooser-dialog.h57
-rw-r--r--gui/simple-greeter/gdm-language-chooser-widget.c1050
-rw-r--r--gui/simple-greeter/gdm-language-chooser-widget.h59
-rw-r--r--gui/simple-greeter/langinfo.h598
-rw-r--r--gui/simple-greeter/libnotificationarea/Makefile.am2
-rw-r--r--gui/simple-greeter/locarchive.h97
-rw-r--r--gui/simple-greeter/test-language-chooser.c59
11 files changed, 2188 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f9bf45b..d92af6ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2007-09-18 William Jon McCann <mccann@jhu.edu>
+
+ * configure.ac:
+ * gui/simple-greeter/Makefile.am:
+ * gui/simple-greeter/gdm-language-chooser-dialog.c:
+ (gdm_language_chooser_dialog_get_current_language_name),
+ (gdm_language_chooser_dialog_set_property),
+ (gdm_language_chooser_dialog_get_property),
+ (gdm_language_chooser_dialog_constructor),
+ (gdm_language_chooser_dialog_dispose),
+ (gdm_language_chooser_dialog_class_init), (on_response),
+ (gdm_language_chooser_dialog_init),
+ (gdm_language_chooser_dialog_finalize),
+ (gdm_language_chooser_dialog_new):
+ * gui/simple-greeter/gdm-language-chooser-dialog.h:
+ * gui/simple-greeter/gdm-language-chooser-widget.c:
+ (chooser_locale_free),
+ (gdm_language_chooser_widget_get_current_language_name),
+ (gdm_language_chooser_widget_set_property),
+ (gdm_language_chooser_widget_get_property),
+ (gdm_language_chooser_widget_constructor),
+ (gdm_language_chooser_widget_dispose),
+ (gdm_language_chooser_widget_class_init), (on_language_selected),
+ (locale_exists), (utf8_convert), (get_lc_identification),
+ (get_short_name_for_locale), (parse_short_name), (nameentcmp),
+ (collect_locales_from_archive), (select_dirs),
+ (collect_locales_from_directory), (collect_locales_from_aliases),
+ (collect_locales), (on_row_activated), (get_translated_language),
+ (get_language), (get_territory), (get_translated_territory),
+ (languages_parse_start_tag), (territories_parse_start_tag),
+ (languages_init), (territories_init), (add_locale_to_model),
+ (populate_model), (gdm_language_chooser_widget_init),
+ (gdm_language_chooser_widget_finalize),
+ (gdm_language_chooser_widget_new):
+ * gui/simple-greeter/gdm-language-chooser-widget.h:
+ * gui/simple-greeter/langinfo.h:
+ * gui/simple-greeter/libnotificationarea/Makefile.am:
+ * gui/simple-greeter/locarchive.h:
+ * gui/simple-greeter/test-language-chooser.c: (main):
+ First shot at a language chooser widget that uses locale
+ archives and iso-codes.
+
2007-09-13 William Jon McCann <mccann@jhu.edu>
* gui/simple-greeter/Makefile.am:
diff --git a/configure.ac b/configure.ac
index 0a14b7da..6f0b2acc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -677,7 +677,7 @@ if test "x$XINPUT_LIBS" = x; then
done
if test "x$XINPUT_LIBS" = x; then
AC_MSG_ERROR(Couldn't find the XInput library. Check config.log for details)
- fi
+ fi
fi
AC_CHECK_HEADER(X11/extensions/XInput.h, have_xinput=yes)
if test "x$have_xinput" = xyes; then
@@ -852,6 +852,18 @@ else
fi
AC_SUBST(DBUS_SYS_DIR)
+dnl ---------------------------------------------------------------------------
+dnl - ISO Codes checks
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether iso-codes has iso-639 domain])
+if $PKG_CONFIG --variable=domains iso-codes | grep 639 >/dev/null ; then
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix])
+ISO_CODES=iso-codes
#
# Define some variables to represent the directories we use.
@@ -1307,7 +1319,6 @@ gui/Makefile
gui/modules/Makefile
gui/simple-greeter/Makefile
gui/simple-greeter/libnotificationarea/Makefile
-gui/simple-greeter/libbackground/Makefile
gui/simple-chooser/Makefile
utils/Makefile
data/Makefile
diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am
index e6714a01..acc6d207 100644
--- a/gui/simple-greeter/Makefile.am
+++ b/gui/simple-greeter/Makefile.am
@@ -8,17 +8,13 @@ INCLUDES = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/libgreeter \
-I$(top_srcdir)/gui/simple-greeter/libnotificationarea \
- -DAUTHDIR=\""$(authdir)"\" \
+ -DGDMCONFDIR=\"$(gdmconfdir)\" \
-DDATADIR=\""$(datadir)"\" \
- -DGDMCONFDIR=\"$(gdmconfdir)\" \
- -DDMCONFDIR=\""$(dmconfdir)"\" \
- -DGDM_CONFIG_FILE=\"$(gdmconfdir)/gdm.conf\" \
- -DGDMLOCALEDIR=\""$(gdmlocaledir)"\" \
+ -DLIBLOCALEDIR=\""$(libdir)/locale"\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGLADEDIR=\""$(pkgdatadir)"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
-DSBINDIR=\""$(sbindir)"\" \
- -DPIXMAPDIR=\""$(pixmapdir)"\" \
$(GUI_CFLAGS) \
$(DBUS_CFLAGS) \
$(GREETER_CFLAGS) \
@@ -28,6 +24,7 @@ INCLUDES = \
noinst_PROGRAMS = \
test-greeter-background \
test-greeter-panel \
+ test-language-chooser \
$(NULL)
test_greeter_background_SOURCES = \
@@ -52,6 +49,18 @@ test_greeter_panel_LDADD = \
$(GUI_LIBS) \
$(NULL)
+test_language_chooser_SOURCES = \
+ test-language-chooser.c \
+ gdm-language-chooser-widget.h \
+ gdm-language-chooser-widget.c \
+ gdm-language-chooser-dialog.h \
+ gdm-language-chooser-dialog.c \
+ $(NULL)
+
+test_language_chooser_LDADD = \
+ $(GUI_LIBS) \
+ $(NULL)
+
libexec_PROGRAMS = \
gdm-simple-greeter
diff --git a/gui/simple-greeter/gdm-language-chooser-dialog.c b/gui/simple-greeter/gdm-language-chooser-dialog.c
new file mode 100644
index 00000000..1f5cdc4d
--- /dev/null
+++ b/gui/simple-greeter/gdm-language-chooser-dialog.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gdm-language-chooser-widget.h"
+#include "gdm-language-chooser-dialog.h"
+
+#define GDM_LANGUAGE_CHOOSER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LANGUAGE_CHOOSER_DIALOG, GdmLanguageChooserDialogPrivate))
+
+struct GdmLanguageChooserDialogPrivate
+{
+ GtkWidget *chooser_widget;
+};
+
+enum {
+ PROP_0,
+};
+
+static void gdm_language_chooser_dialog_class_init (GdmLanguageChooserDialogClass *klass);
+static void gdm_language_chooser_dialog_init (GdmLanguageChooserDialog *language_chooser_dialog);
+static void gdm_language_chooser_dialog_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmLanguageChooserDialog, gdm_language_chooser_dialog, GTK_TYPE_DIALOG)
+
+char *
+gdm_language_chooser_dialog_get_current_language_name (GdmLanguageChooserDialog *dialog)
+{
+ char *language_name;
+
+ g_return_val_if_fail (GDM_IS_LANGUAGE_CHOOSER_DIALOG (dialog), NULL);
+
+ language_name = gdm_language_chooser_widget_get_current_language_name (GDM_LANGUAGE_CHOOSER_WIDGET (dialog->priv->chooser_widget));
+
+ return language_name;
+}
+
+static void
+gdm_language_chooser_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmLanguageChooserDialog *self;
+
+ self = GDM_LANGUAGE_CHOOSER_DIALOG (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_language_chooser_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmLanguageChooserDialog *self;
+
+ self = GDM_LANGUAGE_CHOOSER_DIALOG (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_language_chooser_dialog_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmLanguageChooserDialog *language_chooser_dialog;
+ GdmLanguageChooserDialogClass *klass;
+
+ klass = GDM_LANGUAGE_CHOOSER_DIALOG_CLASS (g_type_class_peek (GDM_TYPE_LANGUAGE_CHOOSER_DIALOG));
+
+ language_chooser_dialog = GDM_LANGUAGE_CHOOSER_DIALOG (G_OBJECT_CLASS (gdm_language_chooser_dialog_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (language_chooser_dialog);
+}
+
+static void
+gdm_language_chooser_dialog_dispose (GObject *object)
+{
+ GdmLanguageChooserDialog *language_chooser_dialog;
+
+ language_chooser_dialog = GDM_LANGUAGE_CHOOSER_DIALOG (object);
+
+ g_debug ("Disposing language_chooser_dialog");
+
+ G_OBJECT_CLASS (gdm_language_chooser_dialog_parent_class)->dispose (object);
+}
+
+static void
+gdm_language_chooser_dialog_class_init (GdmLanguageChooserDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_language_chooser_dialog_get_property;
+ object_class->set_property = gdm_language_chooser_dialog_set_property;
+ object_class->constructor = gdm_language_chooser_dialog_constructor;
+ object_class->dispose = gdm_language_chooser_dialog_dispose;
+ object_class->finalize = gdm_language_chooser_dialog_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmLanguageChooserDialogPrivate));
+}
+
+static void
+on_response (GdmLanguageChooserDialog *dialog,
+ gint response_id)
+{
+ switch (response_id) {
+ default:
+ break;
+ }
+}
+
+static void
+gdm_language_chooser_dialog_init (GdmLanguageChooserDialog *dialog)
+{
+
+ dialog->priv = GDM_LANGUAGE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
+
+ dialog->priv->chooser_widget = gdm_language_chooser_widget_new ();
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), dialog->priv->chooser_widget);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (on_response),
+ dialog);
+
+ gtk_widget_show_all (GTK_WIDGET (dialog));
+}
+
+static void
+gdm_language_chooser_dialog_finalize (GObject *object)
+{
+ GdmLanguageChooserDialog *language_chooser_dialog;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_LANGUAGE_CHOOSER_DIALOG (object));
+
+ language_chooser_dialog = GDM_LANGUAGE_CHOOSER_DIALOG (object);
+
+ g_return_if_fail (language_chooser_dialog->priv != NULL);
+
+ G_OBJECT_CLASS (gdm_language_chooser_dialog_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gdm_language_chooser_dialog_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_LANGUAGE_CHOOSER_DIALOG,
+ NULL);
+
+ return GTK_WIDGET (object);
+}
diff --git a/gui/simple-greeter/gdm-language-chooser-dialog.h b/gui/simple-greeter/gdm-language-chooser-dialog.h
new file mode 100644
index 00000000..c0221eb0
--- /dev/null
+++ b/gui/simple-greeter/gdm-language-chooser-dialog.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GDM_LANGUAGE_CHOOSER_DIALOG_H
+#define __GDM_LANGUAGE_CHOOSER_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtkdialog.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_LANGUAGE_CHOOSER_DIALOG (gdm_language_chooser_dialog_get_type ())
+#define GDM_LANGUAGE_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_LANGUAGE_CHOOSER_DIALOG, GdmLanguageChooserDialog))
+#define GDM_LANGUAGE_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_LANGUAGE_CHOOSER_DIALOG, GdmLanguageChooserDialogClass))
+#define GDM_IS_LANGUAGE_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_LANGUAGE_CHOOSER_DIALOG))
+#define GDM_IS_LANGUAGE_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_LANGUAGE_CHOOSER_DIALOG))
+#define GDM_LANGUAGE_CHOOSER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_LANGUAGE_CHOOSER_DIALOG, GdmLanguageChooserDialogClass))
+
+typedef struct GdmLanguageChooserDialogPrivate GdmLanguageChooserDialogPrivate;
+
+typedef struct
+{
+ GtkDialog parent;
+ GdmLanguageChooserDialogPrivate *priv;
+} GdmLanguageChooserDialog;
+
+typedef struct
+{
+ GtkDialogClass parent_class;
+} GdmLanguageChooserDialogClass;
+
+GType gdm_language_chooser_dialog_get_type (void);
+
+GtkWidget * gdm_language_chooser_dialog_new (void);
+
+char * gdm_language_chooser_dialog_get_current_language_name (GdmLanguageChooserDialog *dialog);
+
+G_END_DECLS
+
+#endif /* __GDM_LANGUAGE_CHOOSER_DIALOG_H */
diff --git a/gui/simple-greeter/gdm-language-chooser-widget.c b/gui/simple-greeter/gdm-language-chooser-widget.c
new file mode 100644
index 00000000..1c28ce36
--- /dev/null
+++ b/gui/simple-greeter/gdm-language-chooser-widget.c
@@ -0,0 +1,1050 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 1998, 1999, 2000 Martin K, Petersen <mkp@mkp.net>
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include "gdm-language-chooser-widget.h"
+
+#include "langinfo.h"
+#ifndef __LC_LAST
+#define __LC_LAST 13
+#endif
+#include "locarchive.h"
+
+#define ALIASES_FILE LIBLOCALEDIR "/locale.alias"
+#define ARCHIVE_FILE LIBLOCALEDIR "/locale-archive"
+#define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
+#define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
+
+#define GDM_LANGUAGE_CHOOSER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LANGUAGE_CHOOSER_WIDGET, GdmLanguageChooserWidgetPrivate))
+
+typedef struct _GdmChooserLocale {
+ char *name;
+ char *language_code;
+ char *territory_code;
+ char *title;
+ char *language;
+ char *territory;
+} GdmChooserLocale;
+
+struct GdmLanguageChooserWidgetPrivate
+{
+ GtkWidget *treeview;
+
+ GHashTable *languages;
+ GHashTable *territories;
+ GHashTable *available_locales;
+
+ GdmChooserLocale *current_locale;
+};
+
+enum {
+ PROP_0,
+};
+
+enum {
+ LANGUAGE_ACTIVATED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gdm_language_chooser_widget_class_init (GdmLanguageChooserWidgetClass *klass);
+static void gdm_language_chooser_widget_init (GdmLanguageChooserWidget *language_chooser_widget);
+static void gdm_language_chooser_widget_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmLanguageChooserWidget, gdm_language_chooser_widget, GTK_TYPE_VBOX)
+
+enum {
+ CHOOSER_LIST_TITLE_COLUMN = 0,
+ CHOOSER_LIST_TRANSLATED_COLUMN,
+ CHOOSER_LIST_LOCALE_COLUMN
+};
+
+static void
+chooser_locale_free (GdmChooserLocale *locale)
+{
+ if (locale == NULL) {
+ return;
+ }
+
+ g_free (locale->name);
+ g_free (locale->title);
+ g_free (locale->language);
+ g_free (locale->territory);
+ g_free (locale);
+}
+
+char *
+gdm_language_chooser_widget_get_current_language_name (GdmLanguageChooserWidget *widget)
+{
+ char *language_name;
+
+ g_return_val_if_fail (GDM_IS_LANGUAGE_CHOOSER_WIDGET (widget), NULL);
+
+ language_name = NULL;
+ if (widget->priv->current_locale != NULL) {
+
+ }
+
+ return language_name;
+}
+
+static void
+gdm_language_chooser_widget_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmLanguageChooserWidget *self;
+
+ self = GDM_LANGUAGE_CHOOSER_WIDGET (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_language_chooser_widget_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmLanguageChooserWidget *self;
+
+ self = GDM_LANGUAGE_CHOOSER_WIDGET (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_language_chooser_widget_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmLanguageChooserWidget *language_chooser_widget;
+ GdmLanguageChooserWidgetClass *klass;
+
+ klass = GDM_LANGUAGE_CHOOSER_WIDGET_CLASS (g_type_class_peek (GDM_TYPE_LANGUAGE_CHOOSER_WIDGET));
+
+ language_chooser_widget = GDM_LANGUAGE_CHOOSER_WIDGET (G_OBJECT_CLASS (gdm_language_chooser_widget_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (language_chooser_widget);
+}
+
+static void
+gdm_language_chooser_widget_dispose (GObject *object)
+{
+ GdmLanguageChooserWidget *widget;
+
+ widget = GDM_LANGUAGE_CHOOSER_WIDGET (object);
+
+ if (widget->priv->languages != NULL) {
+ g_hash_table_destroy (widget->priv->languages);
+ widget->priv->languages = NULL;
+ }
+
+ if (widget->priv->territories != NULL) {
+ g_hash_table_destroy (widget->priv->territories);
+ widget->priv->territories = NULL;
+ }
+
+ if (widget->priv->available_locales != NULL) {
+ g_hash_table_destroy (widget->priv->available_locales);
+ widget->priv->available_locales = NULL;
+ }
+
+ widget->priv->current_locale = NULL;
+
+ G_OBJECT_CLASS (gdm_language_chooser_widget_parent_class)->dispose (object);
+}
+
+static void
+gdm_language_chooser_widget_class_init (GdmLanguageChooserWidgetClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_language_chooser_widget_get_property;
+ object_class->set_property = gdm_language_chooser_widget_set_property;
+ object_class->constructor = gdm_language_chooser_widget_constructor;
+ object_class->dispose = gdm_language_chooser_widget_dispose;
+ object_class->finalize = gdm_language_chooser_widget_finalize;
+
+ signals [LANGUAGE_ACTIVATED] = g_signal_new ("language-activated",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdmLanguageChooserWidgetClass, language_activated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_type_class_add_private (klass, sizeof (GdmLanguageChooserWidgetPrivate));
+}
+
+static void
+on_language_selected (GtkTreeSelection *selection,
+ GdmLanguageChooserWidget *widget)
+{
+ GtkTreeModel *model = NULL;
+ GtkTreeIter iter = {0};
+ GdmChooserLocale *locale;
+
+ locale = NULL;
+
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ gtk_tree_model_get (model, &iter, CHOOSER_LIST_LOCALE_COLUMN, &locale, -1);
+ }
+
+ widget->priv->current_locale = locale;
+}
+
+static gboolean
+locale_exists (const char *loc)
+{
+ gboolean ret;
+ char *old;
+
+ old = g_strdup (setlocale (LC_MESSAGES, NULL));
+ if (setlocale (LC_MESSAGES, loc) != NULL) {
+ ret = TRUE;
+ } else {
+ ret = FALSE;
+ }
+
+ setlocale (LC_MESSAGES, old);
+ g_free (old);
+
+ return ret;
+}
+
+static char *
+utf8_convert (const char *str,
+ int len)
+{
+ char *utf8;
+
+ utf8 = g_locale_to_utf8 (str, len, NULL, NULL, NULL);
+
+ /* if we couldn't convert text from locale then
+ * assume utf-8 and hope for the best */
+ if (utf8 == NULL) {
+ char *p;
+ char *q;
+
+ if (len < 0) {
+ utf8 = g_strdup (str);
+ } else {
+ utf8 = g_strndup (str, len);
+ }
+
+ p = utf8;
+ while (*p != '\0' && !g_utf8_validate ((const char *)p, -1, (const char **)&q)) {
+ *q = '?';
+ p = q + 1;
+ }
+ }
+
+ return utf8;
+}
+
+/* Magic number at the beginning of a locale data file for CATEGORY. */
+#define LIMAGIC(category) \
+ (category == LC_COLLATE \
+ ? ((unsigned int) (0x20051014 ^ (category))) \
+ : ((unsigned int) (0x20031115 ^ (category))))
+
+static void
+get_lc_identification (GdmChooserLocale *locale,
+ void *data,
+ gsize size)
+{
+ struct {
+ unsigned int magic;
+ unsigned int nstrings;
+ unsigned int strindex[0];
+ } *filedata = data;
+
+ if (filedata->magic == LIMAGIC (LC_IDENTIFICATION)
+ && (sizeof *filedata + (filedata->nstrings * sizeof (unsigned int)) <= size)) {
+
+#define GET_HANDLE(idx) ((char *) data + filedata->strindex[_NL_ITEM_INDEX (_NL_IDENTIFICATION_##idx)])
+
+ locale->title = utf8_convert (GET_HANDLE (TITLE), -1);
+ locale->language = utf8_convert (GET_HANDLE (LANGUAGE), -1);
+ locale->territory = utf8_convert (GET_HANDLE (TERRITORY), -1);
+ }
+}
+
+static char *
+get_short_name_for_locale (const char *name)
+{
+ char *short_name;
+ char *p;
+
+ p = strrchr (name, '.');
+ if (p != NULL) {
+ short_name = utf8_convert (name, p - name);
+ } else {
+ short_name = utf8_convert (name, -1);
+ }
+
+ return short_name;
+}
+
+static void
+parse_short_name (const char *short_name,
+ char **language_codep,
+ char **territory_codep)
+{
+ static GRegex *re;
+ GMatchInfo *match_info;
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+ re = g_regex_new ("([a-zA-Z]+)(_([a-zA-Z]+))?", 0, 0, &error);
+ if (re == NULL) {
+ g_critical (error->message);
+ }
+
+ g_regex_match (re, short_name, 0, &match_info);
+
+ res = g_match_info_matches (match_info);
+ if (! res) {
+ g_warning ("Unable to parse locale: %s", short_name);
+ return;
+ }
+
+ if (language_codep != NULL) {
+ *language_codep = g_match_info_fetch (match_info, 1);
+ }
+
+ if (territory_codep != NULL) {
+ *territory_codep = g_match_info_fetch (match_info, 3);
+ }
+
+ g_match_info_free (match_info);
+ g_regex_unref (re);
+}
+
+struct nameent
+{
+ char *name;
+ uint32_t locrec_offset;
+};
+
+static int
+nameentcmp (const void *a, const void *b)
+{
+ return strcoll (((const struct nameent *) a)->name,
+ ((const struct nameent *) b)->name);
+}
+
+static void
+collect_locales_from_archive (GdmLanguageChooserWidget *widget)
+{
+ GMappedFile *mapped;
+ GError *error;
+ char *addr;
+ struct locarhead *head;
+ struct namehashent *namehashtab;
+ struct nameent *names;
+ uint32_t used;
+ uint32_t cnt;
+ gsize len;
+
+ error = NULL;
+ mapped = g_mapped_file_new (ARCHIVE_FILE, FALSE, &error);
+ if (mapped == NULL) {
+ g_warning ("Mapping failed for %s: %s", ARCHIVE_FILE, error->message);
+ g_error_free (error);
+ return;
+ }
+
+ addr = g_mapped_file_get_contents (mapped);
+ len = g_mapped_file_get_length (mapped);
+
+ head = (struct locarhead *) addr;
+ if (head->namehash_offset + head->namehash_size > len
+ || head->string_offset + head->string_size > len
+ || head->locrectab_offset + head->locrectab_size > len
+ || head->sumhash_offset + head->sumhash_size > len) {
+ goto out;
+ }
+
+ namehashtab = (struct namehashent *) (addr + head->namehash_offset);
+
+ names = (struct nameent *) g_new0 (struct nameent, head->namehash_used);
+ for (cnt = used = 0; cnt < head->namehash_size; ++cnt) {
+ if (namehashtab[cnt].locrec_offset != 0) {
+ names[used].name = addr + namehashtab[cnt].name_offset;
+ names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
+ }
+ }
+
+ /* Sort the names. */
+ qsort (names, used, sizeof (struct nameent), nameentcmp);
+
+ for (cnt = 0; cnt < used; ++cnt) {
+ struct locrecent *locrec;
+ char *short_name;
+ GdmChooserLocale *locale;
+
+ short_name = get_short_name_for_locale (names[cnt].name);
+
+ if (g_hash_table_lookup (widget->priv->available_locales, short_name) != NULL) {
+ g_free (short_name);
+ continue;
+ }
+
+ locale = g_new0 (GdmChooserLocale, 1);
+ locale->name = short_name;
+
+ parse_short_name (short_name, &locale->language_code, &locale->territory_code);
+
+ locrec = (struct locrecent *) (addr + names[cnt].locrec_offset);
+
+ get_lc_identification (locale,
+ addr + locrec->record[LC_IDENTIFICATION].offset,
+ locrec->record[LC_IDENTIFICATION].len);
+
+ g_hash_table_insert (widget->priv->available_locales, g_strdup (short_name), locale);
+ }
+
+ g_free (names);
+
+ out:
+
+ g_mapped_file_free (mapped);
+}
+
+static int
+select_dirs (const struct dirent *dirent)
+{
+ int result = 0;
+
+ if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) {
+ mode_t mode = 0;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) {
+ mode = DTTOIF (dirent->d_type);
+ } else
+#endif
+ {
+ struct stat st;
+ char *path;
+
+ path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL);
+ if (g_stat (path, &st) == 0) {
+ mode = st.st_mode;
+ }
+ g_free (path);
+ }
+
+ result = S_ISDIR (mode);
+ }
+
+ return result;
+}
+
+static void
+collect_locales_from_directory (GdmLanguageChooserWidget *widget)
+{
+ struct dirent **dirents;
+ int ndirents;
+ int cnt;
+
+ ndirents = scandir (LIBLOCALEDIR, &dirents, select_dirs, alphasort);
+
+ for (cnt = 0; cnt < ndirents; ++cnt) {
+ char *path;
+ char *short_name;
+ GdmChooserLocale *locale;
+ gboolean res;
+
+ /* first find short name */
+ short_name = get_short_name_for_locale (dirents[cnt]->d_name);
+
+ if (g_hash_table_lookup (widget->priv->available_locales, short_name) != NULL) {
+ g_free (short_name);
+ continue;
+ }
+
+ locale = g_new0 (GdmChooserLocale, 1);
+ locale->name = short_name;
+
+ parse_short_name (short_name, &locale->language_code, &locale->territory_code);
+
+ /* try to get additional information from LC_IDENTIFICATION */
+ path = g_build_filename (LIBLOCALEDIR, dirents[cnt]->d_name, "LC_IDENTIFICATION", NULL);
+ res = g_file_test (path, G_FILE_TEST_IS_REGULAR);
+ if (res) {
+ GMappedFile *mapped;
+ GError *error;
+
+ error = NULL;
+ mapped = g_mapped_file_new (path, FALSE, &error);
+ if (mapped == NULL) {
+ g_warning ("Mapping failed for %s: %s", path, error->message);
+ g_error_free (error);
+ } else {
+ get_lc_identification (locale,
+ g_mapped_file_get_contents (mapped),
+ g_mapped_file_get_length (mapped));
+ g_mapped_file_free (mapped);
+ }
+ }
+ g_free (path);
+
+ g_hash_table_insert (widget->priv->available_locales, g_strdup (short_name), locale);
+ }
+
+ if (ndirents > 0) {
+ free (dirents);
+ }
+}
+
+static void
+collect_locales_from_aliases (GdmLanguageChooserWidget *widget)
+{
+ /* FIXME: */
+}
+
+static void
+collect_locales (GdmLanguageChooserWidget *widget)
+{
+ collect_locales_from_archive (widget);
+ collect_locales_from_directory (widget);
+ collect_locales_from_aliases (widget);
+}
+
+
+static void
+on_row_activated (GtkTreeView *tree_view,
+ GtkTreePath *tree_path,
+ GtkTreeViewColumn *tree_column,
+ GdmLanguageChooserWidget *widget)
+{
+ g_signal_emit (widget, signals[LANGUAGE_ACTIVATED], 0);
+}
+
+static const char *
+get_translated_language (GdmLanguageChooserWidget *widget,
+ const char *code)
+{
+ const char *name;
+ int len;
+
+ g_assert (code != NULL);
+
+ len = strlen (code);
+ if (len != 2 && len != 3) {
+ return NULL;
+ }
+
+ name = (const char *) g_hash_table_lookup (widget->priv->languages, code);
+
+ if (name != NULL) {
+ return dgettext ("iso_639", name);
+ }
+
+ return NULL;
+}
+
+static const char *
+get_language (GdmLanguageChooserWidget *widget,
+ const char *code)
+{
+ const char *name;
+ int len;
+
+ g_assert (code != NULL);
+
+ len = strlen (code);
+ if (len != 2 && len != 3) {
+ return NULL;
+ }
+
+ name = (const char *) g_hash_table_lookup (widget->priv->languages, code);
+
+ return name;
+}
+
+static const char *
+get_territory (GdmLanguageChooserWidget *widget,
+ const char *code)
+{
+ const char *name;
+ int len;
+
+ g_assert (code != NULL);
+
+ len = strlen (code);
+ if (len != 2 && len != 3) {
+ return NULL;
+ }
+
+ name = (const char *) g_hash_table_lookup (widget->priv->territories, code);
+
+ return name;
+}
+
+static const char *
+get_translated_territory (GdmLanguageChooserWidget *widget,
+ const char *code)
+{
+ const char *name;
+ int len;
+
+ g_assert (code != NULL);
+
+ len = strlen (code);
+ if (len != 2 && len != 3) {
+ return NULL;
+ }
+
+ name = (const char *) g_hash_table_lookup (widget->priv->territories, code);
+
+ if (name != NULL) {
+ return dgettext ("iso_3166", name);
+ }
+
+ return NULL;
+}
+
+static void
+languages_parse_start_tag (GMarkupParseContext *ctx,
+ const char *element_name,
+ const char **attr_names,
+ const char **attr_values,
+ GdmLanguageChooserWidget *widget,
+ GError **error)
+{
+ const char *ccode_longB;
+ const char *ccode_longT;
+ const char *ccode;
+ const char *lang_name;
+
+ if (! g_str_equal (element_name, "iso_639_entry") || attr_names == NULL || attr_values == NULL) {
+ return;
+ }
+
+ ccode = NULL;
+ ccode_longB = NULL;
+ ccode_longT = NULL;
+ lang_name = NULL;
+
+ while (*attr_names && *attr_values) {
+ if (g_str_equal (*attr_names, "iso_639_1_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 2) {
+ return;
+ }
+ ccode = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "iso_639_2B_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ ccode_longB = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "iso_639_2T_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ ccode_longT = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "name")) {
+ lang_name = *attr_values;
+ }
+
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (lang_name == NULL) {
+ return;
+ }
+
+ if (ccode != NULL) {
+ g_hash_table_insert (widget->priv->languages,
+ g_strdup (ccode),
+ g_strdup (lang_name));
+ }
+ if (ccode_longB != NULL) {
+ g_hash_table_insert (widget->priv->languages,
+ g_strdup (ccode_longB),
+ g_strdup (lang_name));
+ }
+ if (ccode_longT != NULL) {
+ g_hash_table_insert (widget->priv->languages,
+ g_strdup (ccode_longT),
+ g_strdup (lang_name));
+ }
+}
+
+static void
+territories_parse_start_tag (GMarkupParseContext *ctx,
+ const char *element_name,
+ const char **attr_names,
+ const char **attr_values,
+ GdmLanguageChooserWidget *widget,
+ GError **error)
+{
+ const char *acode_2;
+ const char *acode_3;
+ const char *ncode;
+ const char *territory_name;
+
+ if (! g_str_equal (element_name, "iso_3166_entry") || attr_names == NULL || attr_values == NULL) {
+ return;
+ }
+
+ acode_2 = NULL;
+ acode_3 = NULL;
+ ncode = NULL;
+ territory_name = NULL;
+
+ while (*attr_names && *attr_values) {
+ if (g_str_equal (*attr_names, "alpha_2_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 2) {
+ return;
+ }
+ acode_2 = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "alpha_3_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ acode_3 = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "numeric_code")) {
+ /* skip if empty */
+ if (**attr_values) {
+ if (strlen (*attr_values) != 3) {
+ return;
+ }
+ ncode = *attr_values;
+ }
+ } else if (g_str_equal (*attr_names, "name")) {
+ territory_name = *attr_values;
+ }
+
+ ++attr_names;
+ ++attr_values;
+ }
+
+ if (territory_name == NULL) {
+ return;
+ }
+
+ if (acode_2 != NULL) {
+ g_hash_table_insert (widget->priv->territories,
+ g_strdup (acode_2),
+ g_strdup (territory_name));
+ }
+ if (acode_3 != NULL) {
+ g_hash_table_insert (widget->priv->territories,
+ g_strdup (acode_3),
+ g_strdup (territory_name));
+ }
+ if (ncode != NULL) {
+ g_hash_table_insert (widget->priv->territories,
+ g_strdup (ncode),
+ g_strdup (territory_name));
+ }
+}
+
+static void
+languages_init (GdmLanguageChooserWidget *widget)
+{
+ GError *error;
+ gboolean res;
+ char *buf;
+ gsize buf_len;
+
+ bindtextdomain ("iso_639", ISO_CODES_LOCALESDIR);
+ bind_textdomain_codeset ("iso_639", "UTF-8");
+
+ widget->priv->languages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ error = NULL;
+ res = g_file_get_contents (ISO_CODES_DATADIR "/iso_639.xml",
+ &buf,
+ &buf_len,
+ &error);
+ if (res) {
+ GMarkupParseContext *ctx;
+ GMarkupParser parser = { languages_parse_start_tag, NULL, NULL, NULL, NULL };
+
+ ctx = g_markup_parse_context_new (&parser, 0, widget, NULL);
+
+ error = NULL;
+ res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+ if (! res) {
+ g_warning ("Failed to parse '%s': %s\n",
+ ISO_CODES_DATADIR "/iso_639.xml",
+ error->message);
+ g_error_free (error);
+ }
+
+ g_markup_parse_context_free (ctx);
+ g_free (buf);
+ } else {
+ g_warning ("Failed to load '%s': %s\n",
+ ISO_CODES_DATADIR "/iso_639.xml",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+territories_init (GdmLanguageChooserWidget *widget)
+{
+ GError *error;
+ gboolean res;
+ char *buf;
+ gsize buf_len;
+
+ bindtextdomain ("iso_3166", ISO_CODES_LOCALESDIR);
+ bind_textdomain_codeset ("iso_3166", "UTF-8");
+
+ widget->priv->territories = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ error = NULL;
+ res = g_file_get_contents (ISO_CODES_DATADIR "/iso_3166.xml",
+ &buf,
+ &buf_len,
+ &error);
+ if (res) {
+ GMarkupParseContext *ctx;
+ GMarkupParser parser = { territories_parse_start_tag, NULL, NULL, NULL, NULL };
+
+ ctx = g_markup_parse_context_new (&parser, 0, widget, NULL);
+
+ error = NULL;
+ res = g_markup_parse_context_parse (ctx, buf, buf_len, &error);
+
+ if (! res) {
+ g_warning ("Failed to parse '%s': %s\n",
+ ISO_CODES_DATADIR "/iso_3166.xml",
+ error->message);
+ g_error_free (error);
+ }
+
+ g_markup_parse_context_free (ctx);
+ g_free (buf);
+ } else {
+ g_warning ("Failed to load '%s': %s\n",
+ ISO_CODES_DATADIR "/iso_3166.xml",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+add_locale_to_model (const char *name,
+ GdmChooserLocale *locale,
+ GdmLanguageChooserWidget *widget)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *title;
+ char *translated;
+ const char *lang;
+ const char *translated_lang;
+
+ lang = get_language (widget, locale->language_code);
+ translated_lang = get_translated_language (widget, locale->language_code);
+
+#if 0
+ g_debug ("adding to model: %s title='%s' language='%s' territory='%s' language_code='%s' territory_code='%s'",
+ locale->name,
+ locale->title,
+ locale->language,
+ locale->territory,
+ locale->language_code,
+ locale->territory_code);
+#endif
+
+ if (locale->territory_code == NULL || locale->territory_code[0] == '\0') {
+ title = g_strdup_printf ("%s",
+ lang ? lang : locale->language);
+ translated = g_strdup_printf ("%s",
+ translated_lang ? lang : locale->language);
+ } else {
+ const char *terr;
+ const char *translated_terr;
+
+ terr = get_territory (widget, locale->territory_code);
+ translated_terr = get_translated_territory (widget, locale->territory_code);
+
+ title = g_strdup_printf ("%s (%s)",
+ lang ? lang : locale->language,
+ terr);
+ translated = g_strdup_printf ("%s (%s)",
+ translated_lang ? lang : locale->language,
+ translated_terr);
+ }
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget->priv->treeview));
+
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ CHOOSER_LIST_TITLE_COLUMN, title,
+ CHOOSER_LIST_TRANSLATED_COLUMN, translated,
+ CHOOSER_LIST_LOCALE_COLUMN, locale,
+ -1);
+ g_free (title);
+ g_free (translated);
+}
+
+static void
+populate_model (GdmLanguageChooserWidget *widget)
+{
+ g_hash_table_foreach (widget->priv->available_locales,
+ (GHFunc)add_locale_to_model,
+ widget);
+}
+
+static void
+gdm_language_chooser_widget_init (GdmLanguageChooserWidget *widget)
+{
+ GtkWidget *scrolled;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkTreeModel *model;
+
+ widget->priv = GDM_LANGUAGE_CHOOSER_WIDGET_GET_PRIVATE (widget);
+
+ widget->priv->available_locales = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)chooser_locale_free);
+
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (widget), scrolled, TRUE, TRUE, 0);
+
+ widget->priv->treeview = gtk_tree_view_new ();
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget->priv->treeview), FALSE);
+ g_signal_connect (widget->priv->treeview,
+ "row-activated",
+ G_CALLBACK (on_row_activated),
+ widget);
+ gtk_container_add (GTK_CONTAINER (scrolled), widget->priv->treeview);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (on_language_selected),
+ widget);
+
+ model = (GtkTreeModel *)gtk_list_store_new (3,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (widget->priv->treeview), model);
+
+ column = gtk_tree_view_column_new_with_attributes ("Language",
+ gtk_cell_renderer_text_new (),
+ "markup", CHOOSER_LIST_TITLE_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->treeview), column);
+
+ column = gtk_tree_view_column_new_with_attributes ("Translated Language",
+ gtk_cell_renderer_text_new (),
+ "markup", CHOOSER_LIST_TRANSLATED_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->treeview), column);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+ CHOOSER_LIST_TITLE_COLUMN,
+ GTK_SORT_ASCENDING);
+
+ collect_locales (widget);
+ languages_init (widget);
+ territories_init (widget);
+
+ populate_model (widget);
+}
+
+static void
+gdm_language_chooser_widget_finalize (GObject *object)
+{
+ GdmLanguageChooserWidget *language_chooser_widget;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_LANGUAGE_CHOOSER_WIDGET (object));
+
+ language_chooser_widget = GDM_LANGUAGE_CHOOSER_WIDGET (object);
+
+ g_return_if_fail (language_chooser_widget->priv != NULL);
+
+ G_OBJECT_CLASS (gdm_language_chooser_widget_parent_class)->finalize (object);
+}
+
+GtkWidget *
+gdm_language_chooser_widget_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_LANGUAGE_CHOOSER_WIDGET,
+ NULL);
+
+ return GTK_WIDGET (object);
+}
diff --git a/gui/simple-greeter/gdm-language-chooser-widget.h b/gui/simple-greeter/gdm-language-chooser-widget.h
new file mode 100644
index 00000000..6879ca99
--- /dev/null
+++ b/gui/simple-greeter/gdm-language-chooser-widget.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GDM_LANGUAGE_CHOOSER_WIDGET_H
+#define __GDM_LANGUAGE_CHOOSER_WIDGET_H
+
+#include <glib-object.h>
+#include <gtk/gtkvbox.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_LANGUAGE_CHOOSER_WIDGET (gdm_language_chooser_widget_get_type ())
+#define GDM_LANGUAGE_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_LANGUAGE_CHOOSER_WIDGET, GdmLanguageChooserWidget))
+#define GDM_LANGUAGE_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_LANGUAGE_CHOOSER_WIDGET, GdmLanguageChooserWidgetClass))
+#define GDM_IS_LANGUAGE_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_LANGUAGE_CHOOSER_WIDGET))
+#define GDM_IS_LANGUAGE_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_LANGUAGE_CHOOSER_WIDGET))
+#define GDM_LANGUAGE_CHOOSER_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_LANGUAGE_CHOOSER_WIDGET, GdmLanguageChooserWidgetClass))
+
+typedef struct GdmLanguageChooserWidgetPrivate GdmLanguageChooserWidgetPrivate;
+
+typedef struct
+{
+ GtkVBox parent;
+ GdmLanguageChooserWidgetPrivate *priv;
+} GdmLanguageChooserWidget;
+
+typedef struct
+{
+ GtkVBoxClass parent_class;
+
+ /* signals */
+ void (* language_activated) (GdmLanguageChooserWidget *widget);
+} GdmLanguageChooserWidgetClass;
+
+GType gdm_language_chooser_widget_get_type (void);
+GtkWidget * gdm_language_chooser_widget_new (void);
+
+char * gdm_language_chooser_widget_get_current_language_name (GdmLanguageChooserWidget *widget);
+
+G_END_DECLS
+
+#endif /* __GDM_LANGUAGE_CHOOSER_WIDGET_H */
diff --git a/gui/simple-greeter/langinfo.h b/gui/simple-greeter/langinfo.h
new file mode 100644
index 00000000..10c42329
--- /dev/null
+++ b/gui/simple-greeter/langinfo.h
@@ -0,0 +1,598 @@
+/* Access to locale-dependent parameters.
+ Copyright (C) 1995-2002,2003,2004,2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LANGINFO_H
+#define _LANGINFO_H 1
+
+/* Get the type definition. */
+#include <nl_types.h>
+
+#include <bits/locale.h> /* Define the __LC_* category names. */
+
+
+__BEGIN_DECLS
+
+/* Construct an `nl_item' value for `nl_langinfo' from a locale category
+ (LC_*) and an item index within the category. Some code may depend on
+ the item values within a category increasing monotonically with the
+ indices. */
+#define _NL_ITEM(category, index) (((category) << 16) | (index))
+
+/* Extract the category and item index from a constructed `nl_item' value. */
+#define _NL_ITEM_CATEGORY(item) ((int) (item) >> 16)
+#define _NL_ITEM_INDEX(item) ((int) (item) & 0xffff)
+
+/* Enumeration of locale items that can be queried with `nl_langinfo'. */
+enum
+{
+ /* LC_TIME category: date and time formatting. */
+
+ /* Abbreviated days of the week. */
+ ABDAY_1 = _NL_ITEM (__LC_TIME, 0), /* Sun */
+#define ABDAY_1 ABDAY_1
+ ABDAY_2,
+#define ABDAY_2 ABDAY_2
+ ABDAY_3,
+#define ABDAY_3 ABDAY_3
+ ABDAY_4,
+#define ABDAY_4 ABDAY_4
+ ABDAY_5,
+#define ABDAY_5 ABDAY_5
+ ABDAY_6,
+#define ABDAY_6 ABDAY_6
+ ABDAY_7,
+#define ABDAY_7 ABDAY_7
+
+ /* Long-named days of the week. */
+ DAY_1, /* Sunday */
+#define DAY_1 DAY_1
+ DAY_2, /* Monday */
+#define DAY_2 DAY_2
+ DAY_3, /* Tuesday */
+#define DAY_3 DAY_3
+ DAY_4, /* Wednesday */
+#define DAY_4 DAY_4
+ DAY_5, /* Thursday */
+#define DAY_5 DAY_5
+ DAY_6, /* Friday */
+#define DAY_6 DAY_6
+ DAY_7, /* Saturday */
+#define DAY_7 DAY_7
+
+ /* Abbreviated month names. */
+ ABMON_1, /* Jan */
+#define ABMON_1 ABMON_1
+ ABMON_2,
+#define ABMON_2 ABMON_2
+ ABMON_3,
+#define ABMON_3 ABMON_3
+ ABMON_4,
+#define ABMON_4 ABMON_4
+ ABMON_5,
+#define ABMON_5 ABMON_5
+ ABMON_6,
+#define ABMON_6 ABMON_6
+ ABMON_7,
+#define ABMON_7 ABMON_7
+ ABMON_8,
+#define ABMON_8 ABMON_8
+ ABMON_9,
+#define ABMON_9 ABMON_9
+ ABMON_10,
+#define ABMON_10 ABMON_10
+ ABMON_11,
+#define ABMON_11 ABMON_11
+ ABMON_12,
+#define ABMON_12 ABMON_12
+
+ /* Long month names. */
+ MON_1, /* January */
+#define MON_1 MON_1
+ MON_2,
+#define MON_2 MON_2
+ MON_3,
+#define MON_3 MON_3
+ MON_4,
+#define MON_4 MON_4
+ MON_5,
+#define MON_5 MON_5
+ MON_6,
+#define MON_6 MON_6
+ MON_7,
+#define MON_7 MON_7
+ MON_8,
+#define MON_8 MON_8
+ MON_9,
+#define MON_9 MON_9
+ MON_10,
+#define MON_10 MON_10
+ MON_11,
+#define MON_11 MON_11
+ MON_12,
+#define MON_12 MON_12
+
+ AM_STR, /* Ante meridiem string. */
+#define AM_STR AM_STR
+ PM_STR, /* Post meridiem string. */
+#define PM_STR PM_STR
+
+ D_T_FMT, /* Date and time format for strftime. */
+#define D_T_FMT D_T_FMT
+ D_FMT, /* Date format for strftime. */
+#define D_FMT D_FMT
+ T_FMT, /* Time format for strftime. */
+#define T_FMT T_FMT
+ T_FMT_AMPM, /* 12-hour time format for strftime. */
+#define T_FMT_AMPM T_FMT_AMPM
+
+ ERA, /* Alternate era. */
+#define ERA ERA
+ __ERA_YEAR, /* Year in alternate era format. */
+#ifdef __USE_GNU
+# define ERA_YEAR __ERA_YEAR
+#endif
+ ERA_D_FMT, /* Date in alternate era format. */
+#define ERA_D_FMT ERA_D_FMT
+ ALT_DIGITS, /* Alternate symbols for digits. */
+#define ALT_DIGITS ALT_DIGITS
+ ERA_D_T_FMT, /* Date and time in alternate era format. */
+#define ERA_D_T_FMT ERA_D_T_FMT
+ ERA_T_FMT, /* Time in alternate era format. */
+#define ERA_T_FMT ERA_T_FMT
+
+ _NL_TIME_ERA_NUM_ENTRIES, /* Number entries in the era arrays. */
+ _NL_TIME_ERA_ENTRIES, /* Structure with era entries in usable form.*/
+
+ _NL_WABDAY_1, /* Sun */
+ _NL_WABDAY_2,
+ _NL_WABDAY_3,
+ _NL_WABDAY_4,
+ _NL_WABDAY_5,
+ _NL_WABDAY_6,
+ _NL_WABDAY_7,
+
+ /* Long-named days of the week. */
+ _NL_WDAY_1, /* Sunday */
+ _NL_WDAY_2, /* Monday */
+ _NL_WDAY_3, /* Tuesday */
+ _NL_WDAY_4, /* Wednesday */
+ _NL_WDAY_5, /* Thursday */
+ _NL_WDAY_6, /* Friday */
+ _NL_WDAY_7, /* Saturday */
+
+ /* Abbreviated month names. */
+ _NL_WABMON_1, /* Jan */
+ _NL_WABMON_2,
+ _NL_WABMON_3,
+ _NL_WABMON_4,
+ _NL_WABMON_5,
+ _NL_WABMON_6,
+ _NL_WABMON_7,
+ _NL_WABMON_8,
+ _NL_WABMON_9,
+ _NL_WABMON_10,
+ _NL_WABMON_11,
+ _NL_WABMON_12,
+
+ /* Long month names. */
+ _NL_WMON_1, /* January */
+ _NL_WMON_2,
+ _NL_WMON_3,
+ _NL_WMON_4,
+ _NL_WMON_5,
+ _NL_WMON_6,
+ _NL_WMON_7,
+ _NL_WMON_8,
+ _NL_WMON_9,
+ _NL_WMON_10,
+ _NL_WMON_11,
+ _NL_WMON_12,
+
+ _NL_WAM_STR, /* Ante meridiem string. */
+ _NL_WPM_STR, /* Post meridiem string. */
+
+ _NL_WD_T_FMT, /* Date and time format for strftime. */
+ _NL_WD_FMT, /* Date format for strftime. */
+ _NL_WT_FMT, /* Time format for strftime. */
+ _NL_WT_FMT_AMPM, /* 12-hour time format for strftime. */
+
+ _NL_WERA_YEAR, /* Year in alternate era format. */
+ _NL_WERA_D_FMT, /* Date in alternate era format. */
+ _NL_WALT_DIGITS, /* Alternate symbols for digits. */
+ _NL_WERA_D_T_FMT, /* Date and time in alternate era format. */
+ _NL_WERA_T_FMT, /* Time in alternate era format. */
+
+ _NL_TIME_WEEK_NDAYS,
+ _NL_TIME_WEEK_1STDAY,
+ _NL_TIME_WEEK_1STWEEK,
+ _NL_TIME_FIRST_WEEKDAY,
+ _NL_TIME_FIRST_WORKDAY,
+ _NL_TIME_CAL_DIRECTION,
+ _NL_TIME_TIMEZONE,
+
+ _DATE_FMT, /* strftime format for date. */
+#define _DATE_FMT _DATE_FMT
+ _NL_W_DATE_FMT,
+
+ _NL_TIME_CODESET,
+
+ _NL_NUM_LC_TIME, /* Number of indices in LC_TIME category. */
+
+ /* LC_COLLATE category: text sorting.
+ This information is accessed by the strcoll and strxfrm functions.
+ These `nl_langinfo' names are used only internally. */
+ _NL_COLLATE_NRULES = _NL_ITEM (__LC_COLLATE, 0),
+ _NL_COLLATE_RULESETS,
+ _NL_COLLATE_TABLEMB,
+ _NL_COLLATE_WEIGHTMB,
+ _NL_COLLATE_EXTRAMB,
+ _NL_COLLATE_INDIRECTMB,
+ _NL_COLLATE_GAP1,
+ _NL_COLLATE_GAP2,
+ _NL_COLLATE_GAP3,
+ _NL_COLLATE_TABLEWC,
+ _NL_COLLATE_WEIGHTWC,
+ _NL_COLLATE_EXTRAWC,
+ _NL_COLLATE_INDIRECTWC,
+ _NL_COLLATE_SYMB_HASH_SIZEMB,
+ _NL_COLLATE_SYMB_TABLEMB,
+ _NL_COLLATE_SYMB_EXTRAMB,
+ _NL_COLLATE_COLLSEQMB,
+ _NL_COLLATE_COLLSEQWC,
+ _NL_COLLATE_CODESET,
+ _NL_NUM_LC_COLLATE,
+
+ /* LC_CTYPE category: character classification.
+ This information is accessed by the functions in <ctype.h>.
+ These `nl_langinfo' names are used only internally. */
+ _NL_CTYPE_CLASS = _NL_ITEM (__LC_CTYPE, 0),
+ _NL_CTYPE_TOUPPER,
+ _NL_CTYPE_GAP1,
+ _NL_CTYPE_TOLOWER,
+ _NL_CTYPE_GAP2,
+ _NL_CTYPE_CLASS32,
+ _NL_CTYPE_GAP3,
+ _NL_CTYPE_GAP4,
+ _NL_CTYPE_GAP5,
+ _NL_CTYPE_GAP6,
+ _NL_CTYPE_CLASS_NAMES,
+ _NL_CTYPE_MAP_NAMES,
+ _NL_CTYPE_WIDTH,
+ _NL_CTYPE_MB_CUR_MAX,
+ _NL_CTYPE_CODESET_NAME,
+ CODESET = _NL_CTYPE_CODESET_NAME,
+#define CODESET CODESET
+ _NL_CTYPE_TOUPPER32,
+ _NL_CTYPE_TOLOWER32,
+ _NL_CTYPE_CLASS_OFFSET,
+ _NL_CTYPE_MAP_OFFSET,
+ _NL_CTYPE_INDIGITS_MB_LEN,
+ _NL_CTYPE_INDIGITS0_MB,
+ _NL_CTYPE_INDIGITS1_MB,
+ _NL_CTYPE_INDIGITS2_MB,
+ _NL_CTYPE_INDIGITS3_MB,
+ _NL_CTYPE_INDIGITS4_MB,
+ _NL_CTYPE_INDIGITS5_MB,
+ _NL_CTYPE_INDIGITS6_MB,
+ _NL_CTYPE_INDIGITS7_MB,
+ _NL_CTYPE_INDIGITS8_MB,
+ _NL_CTYPE_INDIGITS9_MB,
+ _NL_CTYPE_INDIGITS_WC_LEN,
+ _NL_CTYPE_INDIGITS0_WC,
+ _NL_CTYPE_INDIGITS1_WC,
+ _NL_CTYPE_INDIGITS2_WC,
+ _NL_CTYPE_INDIGITS3_WC,
+ _NL_CTYPE_INDIGITS4_WC,
+ _NL_CTYPE_INDIGITS5_WC,
+ _NL_CTYPE_INDIGITS6_WC,
+ _NL_CTYPE_INDIGITS7_WC,
+ _NL_CTYPE_INDIGITS8_WC,
+ _NL_CTYPE_INDIGITS9_WC,
+ _NL_CTYPE_OUTDIGIT0_MB,
+ _NL_CTYPE_OUTDIGIT1_MB,
+ _NL_CTYPE_OUTDIGIT2_MB,
+ _NL_CTYPE_OUTDIGIT3_MB,
+ _NL_CTYPE_OUTDIGIT4_MB,
+ _NL_CTYPE_OUTDIGIT5_MB,
+ _NL_CTYPE_OUTDIGIT6_MB,
+ _NL_CTYPE_OUTDIGIT7_MB,
+ _NL_CTYPE_OUTDIGIT8_MB,
+ _NL_CTYPE_OUTDIGIT9_MB,
+ _NL_CTYPE_OUTDIGIT0_WC,
+ _NL_CTYPE_OUTDIGIT1_WC,
+ _NL_CTYPE_OUTDIGIT2_WC,
+ _NL_CTYPE_OUTDIGIT3_WC,
+ _NL_CTYPE_OUTDIGIT4_WC,
+ _NL_CTYPE_OUTDIGIT5_WC,
+ _NL_CTYPE_OUTDIGIT6_WC,
+ _NL_CTYPE_OUTDIGIT7_WC,
+ _NL_CTYPE_OUTDIGIT8_WC,
+ _NL_CTYPE_OUTDIGIT9_WC,
+ _NL_CTYPE_TRANSLIT_TAB_SIZE,
+ _NL_CTYPE_TRANSLIT_FROM_IDX,
+ _NL_CTYPE_TRANSLIT_FROM_TBL,
+ _NL_CTYPE_TRANSLIT_TO_IDX,
+ _NL_CTYPE_TRANSLIT_TO_TBL,
+ _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN,
+ _NL_CTYPE_TRANSLIT_DEFAULT_MISSING,
+ _NL_CTYPE_TRANSLIT_IGNORE_LEN,
+ _NL_CTYPE_TRANSLIT_IGNORE,
+ _NL_CTYPE_MAP_TO_NONASCII,
+ _NL_CTYPE_EXTRA_MAP_1,
+ _NL_CTYPE_EXTRA_MAP_2,
+ _NL_CTYPE_EXTRA_MAP_3,
+ _NL_CTYPE_EXTRA_MAP_4,
+ _NL_CTYPE_EXTRA_MAP_5,
+ _NL_CTYPE_EXTRA_MAP_6,
+ _NL_CTYPE_EXTRA_MAP_7,
+ _NL_CTYPE_EXTRA_MAP_8,
+ _NL_CTYPE_EXTRA_MAP_9,
+ _NL_CTYPE_EXTRA_MAP_10,
+ _NL_CTYPE_EXTRA_MAP_11,
+ _NL_CTYPE_EXTRA_MAP_12,
+ _NL_CTYPE_EXTRA_MAP_13,
+ _NL_CTYPE_EXTRA_MAP_14,
+ _NL_NUM_LC_CTYPE,
+
+ /* LC_MONETARY category: formatting of monetary quantities.
+ These items each correspond to a member of `struct lconv',
+ defined in <locale.h>. */
+ __INT_CURR_SYMBOL = _NL_ITEM (__LC_MONETARY, 0),
+#ifdef __USE_GNU
+# define INT_CURR_SYMBOL __INT_CURR_SYMBOL
+#endif
+ __CURRENCY_SYMBOL,
+#ifdef __USE_GNU
+# define CURRENCY_SYMBOL __CURRENCY_SYMBOL
+#endif
+ __MON_DECIMAL_POINT,
+#ifdef __USE_GNU
+# define MON_DECIMAL_POINT __MON_DECIMAL_POINT
+#endif
+ __MON_THOUSANDS_SEP,
+#ifdef __USE_GNU
+# define MON_THOUSANDS_SEP __MON_THOUSANDS_SEP
+#endif
+ __MON_GROUPING,
+#ifdef __USE_GNU
+# define MON_GROUPING __MON_GROUPING
+#endif
+ __POSITIVE_SIGN,
+#ifdef __USE_GNU
+# define POSITIVE_SIGN __POSITIVE_SIGN
+#endif
+ __NEGATIVE_SIGN,
+#ifdef __USE_GNU
+# define NEGATIVE_SIGN __NEGATIVE_SIGN
+#endif
+ __INT_FRAC_DIGITS,
+#ifdef __USE_GNU
+# define INT_FRAC_DIGITS __INT_FRAC_DIGITS
+#endif
+ __FRAC_DIGITS,
+#ifdef __USE_GNU
+# define FRAC_DIGITS __FRAC_DIGITS
+#endif
+ __P_CS_PRECEDES,
+#ifdef __USE_GNU
+# define P_CS_PRECEDES __P_CS_PRECEDES
+#endif
+ __P_SEP_BY_SPACE,
+#ifdef __USE_GNU
+# define P_SEP_BY_SPACE __P_SEP_BY_SPACE
+#endif
+ __N_CS_PRECEDES,
+#ifdef __USE_GNU
+# define N_CS_PRECEDES __N_CS_PRECEDES
+#endif
+ __N_SEP_BY_SPACE,
+#ifdef __USE_GNU
+# define N_SEP_BY_SPACE __N_SEP_BY_SPACE
+#endif
+ __P_SIGN_POSN,
+#ifdef __USE_GNU
+# define P_SIGN_POSN __P_SIGN_POSN
+#endif
+ __N_SIGN_POSN,
+#ifdef __USE_GNU
+# define N_SIGN_POSN __N_SIGN_POSN
+#endif
+ _NL_MONETARY_CRNCYSTR,
+#define CRNCYSTR _NL_MONETARY_CRNCYSTR
+ __INT_P_CS_PRECEDES,
+#ifdef __USE_GNU
+# define INT_P_CS_PRECEDES __INT_P_CS_PRECEDES
+#endif
+ __INT_P_SEP_BY_SPACE,
+#ifdef __USE_GNU
+# define INT_P_SEP_BY_SPACE __INT_P_SEP_BY_SPACE
+#endif
+ __INT_N_CS_PRECEDES,
+#ifdef __USE_GNU
+# define INT_N_CS_PRECEDES __INT_N_CS_PRECEDES
+#endif
+ __INT_N_SEP_BY_SPACE,
+#ifdef __USE_GNU
+# define INT_N_SEP_BY_SPACE __INT_N_SEP_BY_SPACE
+#endif
+ __INT_P_SIGN_POSN,
+#ifdef __USE_GNU
+# define INT_P_SIGN_POSN __INT_P_SIGN_POSN
+#endif
+ __INT_N_SIGN_POSN,
+#ifdef __USE_GNU
+# define INT_N_SIGN_POSN __INT_N_SIGN_POSN
+#endif
+ _NL_MONETARY_DUO_INT_CURR_SYMBOL,
+ _NL_MONETARY_DUO_CURRENCY_SYMBOL,
+ _NL_MONETARY_DUO_INT_FRAC_DIGITS,
+ _NL_MONETARY_DUO_FRAC_DIGITS,
+ _NL_MONETARY_DUO_P_CS_PRECEDES,
+ _NL_MONETARY_DUO_P_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_N_CS_PRECEDES,
+ _NL_MONETARY_DUO_N_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_INT_P_CS_PRECEDES,
+ _NL_MONETARY_DUO_INT_P_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_INT_N_CS_PRECEDES,
+ _NL_MONETARY_DUO_INT_N_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_P_SIGN_POSN,
+ _NL_MONETARY_DUO_N_SIGN_POSN,
+ _NL_MONETARY_DUO_INT_P_SIGN_POSN,
+ _NL_MONETARY_DUO_INT_N_SIGN_POSN,
+ _NL_MONETARY_UNO_VALID_FROM,
+ _NL_MONETARY_UNO_VALID_TO,
+ _NL_MONETARY_DUO_VALID_FROM,
+ _NL_MONETARY_DUO_VALID_TO,
+ _NL_MONETARY_CONVERSION_RATE,
+ _NL_MONETARY_DECIMAL_POINT_WC,
+ _NL_MONETARY_THOUSANDS_SEP_WC,
+ _NL_MONETARY_CODESET,
+ _NL_NUM_LC_MONETARY,
+
+ /* LC_NUMERIC category: formatting of numbers.
+ These also correspond to members of `struct lconv'; see <locale.h>. */
+ __DECIMAL_POINT = _NL_ITEM (__LC_NUMERIC, 0),
+#ifdef __USE_GNU
+# define DECIMAL_POINT __DECIMAL_POINT
+#endif
+ RADIXCHAR = __DECIMAL_POINT,
+#define RADIXCHAR RADIXCHAR
+ __THOUSANDS_SEP,
+#ifdef __USE_GNU
+# define THOUSANDS_SEP __THOUSANDS_SEP
+#endif
+ THOUSEP = __THOUSANDS_SEP,
+#define THOUSEP THOUSEP
+ __GROUPING,
+#ifdef __USE_GNU
+# define GROUPING __GROUPING
+#endif
+ _NL_NUMERIC_DECIMAL_POINT_WC,
+ _NL_NUMERIC_THOUSANDS_SEP_WC,
+ _NL_NUMERIC_CODESET,
+ _NL_NUM_LC_NUMERIC,
+
+ __YESEXPR = _NL_ITEM (__LC_MESSAGES, 0), /* Regex matching ``yes'' input. */
+#define YESEXPR __YESEXPR
+ __NOEXPR, /* Regex matching ``no'' input. */
+#define NOEXPR __NOEXPR
+ __YESSTR, /* Output string for ``yes''. */
+#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
+# define YESSTR __YESSTR
+#endif
+ __NOSTR, /* Output string for ``no''. */
+#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
+# define NOSTR __NOSTR
+#endif
+ _NL_MESSAGES_CODESET,
+ _NL_NUM_LC_MESSAGES,
+
+ _NL_PAPER_HEIGHT = _NL_ITEM (__LC_PAPER, 0),
+ _NL_PAPER_WIDTH,
+ _NL_PAPER_CODESET,
+ _NL_NUM_LC_PAPER,
+
+ _NL_NAME_NAME_FMT = _NL_ITEM (__LC_NAME, 0),
+ _NL_NAME_NAME_GEN,
+ _NL_NAME_NAME_MR,
+ _NL_NAME_NAME_MRS,
+ _NL_NAME_NAME_MISS,
+ _NL_NAME_NAME_MS,
+ _NL_NAME_CODESET,
+ _NL_NUM_LC_NAME,
+
+ _NL_ADDRESS_POSTAL_FMT = _NL_ITEM (__LC_ADDRESS, 0),
+ _NL_ADDRESS_COUNTRY_NAME,
+ _NL_ADDRESS_COUNTRY_POST,
+ _NL_ADDRESS_COUNTRY_AB2,
+ _NL_ADDRESS_COUNTRY_AB3,
+ _NL_ADDRESS_COUNTRY_CAR,
+ _NL_ADDRESS_COUNTRY_NUM,
+ _NL_ADDRESS_COUNTRY_ISBN,
+ _NL_ADDRESS_LANG_NAME,
+ _NL_ADDRESS_LANG_AB,
+ _NL_ADDRESS_LANG_TERM,
+ _NL_ADDRESS_LANG_LIB,
+ _NL_ADDRESS_CODESET,
+ _NL_NUM_LC_ADDRESS,
+
+ _NL_TELEPHONE_TEL_INT_FMT = _NL_ITEM (__LC_TELEPHONE, 0),
+ _NL_TELEPHONE_TEL_DOM_FMT,
+ _NL_TELEPHONE_INT_SELECT,
+ _NL_TELEPHONE_INT_PREFIX,
+ _NL_TELEPHONE_CODESET,
+ _NL_NUM_LC_TELEPHONE,
+
+ _NL_MEASUREMENT_MEASUREMENT = _NL_ITEM (__LC_MEASUREMENT, 0),
+ _NL_MEASUREMENT_CODESET,
+ _NL_NUM_LC_MEASUREMENT,
+
+ _NL_IDENTIFICATION_TITLE = _NL_ITEM (__LC_IDENTIFICATION, 0),
+ _NL_IDENTIFICATION_SOURCE,
+ _NL_IDENTIFICATION_ADDRESS,
+ _NL_IDENTIFICATION_CONTACT,
+ _NL_IDENTIFICATION_EMAIL,
+ _NL_IDENTIFICATION_TEL,
+ _NL_IDENTIFICATION_FAX,
+ _NL_IDENTIFICATION_LANGUAGE,
+ _NL_IDENTIFICATION_TERRITORY,
+ _NL_IDENTIFICATION_AUDIENCE,
+ _NL_IDENTIFICATION_APPLICATION,
+ _NL_IDENTIFICATION_ABBREVIATION,
+ _NL_IDENTIFICATION_REVISION,
+ _NL_IDENTIFICATION_DATE,
+ _NL_IDENTIFICATION_CATEGORY,
+ _NL_IDENTIFICATION_CODESET,
+ _NL_NUM_LC_IDENTIFICATION,
+
+ /* This marks the highest value used. */
+ _NL_NUM
+};
+
+/* This macro produces an item you can pass to `nl_langinfo' or
+ `nl_langinfo_l' to get the name of the locale in use for CATEGORY. */
+#define _NL_LOCALE_NAME(category) _NL_ITEM ((category), -1)
+#ifdef __USE_GNU
+# define NL_LOCALE_NAME(category) _NL_LOCALE_NAME (category)
+#endif
+
+
+/* Return the current locale's value for ITEM.
+ If ITEM is invalid, an empty string is returned.
+
+ The string returned will not change until `setlocale' is called;
+ it is usually in read-only memory and cannot be modified. */
+
+extern char *nl_langinfo (nl_item __item) __THROW;
+
+
+#ifdef __USE_GNU
+/* This interface is for the extended locale model. See <locale.h> for
+ more information. */
+
+/* Get locale datatype definition. */
+# include <xlocale.h>
+
+/* Just like nl_langinfo but get the information from the locale object L. */
+extern char *nl_langinfo_l (nl_item __item, __locale_t l);
+#endif
+
+__END_DECLS
+
+#endif /* langinfo.h */
diff --git a/gui/simple-greeter/libnotificationarea/Makefile.am b/gui/simple-greeter/libnotificationarea/Makefile.am
index 7b5fde3c..5f766e1a 100644
--- a/gui/simple-greeter/libnotificationarea/Makefile.am
+++ b/gui/simple-greeter/libnotificationarea/Makefile.am
@@ -39,7 +39,7 @@ libnotificationarea_la_LIBADD = \
$(GUI_LIBS) \
$(NULL)
-libnotification_area_la_LDFLAGS = \
+libnotificationarea_la_LDFLAGS = \
-export-dynamic \
$(NULL)
diff --git a/gui/simple-greeter/locarchive.h b/gui/simple-greeter/locarchive.h
new file mode 100644
index 00000000..f933f4d9
--- /dev/null
+++ b/gui/simple-greeter/locarchive.h
@@ -0,0 +1,97 @@
+/* Definitions for locale archive handling.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LOCARCHIVE_H
+#define _LOCARCHIVE_H 1
+
+#include <stdint.h>
+
+#define AR_MAGIC 0xde020109
+
+struct locarhead
+{
+ uint32_t magic;
+ /* Serial number. */
+ uint32_t serial;
+ /* Name hash table. */
+ uint32_t namehash_offset;
+ uint32_t namehash_used;
+ uint32_t namehash_size;
+ /* String table. */
+ uint32_t string_offset;
+ uint32_t string_used;
+ uint32_t string_size;
+ /* Table with locale records. */
+ uint32_t locrectab_offset;
+ uint32_t locrectab_used;
+ uint32_t locrectab_size;
+ /* MD5 sum hash table. */
+ uint32_t sumhash_offset;
+ uint32_t sumhash_used;
+ uint32_t sumhash_size;
+};
+
+
+struct namehashent
+{
+ /* Hash value of the name. */
+ uint32_t hashval;
+ /* Offset of the name in the string table. */
+ uint32_t name_offset;
+ /* Offset of the locale record. */
+ uint32_t locrec_offset;
+};
+
+
+struct sumhashent
+{
+ /* MD5 sum. */
+ char sum[16];
+ /* Offset of the file in the archive. */
+ uint32_t file_offset;
+};
+
+struct locrecent
+{
+ uint32_t refs; /* # of namehashent records that point here */
+ struct
+ {
+ uint32_t offset;
+ uint32_t len;
+ } record[__LC_LAST];
+};
+
+
+struct locarhandle
+{
+ int fd;
+ void *addr;
+ size_t len;
+};
+
+
+/* In memory data for the locales with their checksums. */
+typedef struct locale_category_data
+{
+ off_t size;
+ void *addr;
+ char sum[16];
+} locale_data_t[__LC_LAST];
+
+#endif /* locarchive.h */
diff --git a/gui/simple-greeter/test-language-chooser.c b/gui/simple-greeter/test-language-chooser.c
new file mode 100644
index 00000000..1a4176a1
--- /dev/null
+++ b/gui/simple-greeter/test-language-chooser.c
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <libintl.h>
+#include <locale.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gdm-language-chooser-dialog.h"
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *dialog;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ setlocale (LC_ALL, "");
+
+ gtk_init (&argc, &argv);
+
+ dialog = gdm_language_chooser_dialog_new ();
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ char *name;
+
+ name = gdm_language_chooser_dialog_get_current_language_name (GDM_LANGUAGE_CHOOSER_DIALOG (dialog));
+ g_message ("Language: %s", name);
+ g_free (name);
+ }
+ gtk_widget_destroy (dialog);
+
+ return 0;
+}