]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkaccellabel.c
Do not leak the URI returned by the model; select the row when calling
[~andy/gtk] / gtk / gtkaccellabel.c
index bee1060bd89b3ffcce149a8da7375158c1078798..9d3ca419b7d4efda74ddf108f90575109f6a64ed 100644 (file)
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
+
+#include <config.h>
+#include <string.h>
+
 #include "gtkaccellabel.h"
 #include "gtkaccelmap.h"
 #include "gtkmain.h"
-#include "gtksignal.h"
+#include "gtkprivate.h"
 #include "gtkintl.h"
-
-#include <string.h>
-#include <ctype.h>
+#include "gtkalias.h"
 
 enum {
   PROP_0,
@@ -41,52 +43,24 @@ enum {
   PROP_ACCEL_WIDGET
 };
 
-static void     gtk_accel_label_class_init   (GtkAccelLabelClass *klass);
-static void     gtk_accel_label_init         (GtkAccelLabel      *accel_label);
-static void     gtk_accel_label_set_property (GObject            *object,
-                                             guint               prop_id,
-                                             const GValue       *value,
-                                             GParamSpec         *pspec);
-static void     gtk_accel_label_get_property (GObject            *object,
-                                             guint               prop_id,
-                                             GValue             *value,
-                                             GParamSpec         *pspec);
-static void     gtk_accel_label_destroy      (GtkObject          *object);
-static void     gtk_accel_label_finalize     (GObject            *object);
-static void     gtk_accel_label_size_request (GtkWidget          *widget,
-                                             GtkRequisition     *requisition);
-static gboolean gtk_accel_label_expose_event (GtkWidget          *widget,
-                                             GdkEventExpose     *event);
-static gboolean gtk_accel_label_refetch_idle (GtkAccelLabel      *accel_label);
-
-static GtkAccelLabelClass *accel_label_class = NULL;
-static GtkLabelClass *parent_class = NULL;
-
-
-GtkType
-gtk_accel_label_get_type (void)
-{
-  static GtkType accel_label_type = 0;
-  
-  if (!accel_label_type)
-    {
-      static const GtkTypeInfo accel_label_info =
-      {
-       "GtkAccelLabel",
-       sizeof (GtkAccelLabel),
-       sizeof (GtkAccelLabelClass),
-       (GtkClassInitFunc) gtk_accel_label_class_init,
-       (GtkObjectInitFunc) gtk_accel_label_init,
-        /* reserved_1 */ NULL,
-       /* reserved_2 */ NULL,
-       (GtkClassInitFunc) NULL,
-      };
-      
-      accel_label_type = gtk_type_unique (GTK_TYPE_LABEL, &accel_label_info);
-    }
-  
-  return accel_label_type;
-}
+static void         gtk_accel_label_set_property (GObject            *object,
+                                                 guint               prop_id,
+                                                 const GValue       *value,
+                                                 GParamSpec         *pspec);
+static void         gtk_accel_label_get_property (GObject            *object,
+                                                 guint               prop_id,
+                                                 GValue             *value,
+                                                 GParamSpec         *pspec);
+static void         gtk_accel_label_destroy      (GtkObject          *object);
+static void         gtk_accel_label_finalize     (GObject            *object);
+static void         gtk_accel_label_size_request (GtkWidget          *widget,
+                                                 GtkRequisition     *requisition);
+static gboolean     gtk_accel_label_expose_event (GtkWidget          *widget,
+                                                 GdkEventExpose     *event);
+static const gchar *gtk_accel_label_get_string   (GtkAccelLabel      *accel_label);
+
+
+G_DEFINE_TYPE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_LABEL)
 
 static void
 gtk_accel_label_class_init (GtkAccelLabelClass *class)
@@ -95,9 +69,6 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
   GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   
-  accel_label_class = class;
-  parent_class = g_type_class_peek_parent (class);
-  
   gobject_class->finalize = gtk_accel_label_finalize;
   gobject_class->set_property = gtk_accel_label_set_property;
   gobject_class->get_property = gtk_accel_label_get_property;
@@ -109,27 +80,45 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
 
   class->signal_quote1 = g_strdup ("<:");
   class->signal_quote2 = g_strdup (":>");
