Index: libegg/treeviewutils/eggaccelerators.c
===================================================================
RCS file: /cvs/gnome/libegg/libegg/treeviewutils/eggaccelerators.c,v
retrieving revision 1.5
diff -u -p -r1.5 eggaccelerators.c
--- libegg/treeviewutils/eggaccelerators.c	30 Sep 2002 03:56:38 -0000	1.5
+++ libegg/treeviewutils/eggaccelerators.c	8 Nov 2004 20:27:09 -0000
@@ -20,6 +20,7 @@
 
 #include "eggaccelerators.h"
 
+#include <stdlib.h>
 #include <string.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdkkeysyms.h>
@@ -175,22 +176,36 @@ is_hyper (const gchar *string)
 	  (string[6] == '>'));
 }
 
+static inline gboolean
+is_keycode (const gchar *string)
+{
+  return ((string[0] == '0') &&
+	  (string[1] == 'x'));
+}
+
 /**
  * egg_accelerator_parse_virtual:
- * @accelerator:      string representing an accelerator
- * @accelerator_key:  return location for accelerator keyval
- * @accelerator_mods: return location for accelerator modifier mask
+ * @accelerator:         string representing an accelerator
+ * @accelerator_keyval:  return location for accelerator key value
+ * @accelerator_keycode: return location for accelerator hardware keycode
+ * @accelerator_mods:    return location for accelerator modifier mask
  *
- * Parses a string representing a virtual accelerator. The format
- * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
- * "&lt;Release&gt;z" (the last one is for key release).  The parser
- * is fairly liberal and allows lower or upper case, and also
- * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
+ * Parses a string representing a virtual accelerator. The format looks like 
+ * "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or "&lt;Alt&gt;0xeb" or
+ * "&lt;Release&gt;z" (the last one is for key release). The parser is fairly 
+ * liberal and allows lower or upper case, and also abbreviations such as 
+ * "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If the key is expressed in the form "0x##"
+ * @accelerator_keycode will be set to the hardware keycode, otherwise 
+ * @accelerator_keyval will be set to the key value of the key. In both cases 
+ * the other argument will be set to 0. Note that the mapping between key 
+ * values and hardware keycodes is display-dependent and not 1-1: the key 
+ * values "4" and "$" often have the same hardware keycode, and "multimedia 
+ * keys" often have a hardware keycode e.g. 0xeb but no key value.
  *
- * If the parse fails, @accelerator_key and @accelerator_mods will
- * be set to 0 (zero) and %FALSE will be returned. If the string contains
- * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
- * returned.
+ * If the parse fails, @accelerator_keyval, @accelerator_keycode and 
+ * @accelerator_mods will be set to 0 (zero) and %FALSE will be returned. If 
+ * the string contains only modifiers, @accelerator_keyval and 
+ * @accelerator_keycode will be set to 0 but %TRUE will be returned.
  *
  * The virtual vs. concrete accelerator distinction is a relic of
  * how the X Window System works; there are modifiers Mod2-Mod5 that
@@ -202,24 +217,29 @@ is_hyper (const gchar *string)
  */
 gboolean
 egg_accelerator_parse_virtual (const gchar            *accelerator,
-                               guint                  *accelerator_key,
+                               guint                  *accelerator_keyval,
+                               guint                  *accelerator_keycode,
                                EggVirtualModifierType *accelerator_mods)
 {
   guint keyval;
+  guint keycode;
   GdkModifierType mods;
   gint len;
-  gboolean bad_keyval;
+  gboolean bad_keyname;
   
-  if (accelerator_key)
-    *accelerator_key = 0;
+  if (accelerator_keyval)
+    *accelerator_keyval = 0;
+  if (accelerator_keycode)
+    *accelerator_keycode = 0;
   if (accelerator_mods)
     *accelerator_mods = 0;
 
   g_return_val_if_fail (accelerator != NULL, FALSE);
 
-  bad_keyval = FALSE;
+  bad_keyname = FALSE;
   
   keyval = 0;
+  keycode = 0;
   mods = 0;
   len = strlen (accelerator);
   while (len)
@@ -316,37 +336,119 @@ egg_accelerator_parse_virtual (const gch
           keyval = gdk_keyval_from_name (accelerator);
           
           if (keyval == 0)
-            bad_keyval = TRUE;
+            {
+              /* If keyval is 0, than maybe it's a keycode.  Check for 0x## */
+              if (len >= 4 && is_keycode (accelerator))
+                {
+                  char keystring[5];
+                  gchar *endptr;
+
+                  memcpy (keystring, accelerator, 4);
+                  keystring [4] = '\000';
+
+                  keycode = strtoul (keystring, &endptr, 16);
+
+                  if (endptr == NULL || *endptr != '\000' || keycode == 0)
+                    {
+                      bad_keyname = TRUE;
+                    }
+                }
+              else
+                {
+                  bad_keyname = TRUE;
+                }
+            }
           
           accelerator += len;
           len -= len;              
 	}
     }
   
-  if (accelerator_key)
-    *accelerator_key = gdk_keyval_to_lower (keyval);
+  if (bad_keyname)
+    return FALSE;
+  
+  if (keyval != 0)
+    {
+      if (accelerator_keyval)
+        *accelerator_keyval = gdk_keyval_to_lower (keyval);
+    }
+  else if (keycode != 0)
+    {
+      if (accelerator_keycode)
+        *accelerator_keycode = keycode;
+    }
   if (accelerator_mods)
     *accelerator_mods = mods;
 
-  return !bad_keyval;
+  return TRUE;
 }
 
