gnome-terminal r3157 - trunk/src



Author: chpe
Date: Sat Oct 11 21:15:52 2008
New Revision: 3157
URL: http://svn.gnome.org/viewvc/gnome-terminal?rev=3157&view=rev

Log:
Bug 555824 â gnome-terminal's character encoding menu not updated
Update the encoding menus when the list changes.

Modified:
   trunk/src/terminal-app.c
   trunk/src/terminal-app.h
   trunk/src/terminal-encoding.c
   trunk/src/terminal-encoding.h
   trunk/src/terminal-window.c

Modified: trunk/src/terminal-app.c
==============================================================================
--- trunk/src/terminal-app.c	(original)
+++ trunk/src/terminal-app.c	Sat Oct 11 21:15:52 2008
@@ -75,6 +75,7 @@
 
   void (* quit) (TerminalApp *app);
   void (* profile_list_changed) (TerminalApp *app);
+  void (* encoding_list_changed) (TerminalApp *app);
 };
 
 struct _TerminalApp
@@ -93,6 +94,7 @@
   GConfClient *conf;
   guint profile_list_notify_id;
   guint default_profile_notify_id;
+  guint encoding_list_notify_id;
   guint system_font_notify_id;
   guint enable_mnemonics_notify_id;
   guint enable_menu_accels_notify_id;
@@ -102,6 +104,9 @@
   TerminalProfile *default_profile;
   gboolean default_profile_locked;
 
+  GHashTable *encodings;
+  gboolean encodings_locked;
+
   PangoFontDescription *system_font_desc;
   gboolean enable_mnemonics;
   gboolean enable_menu_accels;
@@ -122,6 +127,7 @@
 {
   QUIT,
   PROFILE_LIST_CHANGED,
+  ENCODING_LIST_CHANGED,
   LAST_SIGNAL
 };
 
@@ -148,6 +154,8 @@
 #define PROFILE_LIST_KEY CONF_GLOBAL_PREFIX "/profile_list"
 #define DEFAULT_PROFILE_KEY CONF_GLOBAL_PREFIX "/default_profile"
 
+#define ENCODING_LIST_KEY CONF_GLOBAL_PREFIX "/active_encodings"
+
 /* Helper functions */
 
 static GdkScreen*
@@ -733,6 +741,7 @@
   GList *profiles_to_delete, *l;
   gboolean need_new_default;
   TerminalProfile *fallback;
+  guint count;
 
   g_object_freeze_notify (object);
 
@@ -768,8 +777,8 @@
 ensure_one_profile:
 
   fallback = NULL;
