--- gdm-2.17.4/daemon/gdm.h.orig	2007-01-11 15:19:28.435011000 +0900
+++ gdm-2.17.4/daemon/gdm.h	2007-02-01 21:27:19.976259000 +0900
@@ -100,6 +100,7 @@ enum {
 #define GDM_LANG       '&'
 #define GDM_SSESS      'C'
 #define GDM_SLANG      'R'
+#define GDM_SETLANG    'L'
 #define GDM_RESET      'A'
 #define GDM_QUIT       'P'
 /* Well these aren't as nice as above, oh well */
@@ -119,6 +120,7 @@ enum {
 #define GDM_FOCUS      'F' /* Allow focus on the login window again (optional) */
 #define GDM_SAVEDIE    '!' /* Save wm order and die (and set busy cursor) */
 #define GDM_QUERY_CAPSLOCK 'Q' /* Is capslock on? */
+#define GDM_ALWAYS_RESTART 'W' /* Retart greeter when the user accepts restarts */
 
 /* Different login interruptions */
 #define GDM_INTERRUPT_TIMED_LOGIN 'T'
@@ -129,6 +131,7 @@ enum {
 #define GDM_INTERRUPT_THEME       'H'
 #define GDM_INTERRUPT_CUSTOM_CMD  'M'
 #define GDM_INTERRUPT_CANCEL      'X'
+#define GDM_INTERRUPT_SELECT_LANG 'O'
 
 /* List delimiter for config file lists */
 #define GDM_DELIMITER_MODULES ":"
--- gdm-2.17.4/daemon/misc.c.orig	2007-01-11 15:35:43.139943000 +0900
+++ gdm-2.17.4/daemon/misc.c	2007-01-11 17:24:04.751480000 +0900
@@ -2183,6 +2183,17 @@ gdm_reset_locale (void)
     gsize i18n_file_length, i;
     GString *line;
     const gchar *p, *q;
+    gchar *gdmlang = g_getenv ("GDM_LANG");
+
+    if (gdmlang)
+      {
+	g_setenv ("LANG", gdmlang, TRUE);
+	g_unsetenv ("LC_ALL");
+	g_unsetenv ("LC_MESSAGES");
+	setlocale (LC_ALL, "");
+	setlocale (LC_MESSAGES, "");
+	return;
+      }
 
     i18n_file_contents = NULL;
     line = NULL; 
--- gdm-2.17.4/daemon/slave.c.orig	2007-01-11 15:19:35.143520000 +0900
+++ gdm-2.17.4/daemon/slave.c	2007-02-02 11:51:04.840673000 +0900
@@ -113,6 +113,8 @@ static gboolean do_restart_greeter = FAL
 					       greeter and try again */
 static gboolean restart_greeter_now = FALSE; /* restart_greeter_when the
 						SIGCHLD hits */
+static gboolean always_restart_greeter = FALSE; /* Always restart greeter when
+						   the user accepts restarts. */
 static gboolean gdm_wait_for_ack = TRUE; /* wait for ack on all messages to
 				      * the daemon */
 static int in_session_stop = 0;
@@ -214,6 +216,7 @@ enum {
 	JMP_SESSION_STOP_AND_QUIT = 1,
 	JMP_JUST_QUIT_QUICKLY = 2
 };
+#define DEFAULT_LANGUAGE "Default"
 #define SIGNAL_EXIT_WITH_JMP(d,how) \
    {											\
 	if ((d)->slavepid == getpid () && return_to_slave_start_jmp) {			\
@@ -2455,6 +2458,7 @@ gdm_slave_greeter (void)
     char *defaultpath;
     char *gdmuser;
     char *moduleslist;
+    const char *gdmlang;
     
     gdm_debug ("gdm_slave_greeter: Running greeter on %s", d->name);
     
@@ -2712,6 +2716,11 @@ gdm_slave_greeter (void)
 	gdm_debug ("gdm_slave_greeter: Greeter on pid %d", (int)pid);
 
 	gdm_slave_send_num (GDM_SOP_GREETPID, d->greetpid);
+	if (always_restart_greeter)
+	  gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "");
+	gdmlang = g_getenv ("GDM_LANG");
+	if (gdmlang)
+	  gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, gdmlang);
 
 	run_pictures (); /* Append pictures to greeter if browsing is on */
 
@@ -4190,7 +4199,6 @@ gdm_slave_session_start (void)
     }
 
     g_free (usrsess);
-    g_free (usrlang);
 
     gdm_debug ("Initial setting: session: '%s' language: '%s'\n",
 	       session, ve_sure_string (language));
@@ -4368,6 +4376,17 @@ gdm_slave_session_start (void)
 	gdm_assert_not_reached ();
 	
     default:
+	if (!savelang && language && strcmp (usrlang, language)) {
+		if (gdm_system_locale) {
+			g_setenv ("LANG", gdm_system_locale, TRUE);
+			setlocale (LC_ALL, "");
+			g_unsetenv ("GDM_LANG");
+			/* for "GDM_LANG" */
+			gdm_clearenv_no_lang ();
+			gdm_saveenv ();
+		}
+		gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, DEFAULT_LANGUAGE);
+	}
 	break;
     }
     
