--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * 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;
+}
# 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;
};
KT_CONFIG, /* Configuration file */
};
-extern const char *kernel_types[];
+extern const char * const kernel_types[];
/* Configurable messages */
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);
#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 },
{ "hshift", 0 },
{ "vshift", 0 },
{ "hiddenrow", -2 },
- { NULL, 0 }
};
#define WIDTH mparm[0].value
#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)
{
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); \
#endif
}
-#define MAX_LINE 512
+#define MAX_LINE 4096
static char *
skipspace(char *p)
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;
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * 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);
+}
--- /dev/null
+/* ----------------------------------------------------------------------- *
+ *
+ * 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