-  class->mod_name_shift = g_strdup ("Shift");
-  class->mod_name_control = g_strdup ("Ctrl");
-  class->mod_name_alt = g_strdup ("Alt");
+  /* This is the text that should appear next to menu accelerators
+   * that use the shift key. If the text on this key isn't typically
+   * translated on keyboards used for your language, don't translate
+   * this.
+   * And do not translate the part before the |.
+   */
+  class->mod_name_shift = g_strdup (Q_("keyboard label|Shift"));
+  /* This is the text that should appear next to menu accelerators
+   * that use the control key. If the text on this key isn't typically
+   * translated on keyboards used for your language, don't translate
+   * this.
+   * And do not translate the part before the |.
+   */
+  class->mod_name_control = g_strdup (Q_("keyboard label|Ctrl"));
+  /* This is the text that should appear next to menu accelerators
+   * that use the alt key. If the text on this key isn't typically
+   * translated on keyboards used for your language, don't translate
+   * this.
+   * And do not translate the part before the |.
+   */
+  class->mod_name_alt = g_strdup (Q_("keyboard label|Alt"));
   class->mod_separator = g_strdup ("+");
   class->accel_seperator = g_strdup (" / ");
   class->latin1_to_char = TRUE;
   
-  g_object_class_install_property (G_OBJECT_CLASS (object_class),
+  g_object_class_install_property (gobject_class,
                                    PROP_ACCEL_CLOSURE,
-                                   g_param_spec_object ("accel_closure",
-                                                        _("Accelerator Closure"),
-                                                        _("The closure to be monitored for accelerator changes"),
-                                                        GTK_TYPE_WIDGET,
-                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
-  g_object_class_install_property (G_OBJECT_CLASS (object_class),
+                                   g_param_spec_boxed ("accel-closure",
+                                                      P_("Accelerator Closure"),
+                                                      P_("The closure to be monitored for accelerator changes"),
+                                                      G_TYPE_CLOSURE,
+                                                      GTK_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
                                    PROP_ACCEL_WIDGET,
-                                   g_param_spec_object ("accel_widget",
-                                                        _("Accelerator Widget"),
-                                                        _("The widget to be monitored for accelerator changes"),
+                                   g_param_spec_object ("accel-widget",
+                                                        P_("Accelerator Widget"),
+                                                        P_("The widget to be monitored for accelerator changes"),
                                                         GTK_TYPE_WIDGET,
-                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                        GTK_PARAM_READWRITE));
 }
 
 static void
@@ -183,14 +172,11 @@ gtk_accel_label_get_property (GObject    *object,
 static void
 gtk_accel_label_init (GtkAccelLabel *accel_label)
 {
-  accel_label->queue_id = 0;
   accel_label->accel_padding = 3;
   accel_label->accel_widget = NULL;
   accel_label->accel_closure = NULL;
   accel_label->accel_group = NULL;
   accel_label->accel_string = NULL;
-  
-  gtk_accel_label_refetch (accel_label);
 }
 
 GtkWidget*
@@ -200,7 +186,7 @@ gtk_accel_label_new (const gchar *string)
   
   g_return_val_if_fail (string != NULL, NULL);
   
-  accel_label = gtk_type_new (GTK_TYPE_ACCEL_LABEL);
+  accel_label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
   
   gtk_label_set_text (GTK_LABEL (accel_label), string);
   
@@ -210,16 +196,12 @@ gtk_accel_label_new (const gchar *string)
 static void
 gtk_accel_label_destroy (GtkObject *object)
 {
-  GtkAccelLabel *accel_label;
-  
-  g_return_if_fail (GTK_IS_ACCEL_LABEL (object));
-  
-  accel_label = GTK_ACCEL_LABEL (object);
+  GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
 
   gtk_accel_label_set_accel_widget (accel_label, NULL);
   gtk_accel_label_set_accel_closure (accel_label, NULL);
   
-  GTK_OBJECT_CLASS (parent_class)->destroy (object);
+  GTK_OBJECT_CLASS (gtk_accel_label_parent_class)->destroy (object);
 }
 
 static void
@@ -227,14 +209,9 @@ gtk_accel_label_finalize (GObject *object)
 {
   GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
 
-  if (accel_label->queue_id)
-    {
-      gtk_idle_remove (accel_label->queue_id);
-      accel_label->queue_id = 0;
-    }
   g_free (accel_label->accel_string);
   
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gtk_accel_label_parent_class)->finalize (object);
 }
 
 /**
@@ -268,39 +245,43 @@ static void
 gtk_accel_label_size_request (GtkWidget             *widget,
                              GtkRequisition *requisition)
 {
-  GtkAccelLabel *accel_label;
+  GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
   PangoLayout *layout;
   gint width;
   
-  g_return_if_fail (GTK_IS_ACCEL_LABEL (widget));
-  g_return_if_fail (requisition != NULL);
-  
-  accel_label = GTK_ACCEL_LABEL (widget);
-  
-  if (GTK_WIDGET_CLASS (parent_class)->size_request)
-    GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
+  if (GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->size_request)
+    GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->size_request (widget, requisition);
 
-  layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
+  layout = gtk_widget_create_pango_layout (widget, gtk_accel_label_get_string (accel_label));
   pango_layout_get_pixel_size (layout, &width, NULL);
   accel_label->accel_string_width = width;
   
-  g_object_unref (G_OBJECT (layout));
+  g_object_unref (layout);
+}
+
+static gint
+get_first_baseline (PangoLayout *layout)
+{
+  PangoLayoutIter *iter;
+  gint result;
+
+  iter = pango_layout_get_iter (layout);
+  result = pango_layout_iter_get_baseline (iter);
+  pango_layout_iter_free (iter);
+
+  return PANGO_PIXELS (result);
 }
 
 static gboolean 
 gtk_accel_label_expose_event (GtkWidget      *widget,
                              GdkEventExpose *event)
 {
-  GtkMisc *misc;
-  GtkAccelLabel *accel_label;
-  PangoLayout *layout;
-  
-  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-  
-  accel_label = GTK_ACCEL_LABEL (widget);
-  misc = GTK_MISC (accel_label);
-         
+  GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
+  GtkMisc *misc = GTK_MISC (accel_label);
+  GtkTextDirection direction;
+
+  direction = gtk_widget_get_direction (widget);
+
   if (GTK_WIDGET_DRAWABLE (accel_label))
     {
       guint ac_width;
@@ -309,22 +290,43 @@ gtk_accel_label_expose_event (GtkWidget      *widget,
       
       if (widget->allocation.width >= widget->requisition.width + ac_width)
        {
-         guint x;
-         guint y;
+         PangoLayout *label_layout;
+         PangoLayout *accel_layout;
+         GtkLabel *label = GTK_LABEL (widget);
+
+         gint x;
+         gint y;
          
+         label_layout = gtk_label_get_layout (GTK_LABEL (accel_label));
+
+         if (direction == GTK_TEXT_DIR_RTL)
+           widget->allocation.x += ac_width;
          widget->allocation.width -= ac_width;
-         if (GTK_WIDGET_CLASS (parent_class)->expose_event)
-           GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
-         widget->allocation.width += ac_width;
+         if (gtk_label_get_ellipsize (label))
+           pango_layout_set_width (label_layout,
+                                   pango_layout_get_width (label_layout) 
+                                   - ac_width * PANGO_SCALE);
          
-         x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width;
-         
-         y = (widget->allocation.y * (1.0 - misc->yalign) +
-              (widget->allocation.y + widget->allocation.height -
-               (widget->requisition.height - misc->ypad * 2)) *
-              misc->yalign) + 1.5;
+         if (GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->expose_event)
+           GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->expose_event (widget, event);
+         if (direction == GTK_TEXT_DIR_RTL)
+           widget->allocation.x -= ac_width;
+         widget->allocation.width += ac_width;
+         if (gtk_label_get_ellipsize (label))
+           pango_layout_set_width (label_layout,
+                                   pango_layout_get_width (label_layout) 
+                                   + ac_width * PANGO_SCALE);
          
-         layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string);
+         if (direction == GTK_TEXT_DIR_RTL)
+           x = widget->allocation.x + misc->xpad;
+         else
+           x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width;
+
+         gtk_label_get_layout_offsets (GTK_LABEL (accel_label), NULL, &y);
+
+         accel_layout = gtk_widget_create_pango_layout (widget, gtk_accel_label_get_string (accel_label));
+
+         y += get_first_baseline (label_layout) - get_first_baseline (accel_layout);
 
           gtk_paint_layout (widget->style,
                             widget->window,
@@ -334,38 +336,47 @@ gtk_accel_label_expose_event (GtkWidget      *widget,
                             widget,
                             "accellabel",
                             x, y,
-                            layout);                            
+                            accel_layout);                            
 
-          g_object_unref (G_OBJECT (layout));
+          g_object_unref (accel_layout);
        }
       else
        {
-         if (GTK_WIDGET_CLASS (parent_class)->expose_event)
-           GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+         if (GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->expose_event)
+           GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->expose_event (widget, event);
        }
     }
   
-  return TRUE;
+  return FALSE;
 }
 
 static void
 refetch_widget_accel_closure (GtkAccelLabel *accel_label)
 {
-  GSList *slist;
-
+  GClosure *closure = NULL;
+  GList *clist, *list;
+  
   g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
   g_return_if_fail (GTK_IS_WIDGET (accel_label->accel_widget));
   
-  for (slist = _gtk_widget_get_accel_closures (accel_label->accel_widget); slist; slist = slist->next)
-    if (gtk_accel_group_from_accel_closure (slist->data))
-      {
-       /* we just take the first correctly used closure */
-       gtk_accel_label_set_accel_closure (accel_label, slist->data);
-       return;
-      }
-  gtk_accel_label_set_accel_closure (accel_label, NULL);
+  clist = gtk_widget_list_accel_closures (accel_label->accel_widget);
+  for (list = clist; list; list = list->next)
+    {
+      /* we just take the first closure used */
+      closure = list->data;
+      break;
+    }
+  g_list_free (clist);
+  gtk_accel_label_set_accel_closure (accel_label, closure);
 }
 
+/**
+ * gtk_accel_label_set_accel_widget:
+ * @accel_label: a #GtkAccelLabel
+ * @accel_widget: the widget to be monitored.
+ *
+ * Sets the widget to be monitored by this accelerator label. 
+ **/
 void
 gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
                                  GtkWidget     *accel_widget)
@@ -380,7 +391,7 @@ gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
        {
          gtk_accel_label_set_accel_closure (accel_label, NULL);
          g_signal_handlers_disconnect_by_func (accel_label->accel_widget,
-                                               G_CALLBACK (refetch_widget_accel_closure),
+                                               refetch_widget_accel_closure,
                                                accel_label);
          g_object_unref (accel_label->accel_widget);
        }
@@ -393,19 +404,20 @@ gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
                                   accel_label, G_CONNECT_SWAPPED);
          refetch_widget_accel_closure (accel_label);
        }