@@ -4391,6 +4410,7 @@ gdm_slave_session_start (void)
     g_free (session);
     g_free (save_session);
     g_free (language);
+    g_free (usrlang);
     g_free (gnome_session);
 
     gdm_slave_send_num (GDM_SOP_SESSPID, pid);
@@ -5101,6 +5121,25 @@ check_for_interruption (const char *msg)
 				d->theme_name = g_strdup (&msg[2]);
 			gdm_slave_send_string (GDM_SOP_CHOSEN_THEME, &msg[2]);
 			return TRUE;
+		case GDM_INTERRUPT_SELECT_LANG:
+			if (msg + 2) {
+				gchar *locale = (gchar*)(msg + 3);
+
+				always_restart_greeter = (gboolean)(*(msg + 2));
+				gdm_clearenv ();
+				if (!strcmp (locale, DEFAULT_LANGUAGE))
+					locale = gdm_system_locale;
+				g_setenv ("GDM_LANG", locale, TRUE);
+				g_setenv ("LANG", locale, TRUE);
+				g_unsetenv ("LC_ALL");
+				g_unsetenv ("LC_MESSAGES");
+				setlocale (LC_ALL, "");
+				setlocale (LC_MESSAGES, "");
+				gdm_saveenv ();
+
+				do_restart_greeter = TRUE;
+			}
+			break;
 		default:
 			break;
 		}
--- gdm-2.17.4/gui/Makefile.am.orig	2007-01-31 21:51:16.535720000 +0900
+++ gdm-2.17.4/gui/Makefile.am	2007-01-31 22:11:08.224857000 +0900
@@ -82,7 +82,9 @@ gdmchooser_SOURCES = \
 	misc.c			\
 	misc.h			
 
+gdmlogin_CFLAGS = $(GREETER_CFLAGS)
 gdmlogin_SOURCES = \
+	gdmlanguages.c		\
 	gdmlogin.c
 
 gdmsetup_SOURCES = \
@@ -111,6 +113,7 @@ gdmchooser_LDADD = \
 gdmlogin_LDADD = \
 	libgdmwm.a		\
 	libgdmcommon.a		\
+	greeter/libgdmgreeter.a	\
 	$(GUING_LIBS)		\
 	$(INTLLIBS)		\
 	$(GLIB_LIBS)		\
@@ -122,8 +125,14 @@ gdmlogin_LDADD = \
 	$(X_EXTRA_LIBS)		\
 	$(XINERAMA_LIBS)	\
 	$(X_LIBS)		\
+	$(GREETER_LIBS)		\
 	-lX11
 
+greeter/libgdmgreeter.a:
+	cd greeter; \
+	make libgdmgreeter.a; \
+	cd ..
+
 # LIBGNOMEUI should be removed from gdmsetup at some point.
 # It is needed because it uses gnome_help_display_uri(), which
 # should be replaced at some point.
