--- gdm-2.17.8/daemon/slave.c.orig	2007-03-29 12:44:34.735999000 +0900
+++ gdm-2.17.8/daemon/slave.c	2007-03-29 14:02:16.777594000 +0900
@@ -2741,7 +2741,9 @@ gdm_slave_greeter (void)
 
 	gdm_slave_send_num (GDM_SOP_GREETPID, d->greetpid);
 	if (always_restart_greeter)
-	  gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "");
+	  gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "Y");
+	else
+	  gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "N");
 	gdmlang = g_getenv ("GDM_LANG");
 	if (gdmlang)
 	  gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, gdmlang);
@@ -4400,6 +4402,7 @@ gdm_slave_session_start (void)
 	gdm_assert_not_reached ();
 	
     default:
+	always_restart_greeter = FALSE;
 	if (!savelang && language && strcmp (usrlang, language)) {
 		if (gdm_system_locale) {
 			g_setenv ("LANG", gdm_system_locale, TRUE);
--- gdm-2.17.8/gui/Makefile.am.orig	2007-03-29 13:13:49.059395000 +0900
+++ gdm-2.17.8/gui/Makefile.am	2007-03-29 13:30:16.818571000 +0900
@@ -19,7 +19,8 @@ INCLUDES = \
 	-I$(top_srcdir)/daemon				\
 	-I$(top_srcdir)/vicious-extensions		\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" 	\
-	$(GUI_CFLAGS)
+	$(GUI_CFLAGS)					\
+	$(GREETER_CFLAGS)
 
 #
 #	-DG_DISABLE_DEPRECATED				\
--- gdm-2.17.8/gui/gdmlanguages.c.orig	2007-03-29 15:50:13.118659000 +0900
+++ gdm-2.17.8/gui/gdmlanguages.c	2007-03-30 11:01:51.912349000 +0900
@@ -1,5 +1,5 @@
 /* GDM - The GNOME Display Manager
- * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net>
+ * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
  *
  * This file Copyright (c) 2001 George Lebl
  *
@@ -19,14 +19,31 @@
  */
 
 #include "config.h"
+
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <locale.h>
 #include <string.h>
 #include <stdio.h>
 
-#include "gdmlanguages.h"
+#include "gdm.h"
+#include "gdmwm.h"
+#include "gdmcommon.h"
 #include "gdmconfig.h"
+#include "gdmlanguages.h"
+
+#include "greeter/greeter_item_customlist.h"
+
+#define LAST_LANGUAGE "Last"
+#define DEFAULT_LANGUAGE "Default"
+
+static GtkWidget    *tv                       = NULL;
+static GtkListStore *lang_model               = NULL;
+static GtkWidget    *dialog                   = NULL;
+static gchar        *current_language         = NULL;
+static gchar        *dialog_selected_language = NULL;
+static gint          savelang                 = GTK_RESPONSE_NO;
+static gboolean      always_restart           = FALSE;
 
 typedef struct _Language Language;
 struct _Language {
@@ -637,4 +654,468 @@ gdm_lang_read_locale_file (const char *l
 	return langs;
 }
 
-/* EOF */
+GtkListStore *
+gdm_lang_get_model (void)
+{
+   return lang_model;
+}
+
+void
+gdm_lang_initialize_model (void)
+{
+  GList *list, *li;
+  GtkTreeIter iter;
+
+  list = gdm_lang_read_locale_file (gdm_config_get_string (GDM_KEY_LOCALE_FILE));
+
+  lang_model = gtk_list_store_new (NUM_COLUMNS,
+				   G_TYPE_STRING,
+				   G_TYPE_STRING,
+				   G_TYPE_STRING);
+
+  gtk_list_store_append (lang_model, &iter);
+  gtk_list_store_set (lang_model, &iter,
+		      TRANSLATED_NAME_COLUMN, _("Last language"),
+		      UNTRANSLATED_NAME_COLUMN, NULL,
+		      LOCALE_COLUMN, LAST_LANGUAGE,
+		      -1);
+
+  gtk_list_store_append (lang_model, &iter);
+  gtk_list_store_set (lang_model, &iter,
+		      TRANSLATED_NAME_COLUMN, _("System Default"),
+		      UNTRANSLATED_NAME_COLUMN, NULL,
+		      LOCALE_COLUMN, DEFAULT_LANGUAGE,
+		      -1);
+
+  for (li = list; li != NULL; li = li->next)
+    {
+      char *lang = li->data;
+      char *name;
+      char *untranslated;
+
+      li->data = NULL;
+
+      name = gdm_lang_name (lang,
+			    FALSE /* never_encoding */,
+			    TRUE /* no_group */,
+			    FALSE /* untranslated */,
+			    FALSE /* markup */);
+
+      untranslated = gdm_lang_untranslated_name (lang,
+						 TRUE /* markup */);
+
+      gtk_list_store_append (lang_model, &iter);
+      gtk_list_store_set (lang_model, &iter,
+			  TRANSLATED_NAME_COLUMN, name,
+			  UNTRANSLATED_NAME_COLUMN, untranslated,
+			  LOCALE_COLUMN, lang,
+			  -1);
+
+      g_free (name);
+      g_free (untranslated);
+      g_free (lang);
+    }
+  g_list_free (list);
+}
+
+gint
+gdm_lang_get_save_language (void)
+{
+  return savelang;
+}
+
+gchar *
+gdm_lang_get_language (const char *old_language)
+{
+  gchar *retval = NULL;
+
+  /* Don't save language unless told otherwise */
+  savelang = GTK_RESPONSE_NO;
+
+  if (old_language == NULL)
+    old_language = "";
+
+  /* If a different language is selected */
+  if (current_language != NULL && strcmp (current_language, LAST_LANGUAGE) != 0)
+    {
+      if (strcmp (current_language, DEFAULT_LANGUAGE) == 0)
+	retval = g_strdup ("");
+      else
+        retval = g_strdup (current_language);
+
+      /* User's saved language is not the chosen one */
+      if (strcmp (old_language, retval) != 0)
+	{
+	  gchar *primary_message;
+	  gchar *secondary_message;
+	  char *current_name, *saved_name;
+
+	  if (strcmp (current_language, DEFAULT_LANGUAGE) == 0)
+	    current_name = g_strdup (_("System Default"));
+	  else
+	    current_name = gdm_lang_name (current_language,
+					  FALSE /* never_encoding */,
+					  TRUE /* no_group */,
+					  TRUE /* untranslated */,
+					  TRUE /* markup */);
+	  if (strcmp (old_language, "") == 0)
+	    saved_name = g_strdup (_("System Default"));
+	  else
+	    saved_name = gdm_lang_name (old_language,
+					FALSE /* never_encoding */,
+					TRUE /* no_group */,
+					TRUE /* untranslated */,
+					TRUE /* markup */);
+
+	  primary_message = g_strdup_printf (_("Do you wish to make %s the default for future sessions?"),
+	                                     current_name);
+ 	  secondary_message = g_strdup_printf (_("You have chosen %s for this session, but your default setting is "
+	                                         "%s."), current_name, saved_name);
+	  g_free (current_name);
+	  g_free (saved_name);
+
+	  savelang = gdm_wm_query_dialog (primary_message, secondary_message,
+		_("Make _Default"), _("Just For _This Session"), TRUE);
+	  g_free (primary_message);
+	  g_free (secondary_message);
+	}
+    }
+  else
+    {
+      retval = g_strdup (old_language);
+    }
+
+  return retval;
+}
+
+static void
+selection_changed (GtkTreeSelection *selection,
+		   gpointer          data)
+{
+  GtkTreeIter iter;
+
+  if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+    {
+      g_free (dialog_selected_language);
+      gtk_tree_model_get (GTK_TREE_MODEL (lang_model), &iter, LOCALE_COLUMN, &dialog_selected_language, -1);
+    }
+}
+
+static void
+tree_row_activated (GtkTreeView         *view,
+                    GtkTreePath         *path,
+                    GtkTreeViewColumn   *column,
+                    gpointer            data)
+{
+  GtkTreeIter iter;
+  if (gtk_tree_model_get_iter (GTK_TREE_MODEL (lang_model), &iter, path))
+    {
+      g_free (dialog_selected_language);
+      gtk_tree_model_get (GTK_TREE_MODEL (lang_model), &iter,
+			  LOCALE_COLUMN, &dialog_selected_language,
+			  -1);
+      gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  }
+}
+
+static void
+gdm_lang_setup_treeview (void)
+{
+  if (dialog == NULL)
+    {
+      GtkWidget *main_vbox;
+      GtkWidget *button;
+      GtkWidget **tmp_p;
+      GtkWidget *swindow;
+      GtkWidget *label;
+      char *s;
+
+      dialog = gtk_dialog_new_with_buttons (_("Select a Language"),
+#ifdef TODO
+					    GTK_WINDOW (parent_window),
+#endif
+					    NULL,
+					    0,
+					    GTK_STOCK_CANCEL,
+					    GTK_RESPONSE_CANCEL,
+					    NULL);
+					    
+      button = gtk_button_new_with_mnemonic (_("Change _Language"));
+      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_widget_show (button);
+      gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
+                                    GTK_RESPONSE_OK);
+					    
+      gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+      gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+      gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
+
+      main_vbox = gtk_vbox_new (FALSE, 6);
+      gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 5);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+                          main_vbox, TRUE, TRUE, 0);
+  
+      gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+				       GTK_RESPONSE_OK);
+      /* evil gcc warnings */
+      tmp_p = &dialog;
+      g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *)tmp_p);
+      s = g_strdup (_("_Select the language for your session to use:"));
+      label = gtk_label_new_with_mnemonic (s);
+      gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+      g_free (s);
+      gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+      gtk_box_pack_start (GTK_BOX (main_vbox),
+			  label, FALSE, FALSE, 0);
+      tv = gtk_tree_view_new ();
+      gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tv), TRUE);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (label), tv);
+      /* FIXME: we should handle this better, but things really look
+       * bad if we aren't always LTR */
+      gtk_widget_set_direction (tv, GTK_TEXT_DIR_LTR);
+      gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tv), FALSE);
+      gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
+					       GTK_DIALOG_MODAL,
+					       NULL,
+					       gtk_cell_renderer_text_new (),
+					       "text", TRANSLATED_NAME_COLUMN,
+					       NULL);
+      gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
+					       GTK_DIALOG_MODAL,
+					       NULL,
+					       gtk_cell_renderer_text_new (),
+					       "markup",
+					       UNTRANSLATED_NAME_COLUMN,
+					       NULL);
+      swindow = gtk_scrolled_window_new (NULL, NULL);
+      gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow), GTK_SHADOW_IN);
+      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
+				  GTK_POLICY_AUTOMATIC,
+				  GTK_POLICY_AUTOMATIC);
+      gtk_container_add (GTK_CONTAINER (swindow), tv);
+      gtk_box_pack_start (GTK_BOX (main_vbox),
+			  swindow, TRUE, TRUE, 0);
+      gtk_window_set_default_size (GTK_WINDOW (dialog),
+				   MIN (400, gdm_wm_screen.width),
+				   MIN (600, gdm_wm_screen.height));
+      g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (tv))),
+			"changed",
+			(GCallback) selection_changed,
+			NULL);
+      g_signal_connect (G_OBJECT (tv),
+                        "row_activated",
+                        (GCallback) tree_row_activated,
+                        NULL);
+      gtk_tree_view_set_model (GTK_TREE_VIEW (tv),
+			       GTK_TREE_MODEL (lang_model));
+    }
+}
+
+static gint
+gdm_lang_ask_restart (gchar *language)
+{
+	GtkWidget *dialog;
+	gchar *firstmsg;
+	gchar *secondmsg;
+	gchar *login;
+	gint response = GTK_RESPONSE_NO;
+
+	if (always_restart)
+		return GTK_RESPONSE_YES;
+
+	login = _("the login screen");
+	firstmsg = g_strdup_printf (_("Do you wish to restart %s with the chosen language?"),
+	                            login);
+	secondmsg = g_strdup_printf (_("You will restart %s with the %s locale."),
+	                             login,
+	                             language);
+
+	response = gdm_wm_query_dialog (firstmsg, secondmsg, _("_Yes"), _("_No"), FALSE);
+
+	g_free (firstmsg);
+	g_free (secondmsg);
+
+	return response;
+}
+
+static gboolean
+gdm_lang_get_restart_state (void)
+{
+  return  always_restart;
+}
+
+static void
+gdm_lang_set_restart_state (gboolean do_restart)
+{
+  always_restart = do_restart;
+}
+
+static void
+gdm_lang_restart_handler (GtkMenuItem *menu_item, gpointer user_data)
+{
+  if ((int)user_data == ALWAYS_RESTART)
+    always_restart = TRUE;
+  else
+    always_restart = FALSE;
+}
+
+void
+gdm_lang_set (char *language)
+{
+   char *locale;
+   GtkTreeSelection *selection;
+   GtkTreeIter iter = {0};
+
+   g_free (current_language);
+   current_language = g_strdup (language);
+
+   if (dialog == NULL)
+     gdm_lang_setup_treeview ();
+
+   if (language == NULL)
+      return;
+ 
+   greeter_custom_set_language (language);
+
+   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
+   gtk_tree_selection_unselect_all (selection);
+
+   if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (lang_model), &iter)) {
+      do {
+         gtk_tree_model_get (GTK_TREE_MODEL (lang_model), &iter, LOCALE_COLUMN, &locale, -1);
+         if (locale != NULL && strcmp (locale, language) == 0) {
+            GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (lang_model), &iter);
+
+            gtk_tree_selection_select_iter (selection, &iter);
+            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tv), path, NULL, FALSE, 0.0, 0.0);
+            gtk_tree_path_free (path);
+            break;
+         }
+      } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (lang_model), &iter));
+   }
+}
+
+/*
+ * The button with this handler appears in the F10 menu, so it
+ * cannot depend on callback data being passed in.
+ */
+void
+gdm_lang_handler (gpointer user_data)
+{
+  if (dialog == NULL)
+    gdm_lang_setup_treeview ();
+
+  gtk_widget_show_all (dialog);
+  gdm_wm_center_window (GTK_WINDOW (dialog));
+
+  gdm_wm_no_login_focus_push ();
+  if (tv != NULL)
+    {
+      GtkTreeSelection *selection;
+	  
+      gtk_widget_show_now (dialog);
+      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
+      if (selection == NULL)
+	gtk_tree_selection_select_path (selection, gtk_tree_path_new_first ());
+      else
+        {
+          GtkTreeIter iter;
+          GtkTreePath *path;
+          GtkTreeModel *tm = GTK_TREE_MODEL (lang_model);
+
+          gtk_tree_selection_get_selected (selection, &tm, &iter);
+          path = gtk_tree_model_get_path (GTK_TREE_MODEL (lang_model), &iter);
+          gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tv), path, NULL, FALSE, 0.0, 0.0);
+          gtk_tree_path_free (path);
+        }
+    }
+  switch (gtk_dialog_run (GTK_DIALOG (dialog)))
+    {
+    case GTK_RESPONSE_OK:
+      if (dialog_selected_language)
+        {
+          gint response = GTK_RESPONSE_YES;
+
+          if (strcmp (dialog_selected_language, LAST_LANGUAGE))
+            response = gdm_lang_ask_restart (dialog_selected_language);
+          if (response == GTK_RESPONSE_YES)
+            gdm_lang_set ((char *) dialog_selected_language);
+          if (strcmp (dialog_selected_language, LAST_LANGUAGE)
+              && (response == GTK_RESPONSE_YES))
+            {
+              printf ("%c%c%c%c%s\n", STX,
+                                      BEL,
+                                      GDM_INTERRUPT_SELECT_LANG,
+                                      response == GTK_RESPONSE_YES ? 1 : 0,
+                                      dialog_selected_language);
+              fflush (stdout);
+            }
+        }
+      break;
+    case GTK_RESPONSE_CANCEL:
+    default:
+      break;
+    }
+
+  gdm_wm_no_login_focus_pop ();
+
+  if (dialog)
+    gtk_widget_hide (dialog);
+}
+
+int
+gdm_lang_op_lang (const gchar *args)
+{
+  gchar *language = gdm_lang_get_language (args);
+
+  if (gdm_lang_get_save_language () == GTK_RESPONSE_CANCEL)
+    printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL);
+  else
+    printf ("%c%s\n", STX, language);
+  fflush (stdout);
+  g_free (language);
+
+  return 0;
+}
+
+int
+gdm_lang_op_slang (const gchar *args)
+{
+  if (gdm_lang_get_save_language () == GTK_RESPONSE_YES)
+    printf ("%cY\n", STX);
+  else
+    printf ("%c\n", STX);
+  fflush (stdout);
+
+  return 0;
+}
+
+int
+gdm_lang_op_setlang (const gchar *args)
+{
+  if (args)
+    gdm_lang_set ((char*)args);
+  printf ("%c\n", STX);
+  fflush (stdout);
+
+  return 0;
+}
+
+int
+gdm_lang_op_always_restart (const gchar *args)
+{
+  if (!args)
+    ;
+  else if (g_ascii_strcasecmp (args, "y") == 0)
+    gdm_lang_set_restart_state (TRUE);
+  else if (g_ascii_strcasecmp (args, "n") == 0)
+    gdm_lang_set_restart_state (FALSE);
+  if (args)
+    gdm_common_error ("test %s", args);
+
+  printf ("%c\n", STX);
+  fflush (stdout);
+
+  return 0;
+}
+
--- gdm-2.17.8/gui/gdmlanguages.h.orig	2007-03-29 16:04:57.359701000 +0900
+++ gdm-2.17.8/gui/gdmlanguages.h	2007-03-29 16:11:13.188716000 +0900
@@ -1,5 +1,5 @@
 /* GDM - The Gnome Display Manager
- * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net>
+ * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
  *
  * This file Copyright (c) 2001 George Lebl
  *
@@ -21,6 +21,20 @@
 #ifndef GDM_LANGUAGES_H
 #define GDM_LANGUAGES_H
 
+#include <glib.h>
+
+enum {
+  LOCALE_COLUMN,
+  TRANSLATED_NAME_COLUMN,
+  UNTRANSLATED_NAME_COLUMN,
+  NUM_COLUMNS
+};
+
+enum {
+  ASK_RESTART = 0,
+  ALWAYS_RESTART
+};
+
 /* This is the interface for translating languages.  Language translations
  * are now hardocded in, but that may change */
 