-  if (terminal_app_get_profile_count (app) == 0 ||
-      terminal_app_get_profile_count (app) <= g_list_length (profiles_to_delete))
+  count = g_hash_table_size (app->profiles);
+  if (count == 0 || count <= g_list_length (profiles_to_delete))
     {
       /* We are going to run out, so create the fallback
        * to be sure we always have one. Must be done
@@ -834,7 +843,7 @@
       g_object_notify (object, TERMINAL_APP_DEFAULT_PROFILE);
     }
 
-  g_assert (terminal_app_get_profile_count (app) > 0);
+  g_assert (g_hash_table_size (app->profiles) > 0);
 
   g_signal_emit (app, signals[PROFILE_LIST_CHANGED], 0);
 
@@ -868,6 +877,93 @@
   g_object_notify (G_OBJECT (app), TERMINAL_APP_DEFAULT_PROFILE);
 }
 
+static int
+compare_encodings (TerminalEncoding *a,
+                   TerminalEncoding *b)
+{
+  return g_utf8_collate (a->name, b->name);
+}
+
+static void
+encoding_mark_active (gpointer key,
+                      gpointer value,
+                      gpointer data)
+{
+  TerminalEncoding *encoding = (TerminalEncoding *) value;
+  guint active = GPOINTER_TO_UINT (data);
+
+  encoding->is_active = active;
+}
+
+static void
+terminal_app_encoding_list_notify_cb (GConfClient *client,
+                                      guint        cnxn_id,
+                                      GConfEntry  *entry,
+                                      gpointer     user_data)
+{
+  TerminalApp *app = TERMINAL_APP (user_data);
+  GConfValue *val;
+  GSList *strings, *tmp;
+  TerminalEncoding *encoding;
+  const char *charset;
+
+  app->encodings_locked = !gconf_entry_get_is_writable (entry);
+
+  /* Mark all as non-active, then re-enable the active ones */
+  g_hash_table_foreach (app->encodings, (GHFunc) encoding_mark_active, GUINT_TO_POINTER (FALSE));
+
+  /* First add the local encoding. */
+  if (!g_get_charset (&charset))
+    {
+      encoding = g_hash_table_lookup (app->encodings, charset);
+      if (encoding)
+        encoding->is_active = TRUE;
+    }
+
+  /* Always ensure that UTF-8 is available. */
+  encoding = g_hash_table_lookup (app->encodings, "UTF-8");
+  g_assert (encoding);
+  encoding->is_active = TRUE;
+
+  val = gconf_entry_get_value (entry);
+  if (val != NULL &&
+      val->type == GCONF_VALUE_LIST &&
+      gconf_value_get_list_type (val) == GCONF_VALUE_STRING)
+    strings = gconf_value_get_list (val);
+  else
+    strings = NULL;
+
+  for (tmp = strings; tmp != NULL; tmp = tmp->next)
+    {
+      GConfValue *v = (GConfValue *) tmp->data;
+      
+      charset = gconf_value_get_string (v);
+      if (!charset)
+        continue;
+
+      /* We already handled the locale charset above */
+      if (strcmp (charset, "current") == 0)
+        continue; 
+
+      encoding = g_hash_table_lookup (app->encodings, charset);
+      if (!encoding)
+        {
+          encoding = terminal_encoding_new (charset,
+                                            _("User Defined"),
+                                            TRUE,
+                                            TRUE /* scary! */);
+          g_hash_table_insert (app->encodings, encoding->charset, encoding);
+        }
+
+      if (!terminal_encoding_is_valid (encoding))
+        continue;
+
+      encoding->is_active = TRUE;
+    }
+
+  g_signal_emit (app, signals[ENCODING_LIST_CHANGED], 0);
+}
+
 static void
 terminal_app_system_font_notify_cb (GConfClient *client,
                                     guint        cnxn_id,
@@ -1130,7 +1226,7 @@
   gtk_widget_set_sensitive (app->manage_profiles_edit_button, selected);
   gtk_widget_set_sensitive (app->manage_profiles_delete_button,
                             selected &&
-                            terminal_app_get_profile_count (app) > 1);
+                            g_hash_table_size (app->profiles) > 1);
 }
 
 static void
@@ -1427,6 +1523,8 @@
 
   app->profiles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
 
+  app->encodings = terminal_encodings_get_builtins ();
+
   app->conf = gconf_client_get_default ();
 
   gconf_client_add_dir (app->conf, CONF_GLOBAL_PREFIX,
@@ -1447,6 +1545,12 @@
                              terminal_app_default_profile_notify_cb,
                              app, NULL, NULL);
 