--- gdm-2.17.4/gui/gdmlogin.c.orig	2007-01-11 15:19:40.266947000 +0900
+++ gdm-2.17.4/gui/gdmlogin.c	2007-02-02 11:25:43.233588000 +0900
@@ -59,13 +59,23 @@
 #include "gdmcommon.h"
 #include "gdmsession.h"
 #include "gdmwm.h"
-#include "gdmlanguages.h"
 #include "gdmconfig.h"
 #include "misc.h"
 
+#include "greeter/greeter_action_language.h"
+#include "greeter/greeter_configuration.h"
+
 /* set the DOING_GDM_DEVELOPMENT env variable if you aren't running
  * within the protocol */
-static gboolean DOING_GDM_DEVELOPMENT = FALSE;
+gboolean DOING_GDM_DEVELOPMENT = FALSE;
+gboolean GdmConfiguratorFound  = FALSE;
+gboolean *GdmCustomCmdsFound   = NULL;
+gboolean GdmSuspendFound       = FALSE;
+gboolean GdmHaltFound          = FALSE;
+gboolean GdmRebootFound        = FALSE;
+gboolean GdmAnyCustomCmdsFound = FALSE;
+GreeterItemInfo *welcome_string_info = NULL;
+
 static gboolean browser_ok = TRUE;
 static gboolean disable_sys_config_chooser_buttons = FALSE;
 static gboolean GdmLockPosition = FALSE;
@@ -73,8 +83,6 @@ static gboolean GdmSetPosition = FALSE;
 static gint GdmPositionX;
 static gint GdmPositionY;
 
