From 189356d1c472f7f400819947f20b6ce030cba5cc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 17 Feb 2008 14:11:13 -0800 Subject: [PATCH] Submenu support: development snapshot Development snapshot before converting to refstrings --- com32/menu/colors.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ com32/menu/menu.h | 69 +++++++++++-------- com32/menu/menumain.c | 147 +--------------------------------------- com32/menu/readconfig.c | 50 +++++++++++--- com32/menu/refstr.c | 56 ++++++++++++++++ com32/menu/refstr.h | 35 ++++++++++ 6 files changed, 345 insertions(+), 185 deletions(-) create mode 100644 com32/menu/colors.c create mode 100644 com32/menu/refstr.c create mode 100644 com32/menu/refstr.h diff --git a/com32/menu/colors.c b/com32/menu/colors.c new file mode 100644 index 00000000..92f446d6 --- /dev/null +++ b/com32/menu/colors.c @@ -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 +#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; +} diff --git a/com32/menu/menu.h b/com32/menu/menu.h index 87e3215c..0d13b540 100644 --- a/com32/menu/menu.h +++ b/com32/menu/menu.h @@ -30,12 +30,15 @@ # 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); diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c index 4dbc66c3..8daf1f30 100644 --- a/com32/menu/menumain.c +++ b/com32/menu/menumain.c @@ -26,59 +26,11 @@ #include #include #include -#include #include #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) { diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c index ab9994e2..9c602688 100644 --- a/com32/menu/readconfig.c +++ b/com32/menu/readconfig.c @@ -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 index 00000000..745bc922 --- /dev/null +++ b/com32/menu/refstr.c @@ -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 +#include +#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 index 00000000..93c9b0ea --- /dev/null +++ b/com32/menu/refstr.h @@ -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 + +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 -- 2.11.4.GIT