+  app->encoding_list_notify_id =
+    gconf_client_notify_add (app->conf,
+                             ENCODING_LIST_KEY,
+                             terminal_app_encoding_list_notify_cb,
+                             app, NULL, NULL);
+
   app->system_font_notify_id =
     gconf_client_notify_add (app->conf,
                              MONOSPACE_FONT_KEY,
@@ -1468,6 +1572,7 @@
   /* Load the settings */
   gconf_client_notify (app->conf, PROFILE_LIST_KEY);
   gconf_client_notify (app->conf, DEFAULT_PROFILE_KEY);
+  gconf_client_notify (app->conf, ENCODING_LIST_KEY);
   gconf_client_notify (app->conf, MONOSPACE_FONT_KEY);
   gconf_client_notify (app->conf, ENABLE_MENU_BAR_ACCEL_KEY);
   gconf_client_notify (app->conf, ENABLE_MNEMONICS_KEY);
@@ -1477,7 +1582,6 @@
   g_assert (app->system_font_desc != NULL);
 
   terminal_accels_init ();
-  terminal_encoding_init ();
   
 #ifdef WITH_SMCLIENT
 {
@@ -1509,6 +1613,8 @@
     gconf_client_notify_remove (app->conf, app->profile_list_notify_id);
   if (app->default_profile_notify_id != 0)
     gconf_client_notify_remove (app->conf, app->default_profile_notify_id);
+  if (app->encoding_list_notify_id != 0)
+    gconf_client_notify_remove (app->conf, app->encoding_list_notify_id);
   if (app->system_font_notify_id != 0)
     gconf_client_notify_remove (app->conf, app->system_font_notify_id);
   if (app->enable_menu_accels_notify_id != 0)
@@ -1525,8 +1631,9 @@
 
   g_hash_table_destroy (app->profiles);
 
-  if (app->system_font_desc)
-    pango_font_description_free (app->system_font_desc);
+  g_hash_table_destroy (app->encodings);
+
+  pango_font_description_free (app->system_font_desc);
 
   terminal_accels_shutdown ();
 
@@ -1620,6 +1727,15 @@
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
 
+  signals[ENCODING_LIST_CHANGED] =
+    g_signal_new (I_("encoding-list-changed"),
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (TerminalAppClass, profile_list_changed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
   g_object_class_install_property
     (object_class,
      PROP_ENABLE_MENU_BAR_ACCEL,
@@ -1877,14 +1993,6 @@
   return g_list_sort (g_hash_table_get_values (app->profiles), profiles_alphabetic_cmp);
 }
 
-guint
-terminal_app_get_profile_count (TerminalApp *app)
-{
-  g_return_val_if_fail (TERMINAL_IS_APP (app), 0);
-
-  return g_hash_table_size (app->profiles);
-}
-
 TerminalProfile*
 terminal_app_get_profile_by_name (TerminalApp *app,
                                   const char *name)
@@ -1939,3 +2047,35 @@
 
   return NULL;
 }
+
+GHashTable *
+terminal_app_get_encodings (TerminalApp *app)
+{
+  return app->encodings;
+}
+
+/**
+ * terminal_app_get_active_encodings:
+ *
+ * Returns: a newly allocated list of newly referenced #TerminalEncoding objects.
+ */
+GSList*
+terminal_app_get_active_encodings (TerminalApp *app)
+{
+  GSList *list = NULL;
+  GHashTableIter iter;
+  gpointer key, value;
+
+  g_hash_table_iter_init (&iter, app->encodings);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      TerminalEncoding *encoding = (TerminalEncoding *) value;
+
+      if (!encoding->is_active)
+        continue;
+
+      list = g_slist_prepend (list, terminal_encoding_ref (encoding));
+    }
+
+  return g_slist_sort (list, (GCompareFunc) compare_encodings);
+}

Modified: trunk/src/terminal-app.h
==============================================================================
--- trunk/src/terminal-app.h	(original)
+++ trunk/src/terminal-app.h	Sat Oct 11 21:15:52 2008
@@ -96,8 +96,6 @@
 
 GList* terminal_app_get_profile_list (TerminalApp *app);
 
-guint  terminal_app_get_profile_count (TerminalApp *app);
-
 TerminalProfile* terminal_app_ensure_profile_fallback (TerminalApp *app);
 
 TerminalProfile* terminal_app_get_profile_by_name         (TerminalApp *app,
@@ -112,6 +110,10 @@
 /* never returns NULL if any profiles exist, one is always supposed to */
 TerminalProfile* terminal_app_get_profile_for_new_term (TerminalApp *app);
 
+GHashTable *terminal_app_get_encodings (TerminalApp *app);
+
+GSList* terminal_app_get_active_encodings (TerminalApp *app);
+
 G_END_DECLS
 
 #endif /* !TERMINAL_APP_H */

Modified: trunk/src/terminal-encoding.c
==============================================================================
--- trunk/src/terminal-encoding.c	(original)
+++ trunk/src/terminal-encoding.c	Sat Oct 11 21:15:52 2008
@@ -127,9 +127,6 @@
   { "JOHAB",  N_("Korean") },
 #endif
 };
-                           
-static GHashTable *encodings_hashtable;
-static gboolean encodings_writable;
 
 typedef struct {
   GtkWidget *dialog;
@@ -146,16 +143,9 @@
 
 static GtkWidget *encoding_dialog = NULL;
 
-static void update_active_encoding_tree_models (void);
-
-static void encodings_notify_cb (GConfClient *client,
-                                 guint        cnxn_id,
-                                 GConfEntry  *entry,
-                                 gpointer     user_data);
-
-static TerminalEncoding *
+TerminalEncoding *
 terminal_encoding_new (const char *charset,
-                       const char *name,
+                       const char *display_name,
                        gboolean is_custom,
                        gboolean force_valid)
 {
@@ -164,9 +154,10 @@
   encoding = g_slice_new (TerminalEncoding);
   encoding->refcount = 1;
   encoding->charset = g_strdup (charset);
-  encoding->name = g_strdup (name);
+  encoding->name = g_strdup (display_name);
   encoding->valid = encoding->validity_checked = force_valid;
   encoding->is_custom = is_custom;
+  encoding->is_active = FALSE;
 
   return encoding;
 }
@@ -191,7 +182,7 @@
   g_slice_free (TerminalEncoding, encoding);
 }
 
-static gboolean
+gboolean
 terminal_encoding_is_valid (TerminalEncoding *encoding)
 {
   /* All of the printing ASCII characters from space (32) to the tilde (126) */
@@ -240,9 +231,7 @@
   return encoding->valid;
 }
 
-#define TERMINAL_TYPE_ENCODING (terminal_encoding_get_type ())
-
-static GType
+GType
 terminal_encoding_get_type (void)
 {
   static GType type = 0;
@@ -257,92 +246,13 @@
 }
 
 static void
-encoding_mark_active (gpointer key,
-                      gpointer value,
-                      gpointer data)
-{
-  TerminalEncoding *encoding = (TerminalEncoding *) value;
-  guint active = GPOINTER_TO_UINT (data);
-
-  encoding->is_active = active;
-}
-
-static void
-encodings_notify_cb (GConfClient *client,
-                     guint        cnxn_id,
-                     GConfEntry  *entry,
-                     gpointer     user_data)
-{
-  GConfValue *val;
-  GSList *strings, *tmp;
-  TerminalEncoding *encoding;
-  const char *charset;
-
-  encodings_writable = gconf_entry_get_is_writable (entry);
-
-  /* Mark all as non-active, then re-enable the active ones */
-  g_hash_table_foreach (encodings_hashtable, (GHFunc) encoding_mark_active, GUINT_TO_POINTER (FALSE));
-
-  /* First add the local encoding. */
-  if (!g_get_charset (&charset))
-    {
-      encoding = g_hash_table_lookup (encodings_hashtable, charset);
-      if (encoding)
-        encoding->is_active = TRUE;
-    }
-
-  /* Always ensure that UTF-8 is available. */
-  encoding = g_hash_table_lookup (encodings_hashtable, "UTF-8");
-  g_assert (encoding);
-  encoding->is_active = TRUE;
-
-  val = gconf_entry_get_value (entry);
-  if (val != NULL &&
-      val->type == GCONF_VALUE_LIST &&
-      gconf_value_get_list_type (val) == GCONF_VALUE_STRING)
-    strings = gconf_value_get_list (val);
-  else
-    strings = NULL;
-
-  for (tmp = strings; tmp != NULL; tmp = tmp->next)
-    {
-      GConfValue *v = (GConfValue *) tmp->data;
-      
-      charset = gconf_value_get_string (v);
-      if (!charset)
-        continue;
-
-      /* We already handled the locale charset above */
-      if (strcmp (charset, "current") == 0)
-        continue; 
-
-      encoding = g_hash_table_lookup (encodings_hashtable, charset);
-      if (!encoding)
-        {
-          encoding = terminal_encoding_new (charset,
-                                            _("User Defined"),
-                                            TRUE,
-                                            TRUE /* scary! */);
-          g_hash_table_insert (encodings_hashtable, encoding->charset, encoding);
-        }
-
-      if (!terminal_encoding_is_valid (encoding))
-        continue;
-
-      encoding->is_active = TRUE;
-    }
-
-  update_active_encoding_tree_models ();
-}
-
-static void
 update_active_encodings_gconf (void)
 {
   GSList *list, *l;
   GSList *strings = NULL;
   GConfClient *conf;
 
-  list = terminal_get_active_encodings ();
+  list = terminal_app_get_active_encodings (terminal_app_get ());
   for (l = list; l != NULL; l = l->next)
     {
       TerminalEncoding *encoding = (TerminalEncoding *) l->data;
@@ -364,34 +274,6 @@
 }
 
 static void
-add_active_encoding_to_list (gpointer key,
-                             gpointer value,
-                             gpointer data)
-{
-  TerminalEncoding *encoding = (TerminalEncoding *) value;
-  GSList **list = (GSList **) data;
-
-  if (!encoding->is_active)
-    return;
-
-  *list = g_slist_prepend (*list, terminal_encoding_ref (encoding));
-}
-
-/**
- * terminal_get_active_encodings:
- *
- * Returns: a newly allocated list of newly referenced #TerminalEncoding objects.
- */
-GSList*
-terminal_get_active_encodings (void)
-{
-  GSList *list = NULL;
-
-  g_hash_table_foreach (encodings_hashtable, (GHFunc) add_active_encoding_to_list, &list);
-  return g_slist_reverse (list); /* FIXME sort ! */
-}
-
-static void
 response_callback (GtkWidget *window,
                    int        id,
                    EncodingDialogData *data)
@@ -467,7 +349,6 @@
   /* We don't need to emit row-changed here, since updating the gconf pref
    * will update the models.
    */
-  
   update_active_encodings_gconf ();
 }
 
@@ -519,38 +400,28 @@
 }
 
 static void
-update_single_liststore (EncodingDialogData *data)
+encodings_list_changed_cb (TerminalApp *app,
+                           EncodingDialogData *data)
 {
   gtk_list_store_clear (data->base_store);
-  g_hash_table_foreach (encodings_hashtable, (GHFunc) liststore_insert_encoding, data->base_store);
-}
-
-static GSList *encoding_dialogs_data = NULL;
 
-static void
-unregister_liststore (void    *data,
-                      GObject *where_object_was)
-{
-  encoding_dialogs_data = g_slist_remove (encoding_dialogs_data, data);
+  g_hash_table_foreach (terminal_app_get_encodings (app), (GHFunc) liststore_insert_encoding, data->base_store);
 }
 
 static void
-update_active_encoding_tree_models (void)
+encoding_dialog_data_free (EncodingDialogData *data)
 {
-  g_slist_foreach (encoding_dialogs_data, (GFunc) update_single_liststore, NULL);
-}
+  g_signal_handlers_disconnect_by_func (terminal_app_get (),
+                                        G_CALLBACK (encodings_list_changed_cb),
+                                        data);
 
-static void
-register_liststore (EncodingDialogData *data)
-{
-  update_single_liststore (data);
-  encoding_dialogs_data = g_slist_prepend (encoding_dialogs_data, data);
-  g_object_weak_ref (G_OBJECT (data->dialog), unregister_liststore, data);
+  g_free (data);
 }
 
 void
 terminal_encoding_dialog_show (GtkWindow *transient_parent)
 {
+  TerminalApp *app;
   GtkCellRenderer *cell_renderer;
   GtkTreeViewColumn *column;
   GtkTreeModel *model;
@@ -577,7 +448,7 @@
       return;
     }
 
-  g_object_set_data_full (G_OBJECT (data->dialog), "GT::Data", data, (GDestroyNotify) g_free);
+  g_object_set_data_full (G_OBJECT (data->dialog), "GT::Data", data, (GDestroyNotify) encoding_dialog_data_free);
 
   gtk_window_set_transient_for (GTK_WINDOW (data->dialog), transient_parent);
   gtk_window_set_role (GTK_WINDOW (data->dialog), "gnome-terminal-encodings");
@@ -644,7 +515,12 @@
                     G_CALLBACK (selection_changed_cb), data);
 
   data->base_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, TERMINAL_TYPE_ENCODING);