-#define LAST_LANGUAGE "Last"
-#define DEFAULT_LANGUAGE "Default"
 #define GTK_KEY "gtk-2.0"
 
 enum {
@@ -118,15 +126,12 @@ static GtkTreeModel *browser_model;
 static GdkPixbuf *defface;
 
 /* Eew. Loads of global vars. It's hard to be event controlled while maintaining state */
-static GSList *languages = NULL;
 static GList *users = NULL;
 static GList *users_string = NULL;
 static gint size_of_users = 0;
 
-static const gchar *curlang = NULL;
 static gchar *curuser = NULL;
 static gchar *session = NULL;
-static gchar *language = NULL;
 
 static gint savelang = GTK_RESPONSE_NO;
 
@@ -737,66 +742,6 @@ gdm_theme_handler (GtkWidget *widget, gp
     gdm_wm_center_window (GTK_WINDOW (login));
 }
 
-static void
-gdm_login_language_lookup (const gchar* savedlang)
-{
-    /* Don't save language unless told otherwise */
-    savelang = GTK_RESPONSE_NO;
-
-    if (savedlang == NULL)
-	    savedlang = "";
-
-    /* If a different language is selected */
-    if (curlang != NULL && strcmp (curlang, LAST_LANGUAGE) != 0) {
-        g_free (language);
-	if (strcmp (curlang, DEFAULT_LANGUAGE) == 0)
-		language = g_strdup ("");
-	else
-		language = g_strdup (curlang);
-
-	/* User's saved language is not the chosen one */
-	if (strcmp (savedlang, language) != 0) {
-	    gchar *firstmsg;
-    	    gchar *secondmsg;
-	    char *curname, *savedname;
-
-	    if (strcmp (curlang, DEFAULT_LANGUAGE) == 0) {
-		    curname = g_strdup (_("System Default"));
-	    } else {
-		    curname = gdm_lang_name (curlang,
-					     FALSE /* never_encoding */,
-					     TRUE /* no_group */,
-					     TRUE /* untranslated */,
-					     TRUE /* markup */);
-	    }
-	    if (strcmp (savedlang, "") == 0) {
-		    savedname = g_strdup (_("System Default"));
-	    } else {
-		    savedname = gdm_lang_name (savedlang,
-					       FALSE /* never_encoding */,
-					       TRUE /* no_group */,
-					       TRUE /* untranslated */,
-					       TRUE /* markup */);
-	    }
-
-	    firstmsg = g_strdup_printf (_("Do you wish to make %s the default for future sessions?"),
-	                                curname);
-	    secondmsg = g_strdup_printf (_("You have chosen %s for this session, but your default setting is %s."),
-	                                 curname, savedname);
-	    g_free (curname);
-	    g_free (savedname);
-
-	    savelang = gdm_wm_query_dialog (firstmsg, secondmsg,
-		_("Make _Default"), _("Just For _This Session"), TRUE);
-	    g_free (firstmsg);
-	    g_free (secondmsg);
-	}
-    } else {
-	g_free (language);
-	language = g_strdup (savedlang);
-    }
-}
-
 static int dance_handler = 0;
 
 static gboolean
@@ -1078,26 +1023,9 @@ gdm_login_session_init (GtkWidget *menu)
 
 
 static void 
-gdm_login_language_handler (GtkWidget *widget) 
+gdm_login_language_handler (GtkMenuItem *menu_item, gpointer user_data) 
 {
-    gchar *s;
-    char *name;
-
-    if (!widget)
-	return;
-
-    curlang = g_object_get_data (G_OBJECT (widget), "Language");
-    name = gdm_lang_name (curlang,
-			  FALSE /* never_encoding */,
-			  TRUE /* no_group */,
-			  TRUE /* untranslated */,
-			  TRUE /* makrup */);
-    s = g_strdup_printf (_("%s language selected"), name);
-    g_free (name);
-    gtk_label_set_markup (GTK_LABEL (msg), s);
-    g_free (s);
-
-    login_window_resize (FALSE /* force */);
+    greeter_language_handler (NULL, NULL);
 }
 
 
@@ -1105,174 +1033,26 @@ static GtkWidget *
 gdm_login_language_menu_new (void)
 {
     GtkWidget *menu;
-    GtkWidget *item, *ammenu, *nzmenu, *omenu;
-    GList *langlist, *li;
-    gboolean has_other_locale = FALSE;
-    GtkWidget *other_menu;
-    const char *g1;
-    const char *g2;
-    char *menulabel;
-    /* Start numbering with 3 since 1-2 is used for toplevel menu */
-    int g1_num = 3;
-    int g2_num = 3;
-    int other_num = 3;
-    int num;
-
-    langlist = gdm_lang_read_locale_file (gdm_config_get_string (GDM_KEY_LOCALE_FILE));
+    GtkWidget *item;
+    GSList *restart_grp = NULL;
 
-    if (langlist == NULL)
-	    return NULL;
+    greeter_language_initialize_model ();
 
     menu = gtk_menu_new ();
 
-    curlang = LAST_LANGUAGE;
-
-    item = gtk_radio_menu_item_new_with_mnemonic (NULL, _("_Last"));
-    languages = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-    g_signal_connect (G_OBJECT (item), "activate", 
-		      G_CALLBACK (gdm_login_language_handler), 
-		      NULL);
-    gtk_widget_show (GTK_WIDGET (item));
-    g_object_set_data (G_OBJECT (item),
-		       "Language",
-		       LAST_LANGUAGE);
-
-    item = gtk_radio_menu_item_new_with_mnemonic (languages, _("_System Default"));
-    languages = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
+    item = gtk_menu_item_new_with_mnemonic (_("Select _Language..."));
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     g_signal_connect (G_OBJECT (item), "activate", 
 		      G_CALLBACK (gdm_login_language_handler), 
 		      NULL);
     gtk_widget_show (GTK_WIDGET (item));
-    g_object_set_data (G_OBJECT (item),
-		       "Language",
-		       DEFAULT_LANGUAGE);
 
     item = gtk_menu_item_new ();
     gtk_widget_set_sensitive (item, FALSE);
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show (GTK_WIDGET (item));
 
-    menulabel = g_strdup_printf ("_1. %s", gdm_lang_group1());
-    item = gtk_menu_item_new_with_mnemonic (menulabel);
-    g_free (menulabel);
-    ammenu = gtk_menu_new ();
-    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), GTK_WIDGET (ammenu));
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-    gtk_widget_show (GTK_WIDGET (item));
-
-    menulabel = g_strdup_printf ("_2. %s", gdm_lang_group2());
-    item = gtk_menu_item_new_with_mnemonic (menulabel);
-    g_free (menulabel);
-    nzmenu = gtk_menu_new ();
-    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), nzmenu);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-    gtk_widget_show (GTK_WIDGET (item));
-
-    other_menu = item = gtk_menu_item_new_with_mnemonic (_("_Other"));
-    omenu = gtk_menu_new ();
-    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), omenu);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-    gtk_widget_show (GTK_WIDGET (item));
-
-    g1 = gdm_lang_group1 ();
-    g2 = gdm_lang_group2 ();
-
-    for (li = langlist; li != NULL; li = li->next) {
-	    char *lang = li->data;
-	    char *name;
-	    char *untranslated;
-	    char *group;
-	    char *p;
-	    GtkWidget *box, *l;
-
-	    li->data = NULL;
-
-	    group = name = gdm_lang_name (lang,
-					  FALSE /* never_encoding */,
-					  FALSE /* no_group */,
-					  FALSE /* untranslated */,
-					  FALSE /* markup */);
-	    if (name == NULL) {
-		    g_free (lang);
-		    continue;
-	    }
-
-	    untranslated = gdm_lang_untranslated_name (lang,
-						       TRUE /* markup */);
-
-	    p = strchr (name, '|');
-	    if (p != NULL) {
-		    *p = '\0';
-		    name = p+1;
-	    }
-
-	    box = gtk_hbox_new (FALSE, 5);
-	    gtk_widget_show (box);
-
-	    if (strcmp (group, g1) == 0)
-		num = g1_num++;
-	    else if (strcmp (group, g2) == 0)
-                num = g2_num++;
-	    else
-		num = other_num++;
-
-	    if (num < 10)
-		menulabel = g_strdup_printf ("_%d. %s", num, name);
-	    else if ((num -10) + (int)'a' <= (int)'z')
-		menulabel = g_strdup_printf ("_%c. %s",
-                                                  (char)(num-10)+'a',
-                                                  name);
-	    else
-		menulabel = g_strdup (name);
-
-	    l = gtk_label_new_with_mnemonic (menulabel);
-	    if ( ! gdm_lang_name_translated (lang))
-		    gtk_widget_set_direction (l, GTK_TEXT_DIR_LTR);
-	    gtk_widget_show (l);
-	    gtk_box_pack_start (GTK_BOX (box), l, FALSE, FALSE, 0);
-
-	    if (untranslated != NULL) {
-		    l = gtk_label_new (untranslated);
-		    /* we really wantd LTR here for the widget */
-		    gtk_widget_set_direction (l, GTK_TEXT_DIR_LTR);
-		    gtk_label_set_use_markup (GTK_LABEL (l), TRUE);
-		    gtk_widget_show (l);
-		    gtk_box_pack_end (GTK_BOX (box), l, FALSE, FALSE, 0);
-	    }
-
-	    item = gtk_radio_menu_item_new (languages);
-	    gtk_container_add (GTK_CONTAINER (item), box);
-	    languages = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
-	    g_object_set_data_full (G_OBJECT (item),
-				    "Language",
-				    g_strdup (lang),
-				    (GDestroyNotify) g_free);
-
-	    if (strcmp (group, g1) == 0) {
-		    gtk_menu_shell_append (GTK_MENU_SHELL (ammenu), item);
-	    } else if (strcmp (group, g2) == 0) {
-		    gtk_menu_shell_append (GTK_MENU_SHELL (nzmenu), item);
-	    } else {
-		    gtk_menu_shell_append (GTK_MENU_SHELL (omenu), item);
-		    has_other_locale = TRUE;
-	    }
-
-	    g_signal_connect (G_OBJECT (item), "activate", 
-			      G_CALLBACK (gdm_login_language_handler), 
-			      NULL);
-	    gtk_widget_show (GTK_WIDGET (item));
-
-	    g_free (lang);
-	    g_free (group);
-	    g_free (untranslated);
-    }
-    if ( ! has_other_locale) 
-	    gtk_widget_destroy (other_menu);
-
-    g_list_free (langlist);
-
+    greeter_language_append_restart_menu (menu, NULL, NULL);
     return menu;
 }
 
