Submenu support: development snapshot
authorH. Peter Anvin <hpa@zytor.com>
Sun, 17 Feb 2008 22:11:13 +0000 (14:11 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 20 Feb 2008 00:51:23 +0000 (16:51 -0800)
Development snapshot before converting to refstrings

com32/menu/colors.c [new file with mode: 0644]
com32/menu/menu.h
com32/menu/menumain.c
com32/menu/readconfig.c
com32/menu/refstr.c [new file with mode: 0644]
com32/menu/refstr.h [new file with mode: 0644]

diff --git a/com32/menu/colors.c b/com32/menu/colors.c
new file mode 100644 (file)
index 0000000..92f446d
--- /dev/null
@@ -0,0 +1,173 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <colortbl.h>
+#include "menu.h"
+
+/*
+ * The color/attribute indexes (\1#X, \2#XX, \3#XXX) are as follows
+ *
+ * 00 - screen         Rest of the screen
+ * 01 - border         Border area
+ * 02 - title          Title bar
+ * 03 - unsel          Unselected menu item
+ * 04 - hotkey         Unselected hotkey
+ * 05 - sel            Selection bar
+ * 06 - hotsel         Selected hotkey
+ * 07 - scrollbar      Scroll bar
+ * 08 - tabmsg         Press [Tab] message
+ * 09 - cmdmark                Command line marker
+ * 10 - cmdline                Command line
+ * 11 - pwdborder      Password box border
+ * 12 - pwdheader      Password box header
+ * 13 - pwdentry       Password box contents
+ * 14 - timeout_msg    Timeout message
+ * 15 - timeout                Timeout counter
+ * 16 - help           Current entry help text
+ * 17 - disabled        Disabled menu item
+ */
+
+static const struct color_table default_color_table[] = {
+  { "screen",      "37;40",     0x80ffffff, 0x00000000, SHADOW_NORMAL },
+  { "border",      "30;44",     0x40000000, 0x00000000, SHADOW_NORMAL },
+  { "title",       "1;36;44",   0xc00090f0, 0x00000000, SHADOW_NORMAL },
+  { "unsel",       "37;44",     0x90ffffff, 0x00000000, SHADOW_NORMAL },
+  { "hotkey",      "1;37;44",   0xffffffff, 0x00000000, SHADOW_NORMAL },
+  { "sel",         "7;37;40",   0xe0000000, 0x20ff8000, SHADOW_ALL },
+  { "hotsel",      "1;7;37;40", 0xe0400000, 0x20ff8000, SHADOW_ALL },
+  { "scrollbar",   "30;44",     0x40000000, 0x00000000, SHADOW_NORMAL },
+  { "tabmsg",      "31;40",     0x90ffff00, 0x00000000, SHADOW_NORMAL },
+  { "cmdmark",     "1;36;40",   0xc000ffff, 0x00000000, SHADOW_NORMAL },
+  { "cmdline",     "37;40",     0xc0ffffff, 0x00000000, SHADOW_NORMAL },
+  { "pwdborder",   "30;47",     0x80ffffff, 0x20ffffff, SHADOW_NORMAL },
+  { "pwdheader",   "31;47",     0x80ff8080, 0x20ffffff, SHADOW_NORMAL },
+  { "pwdentry",    "30;47",     0x80ffffff, 0x20ffffff, SHADOW_NORMAL },
+  { "timeout_msg", "37;40",     0x80ffffff, 0x00000000, SHADOW_NORMAL },
+  { "timeout",     "1;37;40",   0xc0ffffff, 0x00000000, SHADOW_NORMAL },
+  { "help",        "37;40",     0xc0ffffff, 0x00000000, SHADOW_NORMAL },
+  { "disabled",    "1;30;44",   0x60cccccc, 0x00000000, SHADOW_NORMAL },
+};
+
+#define NCOLORS (sizeof default_color_table/sizeof(struct color_table))
+const int message_base_color = NCOLORS;
+
+
+void set_msg_colors_global(struct color_table *tbl,
+                          unsigned int fg, unsigned int bg,
+                          enum color_table_shadow shadow)
+{
+  struct color_table *cp = tbl+message_base_color;
+  unsigned int i;
+  unsigned int fga, bga;
+  unsigned int fgh, bgh;
+  unsigned int fg_idx, bg_idx;
+  unsigned int fg_rgb, bg_rgb;
+
+  static const unsigned int pc2rgb[8] =
+    { 0x000000, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff, 0xffff00,
+      0xffffff };
+
+  /* Converting PC RGBI to sensible RGBA values is an "interesting"
+     proposition.  This algorithm may need plenty of tweaking. */
+
+  fga = fg & 0xff000000;
+  fgh = ((fg >> 1) & 0xff000000) | 0x80000000;
+
+  bga = bg & 0xff000000;
+  bgh = ((bg >> 1) & 0xff000000) | 0x80000000;
+
+  for (i = 0; i < 256; i++) {
+    fg_idx = i & 15;
+    bg_idx = i >> 4;
+
+    fg_rgb = pc2rgb[fg_idx & 7] & fg;
+    bg_rgb = pc2rgb[bg_idx & 7] & bg;
+
+    if (fg_idx & 8) {
+      /* High intensity foreground */
+      fg_rgb |= fgh;
+    } else {
+      fg_rgb |= fga;
+    }
+
+    if (bg_idx == 0) {
+      /* Default black background, assume transparent */
+      bg_rgb = 0;
+    } else if (bg_idx & 8) {
+      bg_rgb |= bgh;
+    } else {
+      bg_rgb |= bga;
+    }
+
+    cp->argb_fg = fg_rgb;
+    cp->argb_bg = bg_rgb;
+    cp->shadow = shadow;
+    cp++;
+  }
+}
+
+struct color_table *default_color_table(const struct color_table *base)
+{
+  unsigned int i, ncolors;
+  const struct color_table *dp;
+  struct color_table *cp;
+  struct color_table *color_table;
+  static const int pc2ansi[8] = {0, 4, 2, 6, 1, 5, 3, 7};
+
+  if (!base)
+    base = default_color_table;
+
+  color_table = calloc(NCOLORS+256, sizeof(struct color_table));
+
+  dp = base;
+  cp = color_table;
+
+  if (base == default_color_table)
+    ncolors = NCOLORS;
+  else
+    ncolors = NCOLORS+256;
+
+  for (i = 0; i < ncolors; i++) {
+    if (cp->ansi)
+      free((void *)cp->ansi);
+
+    *cp = *dp;
+    cp->ansi = strdup(dp->ansi);
+
+    cp++;
+    dp++;
+  }
+
+  if (base == default_color_table) {
+    for (i = 0; i < 256; i++) {
+      if (!cp->name)
+       asprintf((char **)&cp->name, "msg%02x", i);
+      
+      if (cp->ansi)
+       free((void *)cp->ansi);
+      
+      asprintf((char **)&cp->ansi, "%s3%d;4%d", (i & 8) ? "1;" : "",
+              pc2ansi[i & 7], pc2ansi[(i >> 4) & 7]);
+      
+      cp++;
+    }
+    
+    /*** XXX: This needs to move to run_menu() ***/
+    console_color_table = color_table;
+    console_color_table_size = NCOLORS+256;
+    
+    set_msg_colors_global(color_table, MSG_COLORS_DEF_FG, MSG_COLORS_DEF_BG,
+                         MSG_COLORS_DEF_SHADOW);
+  }
+
+  return color_table;
+}
index 87e3215..0d13b54 100644 (file)
 # define CLK_TCK sysconf(_SC_CLK_TCK)
 #endif
 
+struct menu;
+
 struct menu_entry {
   char *displayname;
   char *label;
-  char *cmdline;
   char *passwd;
   char *helptext;
+  char *cmdline;
+  struct menu *submenu;
   unsigned char hotkey;
   unsigned char disabled;
 };
@@ -57,7 +60,7 @@ enum kernel_type {
   KT_CONFIG,                   /* Configuration file */
 };
 
-extern const char *kernel_types[];
+extern const char * const kernel_types[];
 
 /* Configurable messages */
 enum message_number {
@@ -69,48 +72,58 @@ enum message_number {
 
   MSG_COUNT
 };
+
 struct messages {
   const char *name;            /* Message configuration name */
   const char *defmsg;          /* Default message text */
-  char *msg;                   /* Actual message text */
 };
-extern struct messages messages[MSG_COUNT];
 
-/* 2048 is the current definition inside syslinux */
-#define MAX_CMDLINE_LEN         2048
-
-extern struct menu_entry *menu_entries;
-extern struct menu_entry *menu_hotkeys[256];
+extern const struct messages messages[MSG_COUNT];
 
 struct menu_parameter {
   const char *name;
   int value;
 };
 
-extern struct menu_parameter mparm[];
-
-extern int nentries;
-extern int defentry;
-extern int allowedit;
-extern int timeout;
-extern int shiftkey;
-extern int hiddenmenu;
-extern long long totaltimeout;
-
-extern char *ontimeout;
-extern char *onerror;
-extern char *menu_master_passwd;
-extern char *menu_tab_msg;
-extern char *menu_autoboot_msg;
-extern char *menu_passprompt_msg;
-
-extern char *menu_background;
+extern const struct menu_parameter mparm[NPARAMS];
 
 struct fkey_help {
   const char *textname;
   const char *background;
 };
-extern struct fkey_help fkeyhelp[12];
+
+struct menu {
+  struct menu *parent;
+
+  struct menu_entry *menu_entries;
+  struct menu_entry *menu_hotkeys[256];
+
+  const char *messages[MSG_COUNT];
+  int mparm[NPARAMS];
+
+  int nentries;
+  int nentries_space;
+  int defentry;
+  int allowedit;
+  int timeout;
+  int shiftkey;
+  bool hiddenmenu;
+  long long totaltimeout;
+
+  char *ontimeout;
+  char *onerror;
+  char *menu_master_passwd;
+  char *menu_background;
+
+  struct color_table *color_table;
+
+  struct fkey_help fkeyhelp[12];
+};
+
+extern struct menu *root_menu;
+
+/* 2048 is the current definition inside syslinux */
+#define MAX_CMDLINE_LEN         2048
 
 void parse_configs(char **argv);
 int draw_background(const char *filename);
index 4dbc66c..8daf1f3 100644 (file)
 #include <minmax.h>
 #include <setjmp.h>
 #include <limits.h>
-#include <colortbl.h>
 #include <com32.h>
 
 #include "menu.h"
 
-/*
- * The color/attribute indexes (\1#X, \2#XX, \3#XXX) are as follows
- *
- * 00 - screen         Rest of the screen
- * 01 - border         Border area
- * 02 - title          Title bar
- * 03 - unsel          Unselected menu item
- * 04 - hotkey         Unselected hotkey
- * 05 - sel            Selection bar
- * 06 - hotsel         Selected hotkey
- * 07 - scrollbar      Scroll bar
- * 08 - tabmsg         Press [Tab] message
- * 09 - cmdmark                Command line marker
- * 10 - cmdline                Command line
- * 11 - pwdborder      Password box border
- * 12 - pwdheader      Password box header
- * 13 - pwdentry       Password box contents
- * 14 - timeout_msg    Timeout message
- * 15 - timeout                Timeout counter
- * 16 - help           Current entry help text
- * 17 - disabled        Disabled menu item
- */
-
-static const struct color_table default_color_table[] = {
-  { "screen",      "37;40",     0x80ffffff, 0x00000000, SHADOW_NORMAL },
-  { "border",      "30;44",     0x40000000, 0x00000000, SHADOW_NORMAL },
-  { "title",       "1;36;44",   0xc00090f0, 0x00000000, SHADOW_NORMAL },
-  { "unsel",       "37;44",     0x90ffffff, 0x00000000, SHADOW_NORMAL },
-  { "hotkey",      "1;37;44",   0xffffffff, 0x00000000, SHADOW_NORMAL },
-  { "sel",         "7;37;40",   0xe0000000, 0x20ff8000, SHADOW_ALL },
-  { "hotsel",      "1;7;37;40", 0xe0400000, 0x20ff8000, SHADOW_ALL },
-  { "scrollbar",   "30;44",     0x40000000, 0x00000000, SHADOW_NORMAL },
-  { "tabmsg",      "31;40",     0x90ffff00, 0x00000000, SHADOW_NORMAL },
-  { "cmdmark",     "1;36;40",   0xc000ffff, 0x00000000, SHADOW_NORMAL },
-  { "cmdline",     "37;40",     0xc0ffffff, 0x00000000, SHADOW_NORMAL },
-  { "pwdborder",   "30;47",     0x80ffffff, 0x20ffffff, SHADOW_NORMAL },
-  { "pwdheader",   "31;47",     0x80ff8080, 0x20ffffff, SHADOW_NORMAL },
-  { "pwdentry",    "30;47",     0x80ffffff, 0x20ffffff, SHADOW_NORMAL },
-  { "timeout_msg", "37;40",     0x80ffffff, 0x00000000, SHADOW_NORMAL },
-  { "timeout",     "1;37;40",   0xc0ffffff, 0x00000000, SHADOW_NORMAL },
-  { "help",        "37;40",     0xc0ffffff, 0x00000000, SHADOW_NORMAL },
-  { "disabled",    "1;30;44",   0x60cccccc, 0x00000000, SHADOW_NORMAL },
-};
-
-#define NCOLORS (sizeof default_color_table/sizeof(struct color_table))
-const int message_base_color = NCOLORS;
-
-struct menu_parameter mparm[] = {
+const struct menu_parameter mparm[NPARAMS] = {
   { "width", 80 },
   { "margin", 10 },
   { "passwordmargin", 3 },
@@ -93,7 +45,6 @@ struct menu_parameter mparm[] = {
   { "hshift", 0 },
   { "vshift", 0 },
   { "hiddenrow", -2 },
-  { NULL, 0 }
 };
 
 #define WIDTH          mparm[0].value
@@ -111,102 +62,6 @@ struct menu_parameter mparm[] = {
 #define VSHIFT         mparm[12].value
 #define HIDDEN_ROW     mparm[13].value
 
-void set_msg_colors_global(unsigned int fg, unsigned int bg,
-                          enum color_table_shadow shadow)
-{
-  struct color_table *cp = console_color_table+message_base_color;
-  unsigned int i;
-  unsigned int fga, bga;
-  unsigned int fgh, bgh;
-  unsigned int fg_idx, bg_idx;
-  unsigned int fg_rgb, bg_rgb;
-
-  static const unsigned int pc2rgb[8] =
-    { 0x000000, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff, 0xffff00,
-      0xffffff };
-
-  /* Converting PC RGBI to sensible RGBA values is an "interesting"
-     proposition.  This algorithm may need plenty of tweaking. */
-
-  fga = fg & 0xff000000;
-  fgh = ((fg >> 1) & 0xff000000) | 0x80000000;
-
-  bga = bg & 0xff000000;
-  bgh = ((bg >> 1) & 0xff000000) | 0x80000000;
-
-  for (i = 0; i < 256; i++) {
-    fg_idx = i & 15;
-    bg_idx = i >> 4;
-
-    fg_rgb = pc2rgb[fg_idx & 7] & fg;
-    bg_rgb = pc2rgb[bg_idx & 7] & bg;
-
-    if (fg_idx & 8) {
-      /* High intensity foreground */
-      fg_rgb |= fgh;
-    } else {
-      fg_rgb |= fga;
-    }
-
-    if (bg_idx == 0) {
-      /* Default black background, assume transparent */
-      bg_rgb = 0;
-    } else if (bg_idx & 8) {
-      bg_rgb |= bgh;
-    } else {
-      bg_rgb |= bga;
-    }
-
-    cp->argb_fg = fg_rgb;
-    cp->argb_bg = bg_rgb;
-    cp->shadow = shadow;
-    cp++;
-  }
-}
-
-static void
-install_default_color_table(void)
-{
-  unsigned int i;
-  const struct color_table *dp;
-  struct color_table *cp;
-  static struct color_table color_table[NCOLORS+256];
-  static const int pc2ansi[8] = {0, 4, 2, 6, 1, 5, 3, 7};
-
-  dp = default_color_table;
-  cp = color_table;
-
-  for (i = 0; i < NCOLORS; i++) {
-    if (cp->ansi)
-      free((void *)cp->ansi);
-
-    *cp = *dp;
-    cp->ansi = strdup(dp->ansi);
-
-    cp++;
-    dp++;
-  }
-
-  for (i = 0; i < 256; i++) {
-    if (!cp->name)
-      asprintf((char **)&cp->name, "msg%02x", i);
-
-    if (cp->ansi)
-      free((void *)cp->ansi);
-
-    asprintf((char **)&cp->ansi, "%s3%d;4%d", (i & 8) ? "1;" : "",
-            pc2ansi[i & 7], pc2ansi[(i >> 4) & 7]);
-
-    cp++;
-  }
-
-  console_color_table = color_table;
-  console_color_table_size = NCOLORS+256;
-
-  set_msg_colors_global(MSG_COLORS_DEF_FG, MSG_COLORS_DEF_BG,
-                       MSG_COLORS_DEF_SHADOW);
-}
-
 static char *
 pad_line(const char *text, int align, int width)
 {
index ab9994e..9c60268 100644 (file)
@@ -46,16 +46,11 @@ static int menu_entries_space = 0, hide_entries_space = 0;
 struct menu_entry *menu_hotkeys[256];
 
 struct messages messages[MSG_COUNT] = {
-  [MSG_TITLE] =
-  { "title", "", NULL },
-  [MSG_AUTOBOOT] =
-  { "autoboot", "Automatic boot in # second{,s}...", NULL },
-  [MSG_TAB] =
-  { "tabmsg", "Press [Tab] to edit options", NULL },
-  [MSG_NOTAB] =
-  { "notabmsg", "", NULL },
-  [MSG_PASSPROMPT] =
-  { "passprompt", "Password required", NULL },
+  [MSG_TITLE]      =  { "title",    "" },
+  [MSG_AUTOBOOT]   =  { "autoboot", "Automatic boot in # second{,s}..." },
+  [MSG_TAB]        =  { "tabmsg",   "Press [Tab] to edit options", NULL },
+  [MSG_NOTAB]      =  { "notabmsg", "" },
+  [MSG_PASSPROMPT] =  { "passprompt", "Password required", NULL },
 };
 
 #define astrdup(x) ({ char *__x = (x); \
@@ -120,7 +115,7 @@ get_config(void)
 #endif
 }
 
-#define MAX_LINE 512
+#define MAX_LINE 4096
 
 static char *
 skipspace(char *p)
@@ -150,6 +145,39 @@ looking_at(char *line, const char *kwd)
   return my_isspace(*p) ? p : NULL; /* Must be EOL or whitespace */
 }
 
+struct menu *start_menu(struct menu *parent)
+{
+  struct menu *m = malloc(sizeof(struct menu));
+  int i;
+
+  if (parent) {
+    /* Submenu */
+    memcpy(m, parent, sizeof *m);
+
+    m->menu_entries = NULL;
+    memset(m->menu_hotkeys, 0, sizeof m->menu_hotkeys);
+
+    m->parent = parent;
+    m->nentries = 0;
+    m->nentries_space = 0;
+    m->defentry = 0;
+    m->color_table = default_color_table(parent->color_table);
+  } else {
+    /* Root menu */
+
+    memset(m, 0, sizeof *m);
+
+    for (i = 0; i < MSG_COUNT; i++)
+      m->messages[i] = messages.defmsg[i];
+    for (i = 0; i < NPARAMS; i++)
+      m->mparm[i] = mparm[i].value;
+
+    m->color_table = default_color_table(NULL);
+  }
+
+  return m;
+}
+
 struct labeldata {
   char *label;
   char *kernel;
diff --git a/com32/menu/refstr.c b/com32/menu/refstr.c
new file mode 100644 (file)
index 0000000..745bc92
--- /dev/null
@@ -0,0 +1,56 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * refstr.c
+ *
+ * Simple reference-counted strings
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "refstr.h"
+
+const char *refstr_mkn(const char *str, size_t len)
+{
+  char *r;
+
+  len = strnlen(str, len);
+  r = malloc(sizeof(unsigned int)+len+1);
+  *(unsigned int *)r = 1;
+  r += sizeof(unsigned int);
+  memcpy(r, str, len);
+  r[len] = '\0';
+  return r;
+}
+
+const char *refstr_mk(const char *str)
+{
+  refstr *r;
+  size_t len;
+
+  len = strlen(str);
+  r = malloc(sizeof(unsigned int)+len+1);
+  *(unsigned int *)r = 1;
+  r += sizeof(unsigned int);
+  memcpy(r, str, len);
+  r[len] = '\0';
+  return r;
+}
+
+void refstr_put(const char *r)
+{
+  unsigned int *ref = (unsigned int *)r - 1;
+
+  if (!--*ref)
+    free(ref);
+}
diff --git a/com32/menu/refstr.h b/com32/menu/refstr.h
new file mode 100644 (file)
index 0000000..93c9b0e
--- /dev/null
@@ -0,0 +1,35 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * refstr.h
+ *
+ * Simple reference-counted strings
+ */
+
+#ifndef REFSTR_H
+#define REFSTR_H
+
+#include <stddef.h>
+
+static inline const char *refstr_get(const char *r)
+{
+  unsigned int *ref = (unsigned int *)r - 1;
+  ref++;
+  return r;
+}
+
+const char *refstr_mk(const char *);
+const char *refstr_mkn(const char *, size_t);
+void refstr_put(const char *);
+
+#endif