Support menu hotkeys.
authorhpa <hpa>
Tue, 28 Dec 2004 23:18:27 +0000 (23:18 +0000)
committerhpa <hpa>
Tue, 28 Dec 2004 23:18:27 +0000 (23:18 +0000)
README.menu
com32/modules/menu.c
com32/modules/menu.h
com32/modules/readconfig.c

index b6f457a..1e1e825 100644 (file)
@@ -49,16 +49,20 @@ MENU LABEL label
 
        # Soft Cap Linux
        LABEL softcap
-               MENU LABEL Soft Cap Linux 9.6.36
+               MENU LABEL Soft Cap ^Linux 9.6.36
                KERNEL softcap-9.6.36.bzi
                APPEND whatever
 
        # A very dense operating system
        LABEL brick
-               MENU LABEL Windows CE/ME/NT
+               MENU LABEL ^Windows CE/ME/NT
                KERNEL chain.c32
                APPEND hd0 2
 
+       The ^ symbol in a MENU LABEL statement defines a hotkey.
+       The hotkey will be highlighted in the menu and will move the
+       menu cursor immediately to that entry.
+
 MENU HIDE
 
        (Only valid after a LABEL statement.)
index 064afa5..9b91868 100644 (file)
@@ -42,7 +42,9 @@ struct menu_attrib {
   const char *border;          /* Border area */
   const char *title;           /* Title bar */
   const char *unsel;           /* Unselected menu item */
+  const char *hotkey;          /* Unselected hotkey */
   const char *sel;             /* Selected */
+  const char *hotsel;          /* Selected hotkey */
   const char *more;            /* [More] tag */
   const char *tabmsg;          /* Press [Tab] message */
   const char *cmdmark;         /* Command line marker */
@@ -54,7 +56,9 @@ const struct menu_attrib default_attrib = {
   .border  = "\033[0;30;44m",
   .title   = "\033[1;36;44m",
   .unsel   = "\033[0;37;44m",
+  .hotkey  = "\033[1;37;44m",
   .sel     = "\033[0;30;47m",
+  .hotsel  = "\033[1;30;47m",
   .more    = "\033[0;37;44m",
   .tabmsg  = "\033[0;31;40m",
   .cmdmark = "\033[1;36;40m",
@@ -91,6 +95,35 @@ char *pad_line(const char *text, int align, int width)
   return buffer;
 }
 
+/* Display an entry, with possible hotkey highlight.  Assumes
+   that the current attribute is the non-hotkey one, and will
+   guarantee that as an exit condition as well. */
+void display_entry(const struct menu_entry *entry, const char *attrib,
+                  const char *hotattrib, int width)
+{
+  const char *p = entry->displayname;
+
+  while ( width ) {
+    if ( *p ) {
+      if ( *p == '^' ) {
+       p++;
+       if ( *p && (unsigned char)*p == entry->hotkey ) {
+         fputs(hotattrib, stdout);
+         putchar(*p++);
+         fputs(attrib, stdout);
+         width--;
+       }
+      } else {
+       putchar(*p++);
+       width--;
+      }
+    } else {
+      putchar(' ');
+      width--;
+    }
+  }
+}
+
 void draw_menu(int sel, int top)
 {
   int x, y;
@@ -118,13 +151,21 @@ void draw_menu(int sel, int top)
 
   for ( y = 4 ; y < 4+MENU_ROWS ; y++ ) {
     int i = (y-4)+top;
-    const char *txt = (i >= nentries) ? "" : menu_entries[i].displayname;
 
-    printf("\033[%d;%dH\272%s %s %s\272",
+    printf("\033[%d;%dH\272%s ",
           y, MARGIN+1,
-          (i == sel) ? menu_attrib->sel : menu_attrib->unsel,
-          pad_line(txt, 0, WIDTH-2*MARGIN-4),
-          menu_attrib->border);
+          (i == sel) ? menu_attrib->sel : menu_attrib->unsel);
+
+    if ( i >= nentries ) {
+      fputs(pad_line("", 0, WIDTH-2*MARGIN-4), stdout);
+    } else {
+      display_entry(&menu_entries[i],
+                   (i == sel) ? menu_attrib->sel : menu_attrib->unsel,
+                   (i == sel) ? menu_attrib->hotsel : menu_attrib->hotkey,
+                   WIDTH-2*MARGIN-4);
+    }
+    
+    printf(" %s\272", menu_attrib->border);
   }
 
   printf("\033[%d;%dH\310", y, MARGIN+1);
@@ -320,6 +361,13 @@ const char *run_menu(void)
        done = 1;
       break;
     default:
+      if ( key > 0 && key < 0xFF ) {
+       key &= ~0x20;           /* Upper case */
+       if ( menu_hotkeys[key] ) {
+         entry = menu_hotkeys[key] - menu_entries;
+         /* Should we commit at this point? */
+       }
+      }
       break;
     }
   }
index 4766a39..1ae7069 100644 (file)
@@ -24,13 +24,14 @@ struct menu_entry {
   char *displayname;
   char *label;
   char *cmdline;
-  int flags;
+  unsigned char hotkey;
 };
 
 #define MAX_CMDLINE_LEN         256
 
 #define MAX_ENTRIES    4096    /* Oughta be enough for anybody */
 extern struct menu_entry menu_entries[];
+extern struct menu_entry *menu_hotkeys[256];
 
 extern int nentries;
 extern int defentry;
index eb64d6a..cfb249a 100644 (file)
@@ -32,6 +32,7 @@ char *menu_title = "";
 char *ontimeout  = NULL;
 
 struct menu_entry menu_entries[MAX_ENTRIES];
+struct menu_entry *menu_hotkeys[256];
 
 #define astrdup(x) ({ char *__x = (x); \
                       size_t __n = strlen(__x) + 1; \
@@ -121,12 +122,23 @@ static void record(struct labeldata *ld, char *append)
 {
   char ipoptions[256], *ipp;
   int i;
+  struct menu_entry *me = &menu_entries[nentries];
 
   if ( ld->label ) {
     char *a, *s;
-    menu_entries[nentries].displayname =
-      ld->menulabel ? ld->menulabel : ld->label;
-    menu_entries[nentries].label       = ld->label;
+    me->displayname = ld->menulabel ? ld->menulabel : ld->label;
+    me->label       = ld->label;
+    me->hotkey = 0;
+
+    if ( ld->menulabel ) {
+      unsigned char *p = strchr(ld->menulabel, '^');
+      if ( p && p[1] ) {
+       int hotkey = p[1] & ~0x20;
+       if ( !menu_hotkeys[hotkey] ) {
+         me->hotkey = hotkey;
+       }
+      }
+    }
 
     ipp = ipoptions;
     *ipp = '\0';
@@ -139,7 +151,7 @@ static void record(struct labeldata *ld, char *append)
     if ( !a ) a = append;
     if ( !a || (a[0] == '-' && !a[1]) ) a = "";
     s = a[0] ? " " : "";
-    asprintf(&menu_entries[nentries].cmdline, "%s%s%s%s", ld->kernel, ipoptions, s, a);
+    asprintf(&me->cmdline, "%s%s%s%s", ld->kernel, ipoptions, s, a);
 
     ld->label = NULL;
     free(ld->kernel);
@@ -147,8 +159,12 @@ static void record(struct labeldata *ld, char *append)
       free(ld->append);
 
     if ( !ld->menuhide ) {
+      if ( me->hotkey )
+       menu_hotkeys[me->hotkey] = me;
+
       if ( ld->menudefault )
        defentry = nentries;
+
       nentries++;
     }
   }