@@ -1766,12 +1546,7 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_LANG:
-	gdm_login_language_lookup (args);
-	if (savelang == GTK_RESPONSE_CANCEL)
-	    printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL);
-	else
-	    printf ("%c%s\n", STX, language);
-	fflush (stdout);
+	greeter_language_op_lang (args);
 	break;
 
     case GDM_SSESS:
@@ -1784,12 +1559,15 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_SLANG:
-	if (savelang == GTK_RESPONSE_YES)
-	    printf ("%cY\n", STX);
-	else
-	    printf ("%c\n", STX);
-	fflush (stdout);
+	greeter_language_op_slang (args);
+	break;
+
+    case GDM_SETLANG:
+	greeter_language_op_setlang (args);
+	break;
 
+    case GDM_ALWAYS_RESTART:
+	greeter_language_op_always_restart (args);
 	break;
 
     case GDM_RESET:
--- gdm-2.17.4/gui/greeter/Makefile.am.orig	2007-01-31 21:43:41.342258000 +0900
+++ gdm-2.17.4/gui/greeter/Makefile.am	2007-01-31 22:04:36.936681000 +0900
@@ -90,6 +90,20 @@ gdmgreeter_LDADD = \
 	$(X_LIBS)		\
 	-lX11
 
+libgdmgreeter_a_SOURCES = \
+	greeter_action_language.c	\
+	greeter_events.c		\
+	greeter_item.c			\
+	greeter_item_customlist.c	\
+	greeter_parser.c		\
+	greeter_session.c
+
+noinst_LIBRARIES = \
+	libgdmgreeter.a
+
+EXTRA_LIBRARIES = \
+	libgdmgreeter.a
+
 EXTRA_DIST = \
 	gdmthemetester.in \
 	greeter.dtd