-      g_object_notify (G_OBJECT (accel_label), "accel_widget");
+      g_object_notify (G_OBJECT (accel_label), "accel-widget");
     }
 }
 
 static void
-gtk_accel_label_queue_refetch (GtkAccelLabel *accel_label)
+gtk_accel_label_reset (GtkAccelLabel *accel_label)
 {
-  g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
-
-  if (accel_label->queue_id == 0)
-    accel_label->queue_id = gtk_idle_add_priority (G_PRIORITY_HIGH_IDLE,
-                                                  (GtkFunction) gtk_accel_label_refetch_idle,
-                                                  accel_label);
+  if (accel_label->accel_string)
+    {
+      g_free (accel_label->accel_string);
+      accel_label->accel_string = NULL;
+    }
+  
+  gtk_widget_queue_resize (GTK_WIDGET (accel_label));
 }
 
 static void
@@ -416,9 +428,17 @@ check_accel_changed (GtkAccelGroup  *accel_group,
                     GtkAccelLabel  *accel_label)
 {
   if (accel_closure == accel_label->accel_closure)
-    gtk_accel_label_queue_refetch (accel_label);
+    gtk_accel_label_reset (accel_label);
 }
 
+/**
+ * gtk_accel_label_set_accel_closure:
+ * @accel_label: a #GtkAccelLabel
+ * @accel_closure: the closure to monitor for accelerator changes.
+ *
+ * Sets the closure to be monitored by this accelerator label. The closure
+ * must be connected to an accelerator group; see gtk_accel_group_connect().
+ **/
 void
 gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
                                   GClosure      *accel_closure)