+/**
+ * egg_accelerator_parse_virtual_to_keycode:
+ * @accelerator:         string representing an accelerator
+ * @accelerator_keycode: return location for accelerator hardware keycode
+ * @accelerator_mods:    return location for accelerator modifier mask
+ * @keymap               the GdkKeymap to convert key values to keycodes
+ *
+ * Parses a string representing a virtual accelerator. Similar to 
+ * egg_accelerator_parse_virtual(), but converting key values to the 
+ * associated hardware keycode.
+ * 
+ * Returns: %TRUE on success.
+ */
+gboolean
+egg_accelerator_parse_virtual_to_keycode (const gchar            *accelerator,
+                                          guint                  *accelerator_keycode,
+                                          EggVirtualModifierType *accelerator_mods,
+                                          GdkKeymap              *keymap)
+{
+  guint keyval;
+  guint keycode;
+
+  if (accelerator_keycode)
+    *accelerator_keycode = 0;
+  
+  if (!egg_accelerator_parse_virtual (accelerator, &keyval, &keycode,
+                                      accelerator_mods))
+    return FALSE;
+
+  if (keycode == 0 && keyval != 0)
+    {
+      GdkKeymapKey *keys;
+      gint n_keys;
+      
+      if (!gdk_keymap_get_entries_for_keyval (keymap, keyval, &keys, &n_keys))
+        return FALSE;
+
+      keycode = keys[0].keycode;
+
+      g_free (keys);
+    }
+
+  if (keycode != 0 && accelerator_keycode)
+    *accelerator_keycode = keycode;
+  
+  return TRUE;
+}
 
 /**
  * egg_virtual_accelerator_name:
- * @accelerator_key:  accelerator keyval
- * @accelerator_mods: accelerator modifier mask
- * @returns:          a newly-allocated accelerator name
+ * @accelerator_keyval:  accelerator keyval
+ * @accelerator_keycode: accelerator hardware keycode
+ * @accelerator_mods:    accelerator modifier mask
+ * @returns:             a newly-allocated accelerator name
  * 
- * Converts an accelerator keyval and modifier mask
+ * Converts an accelerator keyval (or hardware keycode) and modifier mask
  * into a string parseable by egg_accelerator_parse_virtual().
- * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
- * this function returns "&lt;Control&gt;q".
+ * For example, if you pass in (#GDK_q, 0, #EGG_VIRTUAL_CONTROL_MASK)
+ * this function returns "&lt;Control&gt;q"; if you pass in (0, 0xeb,
+ * #EGG_VIRTUAL_META_MASK) this function returns "&lt;Meta&gt;0xeb".
  *
  * The caller of this function must free the returned string.
  */
 gchar*
-egg_virtual_accelerator_name (guint                  accelerator_key,
+egg_virtual_accelerator_name (guint                  accelerator_keyval,
+                              guint                  accelerator_keycode,
                               EggVirtualModifierType accelerator_mods)
 {
   static const gchar text_release[] = "<Release>";
@@ -362,11 +464,22 @@ egg_virtual_accelerator_name (guint     
   static const gchar text_hyper[] = "<Hyper>";
   guint l;
   gchar *keyval_name;
+  gchar keycode_buf[5]; /* "0x##" - keycodes are in range [8,255] */
   gchar *accelerator;
 
   accelerator_mods &= EGG_VIRTUAL_MODIFIER_MASK;
 
-  keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
+  keyval_name = NULL;
+  if (accelerator_keyval != 0)
+    {
+      keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_keyval));
+    }
+  else if (accelerator_keycode != 0)
+    {
+      g_snprintf (keycode_buf, sizeof(keycode_buf), 
+                  "0x%02x", accelerator_keycode);
+      keyval_name = keycode_buf;
+    }
   if (!keyval_name)
     keyval_name = "";
 
Index: libegg/treeviewutils/eggaccelerators.h
===================================================================
RCS file: /cvs/gnome/libegg/libegg/treeviewutils/eggaccelerators.h,v
retrieving revision 1.1
diff -u -p -r1.1 eggaccelerators.h
--- libegg/treeviewutils/eggaccelerators.h	13 Jul 2002 23:36:30 -0000	1.1
+++ libegg/treeviewutils/eggaccelerators.h	8 Nov 2004 20:27:09 -0000
@@ -68,9 +68,14 @@ typedef enum
 
 } EggVirtualModifierType;
 
-gboolean egg_accelerator_parse_virtual        (const gchar            *accelerator,
-                                               guint                  *accelerator_key,
-                                               EggVirtualModifierType *accelerator_mods);
+gboolean egg_accelerator_parse_virtual            (const gchar            *accelerator,
+                                                   guint                  *accelerator_keyval,
+                                                   guint                  *accelerator_keycode,
+                                                   EggVirtualModifierType *accelerator_mods);
+gboolean egg_accelerator_parse_virtual_to_keycode (const gchar            *accelerator,
+                                                   guint                  *accelerator_keycode,
+                                                   EggVirtualModifierType *accelerator_mods,
+                                                   GdkKeymap              *keymap);
 void     egg_keymap_resolve_virtual_modifiers (GdkKeymap              *keymap,
                                                EggVirtualModifierType  virtual_mods,
                                                GdkModifierType        *concrete_mods);
@@ -79,6 +84,7 @@ void     egg_keymap_virtualize_modifiers
                                                EggVirtualModifierType *virtual_mods);
 
 gchar* egg_virtual_accelerator_name (guint                  accelerator_key,
+                                     guint                  accelerator_keycode,
                                      EggVirtualModifierType accelerator_mods);
 
 G_END_DECLS