--- gdm-2.17.4/gui/greeter/greeter.c.orig	2007-01-11 15:19:45.833166000 +0900
+++ gdm-2.17.4/gui/greeter/greeter.c	2007-02-02 11:37:34.497509000 +0900
@@ -172,7 +172,6 @@ process_operation (guchar       op_code,
     char *session;
     GreeterItemInfo *conversation_info;
     static GnomeCanvasItem *disabled_cover = NULL;
-    gchar *language;
     gchar *selected_user = NULL;
     gint lookup_status = SESSION_LOOKUP_SUCCESS;
     gchar *firstmsg = NULL;
@@ -347,13 +346,7 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_LANG:
-	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);
+	greeter_language_op_lang (args);
 	break;
 
     case GDM_SSESS:
@@ -366,12 +359,15 @@ process_operation (guchar       op_code,
 	break;
 
     case GDM_SLANG:
-	if (greeter_language_get_save_language () == GTK_RESPONSE_YES)
-	    printf ("%cY\n", STX);
-	else
-	    printf ("%c\n", STX);
-	fflush (stdout);
+	greeter_language_op_slang (args);
+	break;
+
+    case GDM_SETLANG:
+	greeter_language_op_setlang (args);
+	break;
 
+    case GDM_ALWAYS_RESTART:
+	greeter_language_op_always_restart (args);
 	break;
 
     case GDM_RESET:
--- gdm-2.17.4/gui/greeter/greeter_action_language.c.orig	2007-01-11 15:19:50.921571000 +0900
+++ gdm-2.17.4/gui/greeter/greeter_action_language.c	2007-02-02 11:13:13.150740000 +0900
@@ -41,9 +41,11 @@
 static GtkWidget    *tv                       = NULL;
 static GtkListStore *lang_model               = NULL;
 static GtkWidget    *dialog                   = NULL;
+static GtkWidget    *restart_item             = 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)
@@ -302,6 +304,56 @@ greeter_language_setup_treeview (void)
     }
 }
 