-  register_liststore (data);
+
+  app = terminal_app_get ();
+  encodings_list_changed_cb (app, data);
+  g_signal_connect (app, "encoding-list-changed",
+                    G_CALLBACK (encodings_list_changed_cb), data);
+
   /* Now turn on sorting */
   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->base_store),
                                         COLUMN_NAME,
@@ -667,15 +543,13 @@
                     G_CALLBACK (gtk_widget_destroyed), &encoding_dialog);
 }
 
-void
-terminal_encoding_init (void)
+GHashTable *
+terminal_encodings_get_builtins (void)
 {
-  GConfClient *conf;
+  GHashTable *encodings_hashtable;
   guint i;
   const char *locale_charset = NULL;
 
-  conf = gconf_client_get_default ();
-
   encodings_hashtable = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                NULL,
                                                (GDestroyNotify) terminal_encoding_unref);
@@ -702,13 +576,5 @@
       g_hash_table_insert (encodings_hashtable, encoding->charset, encoding);
     }
 
-  gconf_client_notify_add (conf,
-                           CONF_GLOBAL_PREFIX"/active_encodings",
-                           encodings_notify_cb,
-                           NULL /* user_data */, NULL,
-                           NULL);
-
-  gconf_client_notify (conf, CONF_GLOBAL_PREFIX"/active_encodings");
-
-  g_object_unref (conf);
+  return encodings_hashtable;
 }