@@ -432,7 +452,7 @@ gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
       if (accel_label->accel_closure)
        {
          g_signal_handlers_disconnect_by_func (accel_label->accel_group,
-                                               G_CALLBACK (check_accel_changed),
+                                               check_accel_changed,
                                                accel_label);
          accel_label->accel_group = NULL;
          g_closure_unref (accel_label->accel_closure);
@@ -446,23 +466,11 @@ gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
                                   G_CALLBACK (check_accel_changed),
                                   accel_label, 0);
        }
-      gtk_accel_label_queue_refetch (accel_label);
-      g_object_notify (G_OBJECT (accel_label), "accel_closure");
+      gtk_accel_label_reset (accel_label);
+      g_object_notify (G_OBJECT (accel_label), "accel-closure");
     }
 }
 
-static gboolean
-gtk_accel_label_refetch_idle (GtkAccelLabel *accel_label)
-{
-  gboolean retval;
-
-  GDK_THREADS_ENTER ();
-  retval = gtk_accel_label_refetch (accel_label);
-  GDK_THREADS_LEAVE ();
-
-  return retval;
-}
-
 static gboolean
 find_accel (GtkAccelKey *key,
            GClosure    *closure,
@@ -471,105 +479,223 @@ find_accel (GtkAccelKey *key,
   return data == (gpointer) closure;
 }
 
-gboolean
-gtk_accel_label_refetch (GtkAccelLabel *accel_label)
+static const gchar *
+gtk_accel_label_get_string (GtkAccelLabel *accel_label)
+{
+  if (!accel_label->accel_string)
+    gtk_accel_label_refetch (accel_label);
+  
+  return accel_label->accel_string;
+}
+
+/* Underscores in key names are better displayed as spaces
+ * E.g., Page_Up should be "Page Up"
+ */
+static void
+substitute_underscores (char *str)
 {
-  GtkAccelLabelClass *class;
-  gchar *utf8;
+  char *p;
 
-  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), FALSE);
+  for (p = str; *p; p++)
+    if (*p == '_')
+      *p = ' ';
+}
 