+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 = info ? _("greeter") : _("login");
+	firstmsg = g_strdup_printf (_("Do you accept to restart %s to change the "
+	                              "locale of %s next time?"),
+	                            login,
+	                            login);
+	secondmsg = g_strdup_printf (_("Now you are restarting %s for %s locale."),
+	                             login,
+	                             language);
+
+	response = gdm_wm_query_dialog (firstmsg, secondmsg, _("Make _Default"), _("Just For _This Time"), TRUE);
+
+	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)
 {
@@ -375,7 +427,26 @@ greeter_language_handler (GreeterItemInf
     {
     case GTK_RESPONSE_OK:
       if (dialog_selected_language)
-        greeter_language_set ((char *) 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);
+          if (response != GTK_RESPONSE_CANCEL)
+            greeter_language_set ((char *) dialog_selected_language);
+          if (strcmp (dialog_selected_language, LAST_LANGUAGE)
+              && (response != GTK_RESPONSE_CANCEL))
+            {
+              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:
@@ -388,3 +459,93 @@ greeter_language_handler (GreeterItemInf
     gtk_widget_hide (dialog);
 }
 
+int
+greeter_language_append_restart_menu (const GtkWidget *menu,
+                                      GtkWidget **item1, 
+                                      GtkWidget **item2)
+{
+  GtkWidget *stop_item;
+  GSList *restart_grp = NULL;
+
+  g_return_val_if_fail (menu != NULL, NULL);
+
+  restart_item = gtk_radio_menu_item_new_with_mnemonic (NULL,
+                                                        _("Always _Restart Login Dialog"));
+  restart_grp = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (restart_item));
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), restart_item);
+  g_signal_connect (G_OBJECT (restart_item), "activate",
+                    G_CALLBACK (greeter_language_restart_handler),
+                    ALWAYS_RESTART);
+  gtk_widget_show (GTK_WIDGET (restart_item));
+
+  stop_item = gtk_radio_menu_item_new_with_mnemonic (restart_grp,
+                                                     _("Ask _To Restart Login Dialog"));
+  restart_grp = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (stop_item));
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), stop_item);
+  g_signal_connect (G_OBJECT (stop_item), "activate",
+                    G_CALLBACK (greeter_language_restart_handler),
+                    ASK_RESTART);
+  gtk_widget_show (GTK_WIDGET (stop_item));
+
+  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (stop_item), TRUE);
+
+  if (item1)
+    *item1 = restart_item;
+  if (item2)
+    *item2 = stop_item;
+
+  return 0;
+}
+
+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);
+  if (restart_item)
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (restart_item),
+                                    TRUE);
+
+  printf ("%c\n", STX);
+  fflush (stdout);
+
+  return 0;
+}
+
--- gdm-2.17.4/gui/greeter/greeter_action_language.h.orig	2007-01-31 19:12:26.216310000 +0900
+++ gdm-2.17.4/gui/greeter/greeter_action_language.h	2007-02-02 11:40:20.527034000 +0900
@@ -28,6 +28,11 @@ enum {
   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);
@@ -35,5 +40,12 @@ void      greeter_language_handler      
 					      gpointer user_data);
 GtkListStore *greeter_language_get_model     (void);
 void      greeter_language_set               (char *language);
+int       greeter_language_append_restart_menu (const GtkWidget	        *menu,
+                                                GtkWidget              **item1,
+                                                GtkWidget              **item2);
+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.4/gui/greeter/greeter_canvas_item.c.orig	2007-02-02 10:58:28.629556000 +0900
+++ gdm-2.17.4/gui/greeter/greeter_canvas_item.c	2007-02-02 11:50:15.480161000 +0900
@@ -35,6 +35,7 @@
 #include "greeter_configuration.h"
 #include "greeter_canvas_text.h"
 #include "greeter_parser.h"
+#include "greeter_action_language.h"
 
 /* Keep track of buttons so they can be set sensitive/insensitive */
 GtkButton *gtk_ok_button = NULL;
@@ -169,6 +170,8 @@ make_menubar (void)
 			  G_CALLBACK (activate_button),
 			  "session_button");
 
+	greeter_language_append_restart_menu (menu, NULL, NULL);
+
 	greeter_system_append_system_menu (menu);
 
 	/* Add a quit/disconnect item when in xdmcp mode or flexi mode */
