Here is a small patch which enhances the hotkey handling for menu entries.
        - new static function parse_key()
        - hotkey aliases are now case insensitive
        - additional hotkey aliases
        - handling now <SHIFT> and <CTRL> modifiers for hotkeys

Any chance that this is included (Vladimir: taking into account that
might do some work in these area anyway)? Any comments?

Andreas
------------------------------------------------------------
revno: 4098
committer: Andreas Vogel <andreas.f.vo...@gmail.com>
branch nick: 01-menuentry_enhanced_hotkeys
timestamp: Thu 2012-03-01 22:38:32 +0100
message:
        * grub-core/commands/menuentry.c: enhanced hotkey handling:
          - new static function parse_key()
          - hotkey aliases are now case insensitive
          - additional hotkey aliases
          - handling now <SHIFT> and <CTRL> modifiers for hotkeys
diff:
=== modified file 'grub-core/commands/menuentry.c'
--- grub-core/commands/menuentry.c      2012-02-26 16:28:05 +0000
+++ grub-core/commands/menuentry.c      2012-03-01 21:38:32 +0000
@@ -45,24 +45,110 @@
   int key;
 } hotkey_aliases[] =
   {
-    {"backspace", '\b'},
-    {"tab", '\t'},
-    {"delete", GRUB_TERM_KEY_DC},
-    {"insert", GRUB_TERM_KEY_INSERT},
-    {"f1", GRUB_TERM_KEY_F1},
-    {"f2", GRUB_TERM_KEY_F2},
-    {"f3", GRUB_TERM_KEY_F3},
-    {"f4", GRUB_TERM_KEY_F4},
-    {"f5", GRUB_TERM_KEY_F5},
-    {"f6", GRUB_TERM_KEY_F6},
-    {"f7", GRUB_TERM_KEY_F7},
-    {"f8", GRUB_TERM_KEY_F8},
-    {"f9", GRUB_TERM_KEY_F9},
-    {"f10", GRUB_TERM_KEY_F10},
-    {"f11", GRUB_TERM_KEY_F11},
-    {"f12", GRUB_TERM_KEY_F12},
+    { "backspace", '\b'},
+    { "tab",       '\t'},
+    { "delete",    GRUB_TERM_KEY_DC },
+    { "insert",    GRUB_TERM_KEY_INSERT },
+    { "up",        GRUB_TERM_KEY_UP },
+    { "down",      GRUB_TERM_KEY_DOWN },
+    { "left",      GRUB_TERM_KEY_LEFT },
+    { "right",     GRUB_TERM_KEY_RIGHT },
+    { "prev",      GRUB_TERM_KEY_PPAGE },
+    { "next",      GRUB_TERM_KEY_NPAGE },
+    { "home",      GRUB_TERM_KEY_HOME },
+    { "end",       GRUB_TERM_KEY_END },
+    { "f1",        GRUB_TERM_KEY_F1 },
+    { "f2",        GRUB_TERM_KEY_F2 },
+    { "f3",        GRUB_TERM_KEY_F3 },
+    { "f4",        GRUB_TERM_KEY_F4 },
+    { "f5",        GRUB_TERM_KEY_F5 },
+    { "f6",        GRUB_TERM_KEY_F6 },
+    { "f7",        GRUB_TERM_KEY_F7 },
+    { "f8",        GRUB_TERM_KEY_F8 },
+    { "f9",        GRUB_TERM_KEY_F9 },
+    { "f10",       GRUB_TERM_KEY_F10 },
+    { "f11",       GRUB_TERM_KEY_F11 },
+    { "f12",       GRUB_TERM_KEY_F12 },
   };
 
+
+/* Parse the given string and return a GRUB_TERM key.
+   The given string can be one of the predefined key names (aliases),
+   otherwise the first character of the given str is taken as key.
+   Modifiers like "<SHIFT>" or "<CTRL>" are handled. They may appear
+   in any order but need to be in front of the alias or key.
+   Spaces between the modifiers and key are silently ignored.
+   Comparison with alias names is case independent. */
+
+static int
+parse_key (const char *string)
+{
+  char *str, *ptr, *keystr;
+  int key = 0;
+  int i;
+
+  if (string == 0 || *string == 0)
+    return 0;
+
+  str = grub_strdup (string);
+  if (!str)
+    return 0;
+
+#define STRING_CTRL  "<CTRL>"
+#define STRING_SHIFT "<SHIFT>"
+
+  /* check for CTRL modifier */
+  ptr = grub_strstr (str, STRING_CTRL);
+  if (ptr)
+  {
+    /* replace modifier string with spaces */
+    for (i = 0; i < grub_strlen (STRING_CTRL); i++)
+      *(ptr + i) = ' ';
+    key |= GRUB_TERM_CTRL;
+  }
+
+  /* check for SHIFT modifier */
+  ptr = grub_strstr (str, STRING_SHIFT);
+  if (ptr)
+  {
+    /* replace modifier string with spaces */
+    for (i = 0; i < grub_strlen (STRING_SHIFT); i++)
+      *(ptr + i) = ' ';
+    key |= GRUB_TERM_SHIFT;
+  }
+
+  /* remove/zero trailing spaces */
+  for (ptr = str + grub_strlen (str) - 1; ptr >= str && *ptr == ' '; ptr--)
+  *ptr = 0;
+
+  /* skip leading spaces */
+  for (ptr = str; *ptr == ' '; ptr++) /*NOTHING*/;
+
+  /* the remaining chars are the real key string */
+  keystr = ptr;
+
+  /* check if the key string is an alias name */
+  for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
+  {
+    /* case is not significant for key aliases */
+    if (grub_strcasecmp (keystr, hotkey_aliases[i].name) == 0)
+    {
+      key |= hotkey_aliases[i].key;
+      break;
+    }
+  }
+
+  if (i == ARRAY_SIZE (hotkey_aliases))
+  {
+    /* no alias matched, so use the first char in the given string as the key 
*/
+    key |= keystr[0];
+  }
+
+  grub_free (str);
+
+  return key;
+}
+
 /* Add a menu entry to the current menu context (as given by the environment
    variable data slot `menu').  As the configuration file is read, the script
    parser calls this when a menu entry is to be created.  */
@@ -117,17 +203,7 @@
     }
 
   if (hotkey)
-    {
-      unsigned i;
-      for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
-       if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
-         {
-           menu_hotkey = hotkey_aliases[i].key;
-           break;
-         }
-      if (i == ARRAY_SIZE (hotkey_aliases))
-       menu_hotkey = hotkey[0];
-    }
+    menu_hotkey = parse_key (hotkey);
 
   if (! argc)
     {
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to