-  class = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
+gchar *
+_gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass,
+                                             guint               accelerator_key,
+                                             GdkModifierType     accelerator_mods)
+{
+  GString *gstring;
+  gboolean seen_mod = FALSE;
+  gunichar ch;
+  
+  gstring = g_string_new ("");
+  
+  if (accelerator_mods & GDK_SHIFT_MASK)
+    {
+      g_string_append (gstring, klass->mod_name_shift);
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_CONTROL_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
+      g_string_append (gstring, klass->mod_name_control);
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_MOD1_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
+      g_string_append (gstring, klass->mod_name_alt);
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_MOD2_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
 
-  g_free (accel_label->accel_string);
-  accel_label->accel_string = NULL;
+      g_string_append (gstring, "Mod2");
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_MOD3_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
 
-  if (accel_label->accel_closure)
+      g_string_append (gstring, "Mod3");
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_MOD4_MASK)
     {
-      GtkAccelKey *key = gtk_accel_group_find (accel_label->accel_group, find_accel, accel_label->accel_closure);
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
 
-      if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
+      g_string_append (gstring, "Mod4");
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_MOD5_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
+
+      g_string_append (gstring, "Mod5");
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_SUPER_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
+
+      /* This is the text that should appear next to menu accelerators
+       * that use the super key. If the text on this key isn't typically
+       * translated on keyboards used for your language, don't translate
+       * this.
+       * And do not translate the part before the |.
+       */
+      g_string_append (gstring, Q_("keyboard label|Super"));
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_HYPER_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
+
+      /* This is the text that should appear next to menu accelerators
+       * that use the hyper key. If the text on this key isn't typically
+       * translated on keyboards used for your language, don't translate
+       * this.
+       * And do not translate the part before the |.
+       */
+      g_string_append (gstring, Q_("keyboard label|Hyper"));
+      seen_mod = TRUE;
+    }
+  if (accelerator_mods & GDK_META_MASK)
+    {
+      if (seen_mod)
+       g_string_append (gstring, klass->mod_separator);
+
+      /* This is the text that should appear next to menu accelerators
+       * that use the meta key. If the text on this key isn't typically
+       * translated on keyboards used for your language, don't translate
+       * this.
+       * And do not translate the part before the |.
+       */
+      g_string_append (gstring, Q_("keyboard label|Meta"));
+      seen_mod = TRUE;
+    }
+  if (seen_mod)
+    g_string_append (gstring, klass->mod_separator);
+  
+  ch = gdk_keyval_to_unicode (accelerator_key);
+  if (ch && (g_unichar_isgraph (ch) || ch == ' ') &&
+      (ch < 0x80 || klass->latin1_to_char))
+    {
+      switch (ch)
        {
-         GString *gstring;
-         gboolean seen_mod = FALSE;
-         
-         gstring = g_string_new (accel_label->accel_string);
-         g_string_append (gstring, gstring->len ? class->accel_seperator : "   ");
-         
-         if (key->accel_mods & GDK_SHIFT_MASK)
-           {
-             g_string_append (gstring, class->mod_name_shift);
-             seen_mod = TRUE;
-           }
-         if (key->accel_mods & GDK_CONTROL_MASK)
-           {
-             if (seen_mod)
-               g_string_append (gstring, class->mod_separator);
-             g_string_append (gstring, class->mod_name_control);
-             seen_mod = TRUE;
-           }
-         if (key->accel_mods & GDK_MOD1_MASK)
-           {
-             if (seen_mod)
-               g_string_append (gstring, class->mod_separator);
-             g_string_append (gstring, class->mod_name_alt);
-             seen_mod = TRUE;
-           }
-         if (seen_mod)
-           g_string_append (gstring, class->mod_separator);
-         if (key->accel_key < 0x80 ||
-             (key->accel_key > 0x80 &&
-              key->accel_key <= 0xff &&
-              class->latin1_to_char))
-           {
-             switch (key->accel_key)
-               {
-               case ' ':
-                 g_string_append (gstring, "Space");
-                 break;
-               case '\\':
-                 g_string_append (gstring, "Backslash");
-                 break;
-               default:
-                 g_string_append_c (gstring, toupper (key->accel_key));
-                 break;
-               }
-           }
+       case ' ':
+         /* do not translate the part before the | */
+         g_string_append (gstring, Q_("keyboard label|Space"));
+         break;
+       case '\\':
+         /* do not translate the part before the | */
+         g_string_append (gstring, Q_("keyboard label|Backslash"));
+         break;
+       default:
+         g_string_append_unichar (gstring, g_unichar_toupper (ch));
+         break;
+       }
+    }
+  else
+    {
+      gchar *tmp;
+
+      tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
+      if (tmp != NULL)
+       {
+         if (tmp[0] != 0 && tmp[1] == 0)
+           g_string_append_c (gstring, g_ascii_toupper (tmp[0]));
          else
            {
-             gchar *tmp;
+             gchar msg[128];
+             gchar *str;
              
-             tmp = gtk_accelerator_name (key->accel_key, 0);
-             if (tmp[0] != 0 && tmp[1] == 0)
-               tmp[0] = toupper (tmp[0]);
-             g_string_append (gstring, tmp);
-             g_free (tmp);
+             strcpy (msg, "keyboard label|");
+             g_strlcat (msg, tmp, 128);
+             str = dgettext (GETTEXT_PACKAGE, msg);
+             if (str == msg)
+               {
+                 g_string_append (gstring, tmp);
+                 substitute_underscores (gstring->str);
+               }
+             else
+               g_string_append (gstring, str);
            }
-         g_free (accel_label->accel_string);
-         accel_label->accel_string = gstring->str;
-         g_string_free (gstring, FALSE);
        }
-      if (!accel_label->accel_string)
-       accel_label->accel_string = g_strdup ("-/-");
     }
-  
-  if (!accel_label->accel_string)
-    accel_label->accel_string = g_strdup ("");
 
-  utf8 = g_locale_to_utf8 (accel_label->accel_string, -1, NULL, NULL, NULL);
-  if (utf8)
+  return g_string_free (gstring, FALSE);
+}
+
+gboolean
+gtk_accel_label_refetch (GtkAccelLabel *accel_label)
+{
+  g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), FALSE);
+
+  if (accel_label->accel_string)
     {
       g_free (accel_label->accel_string);
-      accel_label->accel_string = utf8;
+      accel_label->accel_string = NULL;
     }
 
-  if (accel_label->queue_id)
+  if (accel_label->accel_closure)
     {
-      gtk_idle_remove (accel_label->queue_id);
-      accel_label->queue_id = 0;
+      GtkAccelKey *key = gtk_accel_group_find (accel_label->accel_group, find_accel, accel_label->accel_closure);
+
+      if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
+       {
+         GtkAccelLabelClass *klass;
+         gchar *tmp;
+
+         klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
+         tmp = _gtk_accel_label_class_get_accelerator_label (klass,
+                                                             key->accel_key,
+                                                             key->accel_mods);
+         accel_label->accel_string = g_strconcat ("   ", tmp, NULL);
+         g_free (tmp);
+       }
+      if (!accel_label->accel_string)
+       accel_label->accel_string = g_strdup ("-/-");
     }
+  
+  if (!accel_label->accel_string)
+    accel_label->accel_string = g_strdup ("");
 
   gtk_widget_queue_resize (GTK_WIDGET (accel_label));
 
   return FALSE;
 }
+
+#define __GTK_ACCEL_LABEL_C__
+#include "gtkaliasdef.c"