Modified: trunk/src/terminal-encoding.h
==============================================================================
--- trunk/src/terminal-encoding.h	(original)
+++ trunk/src/terminal-encoding.h	Sat Oct 11 21:15:52 2008
@@ -24,6 +24,8 @@
 
 #include <gtk/gtk.h>
 
+#define TERMINAL_TYPE_ENCODING (terminal_encoding_get_type ())
+
 typedef struct
 {
   int   refcount;
@@ -35,14 +37,21 @@
   guint is_active        : 1;
 } TerminalEncoding;
 
-void terminal_encoding_init (void);
-
-void terminal_encoding_dialog_show (GtkWindow *transient_parent);
+GType terminal_encoding_get_type (void);
 
-GSList* terminal_get_active_encodings (void);
+TerminalEncoding *terminal_encoding_new (const char *charset,
+                                         const char *display_name,
+                                         gboolean is_custom,
+                                         gboolean force_valid);
 
-TerminalEncoding* terminal_encoding_ref (TerminalEncoding *encoding);
+TerminalEncoding *terminal_encoding_ref (TerminalEncoding *encoding);
 
 void terminal_encoding_unref (TerminalEncoding *encoding);
 
+gboolean terminal_encoding_is_valid (TerminalEncoding *encoding);
+
+GHashTable *terminal_encodings_get_builtins (void);
+
+void terminal_encoding_dialog_show (GtkWindow *transient_parent);
+
 #endif /* TERMINAL_ENCODING_H */