@@ -40,6 +54,15 @@ char *		gdm_lang_untranslated_name (cons
 
 GList *		gdm_lang_read_locale_file (const char *file);
 
-#endif /* GDM_LANGUAGES_H */
+GtkListStore *	gdm_lang_get_model		(void);
+void		gdm_lang_initialize_model	(void);
+gint		gdm_lang_get_save_language	(void);
+gchar *		gdm_lang_get_language		(const char      *old_language);
+void		gdm_lang_set			(char *language);
+void		gdm_lang_handler		(gpointer user_data);
+int		gdm_lang_op_lang		(const gchar *args);
+int		gdm_lang_op_slang		(const gchar *args);
+int		gdm_lang_op_setlang		(const gchar *args);
+int		gdm_lang_op_always_restart	(const gchar *args);
 
-/* EOF */
+#endif /* GDM_LANGUAGES_H */
--- gdm-2.17.8/gui/gdmlogin.c.orig	2007-03-29 14:29:48.512986000 +0900
+++ gdm-2.17.8/gui/gdmlogin.c	2007-03-29 15:32:43.470799000 +0900
@@ -1029,7 +1029,7 @@ gdm_login_session_init (GtkWidget *menu)
 static void 
 gdm_login_language_handler (GtkMenuItem *menu_item, gpointer user_data) 
 {
-    greeter_language_handler (NULL, NULL);
+    gdm_lang_handler (user_data);
 }
 
 
@@ -1039,7 +1039,7 @@ gdm_login_language_menu_new (void)
     GtkWidget *menu;
     GtkWidget *item;
 
-    greeter_language_initialize_model ();
+    gdm_lang_initialize_model ();
 
     menu = gtk_menu_new ();
 
@@ -1540,7 +1540,7 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_LANG:
-	greeter_language_op_lang (args);
+	gdm_lang_op_lang (args);
 	break;
 
     case GDM_SSESS:
@@ -1553,15 +1553,15 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_SLANG:
-	greeter_language_op_slang (args);
+	gdm_lang_op_slang (args);
 	break;
 
     case GDM_SETLANG:
-	greeter_language_op_setlang (args);
+	gdm_lang_op_setlang (args);
 	break;
 
     case GDM_ALWAYS_RESTART:
-	greeter_language_op_always_restart (args);
+	gdm_lang_op_always_restart (args);
 	break;
 
     case GDM_RESET:
--- gdm-2.17.8/gui/greeter/Makefile.am.orig	2007-03-30 10:40:42.682541000 +0900
+++ gdm-2.17.8/gui/greeter/Makefile.am	2007-03-30 10:58:07.998663000 +0900
@@ -43,8 +43,6 @@ gdmthemetester: $(srcdir)/gdmthemetester
 gdmgreeter_SOURCES =  \
 	greeter.c \
 	greeter.h \
-	greeter_action_language.c \
-	greeter_action_language.h \
 	greeter_canvas_text.c \
 	greeter_canvas_text.h \
 	greeter_canvas_item.c \
@@ -93,7 +91,6 @@ gdmgreeter_LDADD = \
 	-lX11
 
 libgdmgreeter_a_SOURCES = \
-	greeter_action_language.c	\
 	greeter_events.c		\
 	greeter_item.c			\
 	greeter_item_customlist.c	\
--- gdm-2.17.8/gui/greeter/greeter.c.orig	2007-03-29 14:28:39.843206000 +0900
+++ gdm-2.17.8/gui/greeter/greeter.c	2007-03-30 10:28:12.313714000 +0900
@@ -45,6 +45,7 @@
 #include "gdmcommon.h"
 #include "gdmconfig.h"
 #include "gdmsession.h"
+#include "gdmlanguages.h"
 
 #include "greeter.h"
 #include "greeter_configuration.h"
@@ -340,7 +341,7 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_LANG:
-	greeter_language_op_lang (args);
+	gdm_lang_op_lang (args);
 	break;
 
     case GDM_SSESS:
@@ -353,15 +354,15 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_SLANG:
-	greeter_language_op_slang (args);
+	gdm_lang_op_slang (args);
 	break;
 
     case GDM_SETLANG:
-	greeter_language_op_setlang (args);
+	gdm_lang_op_setlang (args);
 	break;
 
     case GDM_ALWAYS_RESTART:
-	greeter_language_op_always_restart (args);
+	gdm_lang_op_always_restart (args);
 	break;
 
     case GDM_RESET:
@@ -574,6 +575,13 @@ greeter_cancel_handler (GreeterItemInfo 
 }
 
 static void
+greeter_language_handler (GreeterItemInfo *info,
+                          gpointer         user_data)
+{
+  gdm_lang_handler (user_data);
+}
+
+static void
 greeter_setup_items (void)
 {
   greeter_item_clock_setup ();
@@ -1220,7 +1228,7 @@ main (int argc, char *argv[])
   }
   gdm_common_setup_background_color (bg_color);
   greeter_session_init ();
-  greeter_language_initialize_model ();
+  gdm_lang_initialize_model ();
 
   ve_signal_add (SIGHUP, greeter_reread_config, NULL);
 
--- gdm-2.17.8/gui/greeter/greeter_action_language.c.orig	2007-03-29 12:09:40.019123000 +0900
+++ gdm-2.17.8/gui/greeter/greeter_action_language.c	2007-03-30 10:30:23.949144000 +0900
@@ -1,507 +0,0 @@
-/* GDM - The GNOME Display Manager
- * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
- *
- * 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 <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <string.h>
-
-#include "gdm.h"
-#include "gdmwm.h"
-#include "gdmcommon.h"
-#include "gdmconfig.h"
-#include "gdmlanguages.h"
-
-#include "greeter.h"
-#include "greeter_configuration.h"
-#include "greeter_item_pam.h"
-#include "greeter_action_language.h"
-#include "greeter_parser.h"
-#include "greeter_item_customlist.h"
-
-#define LAST_LANGUAGE "Last"
-#define DEFAULT_LANGUAGE "Default"
-
-static GtkWidget    *tv                       = NULL;
-static GtkListStore *lang_model               = NULL;
-static GtkWidget    *dialog                   = NULL;
-static gchar        *current_language         = NULL;
-static gchar        *dialog_selected_language = NULL;
-static gint          savelang                 = GTK_RESPONSE_NO;
-static gboolean      always_restart           = FALSE;
-
-GtkListStore *
-greeter_language_get_model (void)
-{
-   return lang_model;
-}
-
-void
-greeter_language_initialize_model (void)
-{
-  GList *list, *li;
-  GtkTreeIter iter;
-
-  list = gdm_lang_read_locale_file (gdm_config_get_string (GDM_KEY_LOCALE_FILE));
-
-  lang_model = gtk_list_store_new (NUM_COLUMNS,
-				   G_TYPE_STRING,
-				   G_TYPE_STRING,
-				   G_TYPE_STRING);
-
-  gtk_list_store_append (lang_model, &iter);
-  gtk_list_store_set (lang_model, &iter,
-		      TRANSLATED_NAME_COLUMN, _("Last language"),
-		      UNTRANSLATED_NAME_COLUMN, NULL,
-		      LOCALE_COLUMN, LAST_LANGUAGE,
-		      -1);
-
-  gtk_list_store_append (lang_model, &iter);
-  gtk_list_store_set (lang_model, &iter,
-		      TRANSLATED_NAME_COLUMN, _("System Default"),
-		      UNTRANSLATED_NAME_COLUMN, NULL,
-		      LOCALE_COLUMN, DEFAULT_LANGUAGE,
-		      -1);
-
-  for (li = list; li != NULL; li = li->next)
-    {
-      char *lang = li->data;
-      char *name;
-      char *untranslated;
-
-      li->data = NULL;
-
-      name = gdm_lang_name (lang,
-			    FALSE /* never_encoding */,
-			    TRUE /* no_group */,
-			    FALSE /* untranslated */,
-			    FALSE /* markup */);
-
-      untranslated = gdm_lang_untranslated_name (lang,
-						 TRUE /* markup */);
-
-      gtk_list_store_append (lang_model, &iter);
-      gtk_list_store_set (lang_model, &iter,
-			  TRANSLATED_NAME_COLUMN, name,
-			  UNTRANSLATED_NAME_COLUMN, untranslated,
-			  LOCALE_COLUMN, lang,
-			  -1);
-
-      g_free (name);
-      g_free (untranslated);
-      g_free (lang);
-    }
-  g_list_free (list);
-}
-
-gint
-greeter_language_get_save_language (void)
-{
-  return savelang;
-}
-
-gchar *
-greeter_language_get_language (const char *old_language)
-{
-  gchar *retval = NULL;
-
-  /* Don't save language unless told otherwise */
-  savelang = GTK_RESPONSE_NO;
-
-  if (old_language == NULL)
-    old_language = "";
-
-  /* If a different language is selected */
-  if (current_language != NULL && strcmp (current_language, LAST_LANGUAGE) != 0)
-    {
-      if (strcmp (current_language, DEFAULT_LANGUAGE) == 0)
-	retval = g_strdup ("");
-      else
-        retval = g_strdup (current_language);
-
-      /* User's saved language is not the chosen one */
-      if (strcmp (old_language, retval) != 0)
-	{
-	  gchar *primary_message;
-	  gchar *secondary_message;
-	  char *current_name, *saved_name;
-
-	  if (strcmp (current_language, DEFAULT_LANGUAGE) == 0)
-	    current_name = g_strdup (_("System Default"));
-	  else
-	    current_name = gdm_lang_name (current_language,
-					  FALSE /* never_encoding */,
-					  TRUE /* no_group */,
-					  TRUE /* untranslated */,
-					  TRUE /* markup */);
-	  if (strcmp (old_language, "") == 0)
-	    saved_name = g_strdup (_("System Default"));
-	  else
-	    saved_name = gdm_lang_name (old_language,
-					FALSE /* never_encoding */,
-					TRUE /* no_group */,
-					TRUE /* untranslated */,
-					TRUE /* markup */);
-
-	  primary_message = g_strdup_printf (_("Do you wish to make %s the default for future sessions?"),
-	                                     current_name);
- 	  secondary_message = g_strdup_printf (_("You have chosen %s for this session, but your default setting is "
-	                                         "%s."), current_name, saved_name);
-	  g_free (current_name);
-	  g_free (saved_name);
-
-	  savelang = gdm_wm_query_dialog (primary_message, secondary_message,
-		_("Make _Default"), _("Just For _This Session"), TRUE);
-	  g_free (primary_message);
-	  g_free (secondary_message);
-	}
-    }
-  else
-    {
-      retval = g_strdup (old_language);
-    }
-
-  return retval;
-}
-
-static void
-selection_changed (GtkTreeSelection *selection,
-		   gpointer          data)
-{
-  GtkTreeIter iter;
-
-  if (gtk_tree_selection_get_selected (selection, NULL, &iter))
-    {
-      g_free (dialog_selected_language);
-      gtk_tree_model_get (GTK_TREE_MODEL (lang_model), &iter, LOCALE_COLUMN, &dialog_selected_language, -1);
-    }
-}
-
-static void
-tree_row_activated (GtkTreeView         *view,
-                    GtkTreePath         *path,
-                    GtkTreeViewColumn   *column,
-                    gpointer            data)
-{
-  GtkTreeIter iter;
-  if (gtk_tree_model_get_iter (GTK_TREE_MODEL (lang_model), &iter, path))
-    {
-      g_free (dialog_selected_language);
-      gtk_tree_model_get (GTK_TREE_MODEL (lang_model), &iter,
-			  LOCALE_COLUMN, &dialog_selected_language,
-			  -1);
-      gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-  }
-}
-
-static void
-greeter_language_setup_treeview (void)
-{
-  if (dialog == NULL)
-    {
-      GtkWidget *main_vbox;
-      GtkWidget *button;
-      GtkWidget **tmp_p;
-      GtkWidget *swindow;
-      GtkWidget *label;
-      char *s;
-
-      dialog = gtk_dialog_new_with_buttons (_("Select a Language"),
-#ifdef TODO
-					    GTK_WINDOW (parent_window),
-#endif
-					    NULL,
-					    0,
-					    GTK_STOCK_CANCEL,
-					    GTK_RESPONSE_CANCEL,
-					    NULL);
-					    
-      button = gtk_button_new_with_mnemonic (_("Change _Language"));
-      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
-      gtk_widget_show (button);
-      gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
-                                    GTK_RESPONSE_OK);
-					    
-      gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-      gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
-      gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 2);
-
-      main_vbox = gtk_vbox_new (FALSE, 6);
-      gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 5);
-      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
-                          main_vbox, TRUE, TRUE, 0);
-  
-      gtk_dialog_set_default_response (GTK_DIALOG (dialog),
-				       GTK_RESPONSE_OK);
-      /* evil gcc warnings */
-      tmp_p = &dialog;
-      g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *)tmp_p);
-      s = g_strdup (_("_Select the language for your session to use:"));
-      label = gtk_label_new_with_mnemonic (s);
-      gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-      g_free (s);
-      gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-      gtk_box_pack_start (GTK_BOX (main_vbox),
-			  label, FALSE, FALSE, 0);
-      tv = gtk_tree_view_new ();
-      gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tv), TRUE);
-      gtk_label_set_mnemonic_widget (GTK_LABEL (label), tv);
-      /* FIXME: we should handle this better, but things really look
-       * bad if we aren't always LTR */
-      gtk_widget_set_direction (tv, GTK_TEXT_DIR_LTR);
-      gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tv), FALSE);
-      gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
-					       GTK_DIALOG_MODAL,
-					       NULL,
-					       gtk_cell_renderer_text_new (),
-					       "text", TRANSLATED_NAME_COLUMN,
-					       NULL);
-      gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
-					       GTK_DIALOG_MODAL,
-					       NULL,
-					       gtk_cell_renderer_text_new (),
-					       "markup",
-					       UNTRANSLATED_NAME_COLUMN,
-					       NULL);
-      swindow = gtk_scrolled_window_new (NULL, NULL);
-      gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow), GTK_SHADOW_IN);
-      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
-				  GTK_POLICY_AUTOMATIC,
-				  GTK_POLICY_AUTOMATIC);
-      gtk_container_add (GTK_CONTAINER (swindow), tv);
-      gtk_box_pack_start (GTK_BOX (main_vbox),
-			  swindow, TRUE, TRUE, 0);
-      gtk_window_set_default_size (GTK_WINDOW (dialog),
-				   MIN (400, gdm_wm_screen.width),
-				   MIN (600, gdm_wm_screen.height));
-      g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (tv))),
-			"changed",
-			(GCallback) selection_changed,
-			NULL);
-      g_signal_connect (G_OBJECT (tv),
-                        "row_activated",
-                        (GCallback) tree_row_activated,
-                        NULL);
-      gtk_tree_view_set_model (GTK_TREE_VIEW (tv),
-			       GTK_TREE_MODEL (lang_model));
-    }
-}
-
-static gint
-greeter_language_ask_restart (gchar *language, GreeterItemInfo *info)
-{
-	GtkWidget *dialog;
-	gchar *firstmsg;
-	gchar *secondmsg;
-	gchar *login;
-	gint response = GTK_RESPONSE_NO;
-
-	if (always_restart)
-		return GTK_RESPONSE_YES;
-
-	login = _("the login screen");
-	firstmsg = g_strdup_printf (_("Do you wish to restart %s with the chosen language?"),
-	                            login);
-	secondmsg = g_strdup_printf (_("You will restart %s with the %s locale."),
-	                             login,
-	                             language);
-
-	response = gdm_wm_query_dialog (firstmsg, secondmsg, _("_Yes"), _("_No"), FALSE);
-
-	g_free (firstmsg);
-	g_free (secondmsg);
-
-	return response;
-}
-
-static gboolean
-greeter_language_get_restart_state (void)
-{
-  return  always_restart;
-}
-
-static void
-greeter_language_set_restart_state (gboolean do_restart)
-{
-  always_restart = do_restart;
-}
-
-static void
-greeter_language_restart_handler (GtkMenuItem *menu_item, gpointer user_data)
-{
-  if ((int)user_data == ALWAYS_RESTART)
-    always_restart = TRUE;
-  else
-    always_restart = FALSE;
-}
-
-void
-greeter_language_set (char *language)
-{
-   char *locale;
-   GtkTreeSelection *selection;
-   GtkTreeIter iter = {0};
-
-   g_free (current_language);
-   current_language = g_strdup (language);
-
-   if (dialog == NULL)
-     greeter_language_setup_treeview ();
-
-   if (language == NULL)
-      return;
- 
-   greeter_custom_set_language (language);
-
-   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
-   gtk_tree_selection_unselect_all (selection);
-
-   if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (lang_model), &iter)) {
-      do {
-         gtk_tree_model_get (GTK_TREE_MODEL (lang_model), &iter, LOCALE_COLUMN, &locale, -1);
-         if (locale != NULL && strcmp (locale, language) == 0) {
-            GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (lang_model), &iter);
-
-            gtk_tree_selection_select_iter (selection, &iter);
-            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tv), path, NULL, FALSE, 0.0, 0.0);
-            gtk_tree_path_free (path);
-            break;
-         }
-      } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (lang_model), &iter));
-   }
-}
-
-/*
- * The button with this handler appears in the F10 menu, so it
- * cannot depend on callback data being passed in.
- */
-void
-greeter_language_handler (GreeterItemInfo *info, gpointer user_data)
-{
-  if (dialog == NULL)
-    greeter_language_setup_treeview ();
-
-  gtk_widget_show_all (dialog);
-  gdm_wm_center_window (GTK_WINDOW (dialog));
-
-  gdm_wm_no_login_focus_push ();
-  if (tv != NULL)
-    {
-      GtkTreeSelection *selection;
-	  
-      gtk_widget_show_now (dialog);
-      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
-      if (selection == NULL)
-	gtk_tree_selection_select_path (selection, gtk_tree_path_new_first ());
-      else
-        {
-          GtkTreeIter iter;
-          GtkTreePath *path;
-          GtkTreeModel *tm = GTK_TREE_MODEL (lang_model);
-
-          gtk_tree_selection_get_selected (selection, &tm, &iter);
-          path = gtk_tree_model_get_path (GTK_TREE_MODEL (lang_model), &iter);
-          gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tv), path, NULL, FALSE, 0.0, 0.0);
-          gtk_tree_path_free (path);
-        }
-    }
-  switch (gtk_dialog_run (GTK_DIALOG (dialog)))
-    {
-    case GTK_RESPONSE_OK:
-      if (dialog_selected_language)
-        {
-          gint response = greeter_language_get_restart_state () ?
-                          GTK_RESPONSE_YES : GTK_RESPONSE_NO;
-
-          if (strcmp (dialog_selected_language, LAST_LANGUAGE))
-             response = greeter_language_ask_restart (dialog_selected_language,
-                                                     info);
-          greeter_language_set ((char *) dialog_selected_language);
-          if (strcmp (dialog_selected_language, LAST_LANGUAGE)
-              && (response != GTK_RESPONSE_YES))
-            {
-              printf ("%c%c%c%c%s\n", STX,
-                                      BEL,
-                                      GDM_INTERRUPT_SELECT_LANG,
-                                      response == GTK_RESPONSE_YES ? 1 : 0,
-                                      dialog_selected_language);
-              fflush (stdout);
-            }
-        }
-      break;
-    case GTK_RESPONSE_CANCEL:
-    default:
-      break;
-    }
-
-  gdm_wm_no_login_focus_pop ();
-
-  if (dialog)
-    gtk_widget_hide (dialog);
-}
-
-int
-greeter_language_op_lang (const gchar *args)
-{
-  gchar *language = greeter_language_get_language (args);
-
-  if (greeter_language_get_save_language () == GTK_RESPONSE_CANCEL)
-    printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL);
-  else
-    printf ("%c%s\n", STX, language);
-  fflush (stdout);
-  g_free (language);
-
-  return 0;
-}
-
-int
-greeter_language_op_slang (const gchar *args)
-{
-  if (greeter_language_get_save_language () == GTK_RESPONSE_YES)
-    printf ("%cY\n", STX);
-  else
-    printf ("%c\n", STX);
-  fflush (stdout);
-
-  return 0;
-}
-
-int
-greeter_language_op_setlang (const gchar *args)
-{
-  if (args)
-    greeter_language_set ((char*)args);
-  printf ("%c\n", STX);
-  fflush (stdout);
-
-  return 0;
-}
-
-int
-greeter_language_op_always_restart (const gchar *args)
-{
-  greeter_language_set_restart_state (TRUE);
-
-  printf ("%c\n", STX);
-  fflush (stdout);
-
-  return 0;
-}
-
--- gdm-2.17.8/gui/greeter/greeter_action_language.h.orig	2007-03-29 14:28:53.590872000 +0900
+++ gdm-2.17.8/gui/greeter/greeter_action_language.h	2007-03-30 10:29:17.772832000 +0900
@@ -1,48 +0,0 @@
-/* GDM - The GNOME Display Manager
- * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
- *
- * 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 __GREETER_ACTION_LANGUAGE_H__
-#define __GREETER_ACTION_LANGUAGE_H__
-
-#include "greeter_item.h"
-
-enum {
-  LOCALE_COLUMN,
-  TRANSLATED_NAME_COLUMN,
-  UNTRANSLATED_NAME_COLUMN,
-  NUM_COLUMNS
-};
-
-enum {
-  ASK_RESTART = 0,
-  ALWAYS_RESTART
-};
-
-void      greeter_language_initialize_model  (void);
-gint      greeter_language_get_save_language (void);
-gchar    *greeter_language_get_language      (const char      *old_language);
-void      greeter_language_handler           (GreeterItemInfo *info,
-					      gpointer user_data);
-GtkListStore *greeter_language_get_model     (void);
-void      greeter_language_set               (char *language);
-int       greeter_language_op_lang           (const gchar *args);
-int       greeter_language_op_slang          (const gchar *args);
-int       greeter_language_op_setlang        (const gchar *args);
-int       greeter_language_op_always_restart (const gchar *args);
-#endif
-
--- gdm-2.17.8/gui/greeter/greeter_item_customlist.c.orig	2007-03-29 14:55:23.002382000 +0900
+++ gdm-2.17.8/gui/greeter/greeter_item_customlist.c	2007-03-29 16:19:11.230971000 +0900
@@ -24,6 +24,7 @@
 #include "gdm.h"
 #include "gdmconfig.h"
 #include "gdmsession.h"
+#include "gdmlanguages.h"
 
 #include "greeter_item.h"
 #include "greeter_configuration.h"
@@ -160,7 +161,7 @@ greeter_custom_set_session (gchar *sessi
 void
 greeter_custom_set_language (gchar *language)
 {
-  GtkListStore *lang_model = greeter_language_get_model ();
+  GtkListStore *lang_model = gdm_lang_get_model ();
   GtkTreeIter iter;
   gboolean valid;
   char *locale_name;
@@ -310,7 +311,7 @@ populate_session (GObject * object)
 static void
 populate_language (GObject *object)
 {
-  GtkListStore *lang_model = greeter_language_get_model ();
+  GtkListStore *lang_model = gdm_lang_get_model ();
   GtkTreeIter iter;
   char *name, *untranslated, *display_name, *locale_name;
   gboolean valid;
@@ -407,7 +408,7 @@ combo_selected (GtkComboBox *combo, Gree
        * Since combo boxes can't store the ID value, have to do some
        * extra work to figure out which row is selected.
        */
-      GtkListStore *lang_model = greeter_language_get_model ();
+      GtkListStore *lang_model = gdm_lang_get_model ();
       GtkTreeIter iter;
       char *name, *untranslated, *display_name, *locale_name;
       gboolean valid;
@@ -428,7 +429,7 @@ combo_selected (GtkComboBox *combo, Gree
 
           if (strcmp (display_name, active) == 0)
             {
-              greeter_language_set (locale_name);
+              gdm_lang_set (locale_name);
               break;
             }
           g_free (display_name);
@@ -518,7 +519,7 @@ list_selected (GtkTreeSelection *selecti
   else if (strcmp (item->id, "language") == 0)
     {
       if (id != NULL)
-        greeter_language_set (id);
+        gdm_lang_set (id);
     }
   else
     {