Modified: trunk/src/terminal-window.c
==============================================================================
--- trunk/src/terminal-window.c	(original)
+++ trunk/src/terminal-window.c	Sat Oct 11 21:15:52 2008
@@ -732,7 +732,7 @@
   else
     charset = NULL;
   
-  encodings = terminal_get_active_encodings ();
+  encodings = terminal_app_get_active_encodings (terminal_app_get ());
 
   group = NULL;
   n = 0;
@@ -1434,6 +1434,13 @@
 }
 
 static void
+terminal_window_encoding_list_changed_cb (TerminalApp *app,
+                                          TerminalWindow *window)
+{
+  terminal_window_update_encoding_menu (window);
+}
+
+static void
 terminal_window_init (TerminalWindow *window)
 {
   const GtkActionEntry menu_entries[] =
@@ -1710,11 +1717,13 @@
   g_signal_connect (app, "profile-list-changed",
                     G_CALLBACK (terminal_window_profile_list_changed_cb), window);
   
+  terminal_window_encoding_list_changed_cb (app, window);
+  g_signal_connect (app, "encoding-list-changed",
+                    G_CALLBACK (terminal_window_encoding_list_changed_cb), window);
+
   terminal_window_set_menubar_visible (window, TRUE);
   priv->use_default_menubar_visibility = TRUE;
 
-  terminal_window_update_encoding_menu (window);
-
   terminal_window_update_size_to_menu (window);
 
   /* We have to explicitly call this, since screen-changed is NOT



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