summaryrefslogtreecommitdiff
path: root/com32
diff options
context:
space:
mode:
Diffstat (limited to 'com32')
-rw-r--r--com32/menu/menumain.c1846
1 files changed, 936 insertions, 910 deletions
diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c
index 81780eac..b86e9b4d 100644
--- a/com32/menu/menumain.c
+++ b/com32/menu/menumain.c
@@ -36,20 +36,20 @@
static struct menu *cm;
const struct menu_parameter mparm[NPARAMS] = {
- [P_WIDTH] = { "width", 0 },
- [P_MARGIN] = { "margin", 10 },
- [P_PASSWD_MARGIN] = { "passwordmargin", 3 },
- [P_MENU_ROWS] = { "rows", 12 },
- [P_TABMSG_ROW] = { "tabmsgrow", 18 },
- [P_CMDLINE_ROW] = { "cmdlinerow", 18 },
- [P_END_ROW] = { "endrow", -1 },
- [P_PASSWD_ROW] = { "passwordrow", 11 },
- [P_TIMEOUT_ROW] = { "timeoutrow", 20 },
- [P_HELPMSG_ROW] = { "helpmsgrow", 22 },
- [P_HELPMSGEND_ROW] = { "helpmsgendrow", -1 },
- [P_HSHIFT] = { "hshift", 0 },
- [P_VSHIFT] = { "vshift", 0 },
- [P_HIDDEN_ROW] = { "hiddenrow", -2 },
+ [P_WIDTH] = {"width", 0},
+ [P_MARGIN] = {"margin", 10},
+ [P_PASSWD_MARGIN] = {"passwordmargin", 3},
+ [P_MENU_ROWS] = {"rows", 12},
+ [P_TABMSG_ROW] = {"tabmsgrow", 18},
+ [P_CMDLINE_ROW] = {"cmdlinerow", 18},
+ [P_END_ROW] = {"endrow", -1},
+ [P_PASSWD_ROW] = {"passwordrow", 11},
+ [P_TIMEOUT_ROW] = {"timeoutrow", 20},
+ [P_HELPMSG_ROW] = {"helpmsgrow", 22},
+ [P_HELPMSGEND_ROW] = {"helpmsgendrow", -1},
+ [P_HSHIFT] = {"hshift", 0},
+ [P_VSHIFT] = {"vshift", 0},
+ [P_HIDDEN_ROW] = {"hiddenrow", -2},
};
/* These macros assume "cm" is a pointer to the current menu */
@@ -68,25 +68,24 @@ const struct menu_parameter mparm[NPARAMS] = {
#define VSHIFT (cm->mparm[P_VSHIFT])
#define HIDDEN_ROW (cm->mparm[P_HIDDEN_ROW])
-static char *
-pad_line(const char *text, int align, int width)
+static char *pad_line(const char *text, int align, int width)
{
- static char buffer[MAX_CMDLINE_LEN];
- int n, p;
+ static char buffer[MAX_CMDLINE_LEN];
+ int n, p;
- if ( width >= (int) sizeof buffer )
- return NULL; /* Can't do it */
+ if (width >= (int)sizeof buffer)
+ return NULL; /* Can't do it */
- n = strlen(text);
- if ( n >= width )
- n = width;
+ n = strlen(text);
+ if (n >= width)
+ n = width;
- memset(buffer, ' ', width);
- buffer[width] = 0;
- p = ((width-n)*align)>>1;
- memcpy(buffer+p, text, n);
+ memset(buffer, ' ', width);
+ buffer[width] = 0;
+ p = ((width - n) * align) >> 1;
+ memcpy(buffer + p, text, n);
- return buffer;
+ return buffer;
}
/* Display an entry, with possible hotkey highlight. Assumes
@@ -96,999 +95,1026 @@ static void
display_entry(const struct menu_entry *entry, const char *attrib,
const char *hotattrib, int width)
{
- const char *p = entry->displayname;
- char marker;
-
- if (!p)
- p = "";
-
- switch (entry->action) {
- case MA_SUBMENU:
- marker = '>';
- break;
- case MA_EXIT:
- marker = '<';
- break;
- default:
- marker = 0;
- break;
- }
-
- if (marker)
- width -= 2;
-
- while ( width ) {
- if ( *p ) {
- if ( *p == '^' ) {
- p++;
- if ( *p && ((unsigned char)*p & ~0x20) == entry->hotkey ) {
- fputs(hotattrib, stdout);
- putchar(*p++);
- fputs(attrib, stdout);
- width--;
+ const char *p = entry->displayname;
+ char marker;
+
+ if (!p)
+ p = "";
+
+ switch (entry->action) {
+ case MA_SUBMENU:
+ marker = '>';
+ break;
+ case MA_EXIT:
+ marker = '<';
+ break;
+ default:
+ marker = 0;
+ break;
+ }
+
+ if (marker)
+ width -= 2;
+
+ while (width) {
+ if (*p) {
+ if (*p == '^') {
+ p++;
+ if (*p && ((unsigned char)*p & ~0x20) == entry->hotkey) {
+ fputs(hotattrib, stdout);
+ putchar(*p++);
+ fputs(attrib, stdout);
+ width--;
+ }
+ } else {
+ putchar(*p++);
+ width--;
+ }
+ } else {
+ putchar(' ');
+ width--;
}
- } else {
- putchar(*p++);
- width--;
- }
- } else {
- putchar(' ');
- width--;
}
- }
- if (marker) {
- putchar(' ');
- putchar(marker);
- }
+ if (marker) {
+ putchar(' ');
+ putchar(marker);
+ }
}
-static void
-draw_row(int y, int sel, int top, int sbtop, int sbbot)
+static void draw_row(int y, int sel, int top, int sbtop, int sbbot)
{
- int i = (y-4-VSHIFT)+top;
- int dis = (i < cm->nentries) && is_disabled(cm->menu_entries[i]);
-
- printf("\033[%d;%dH\1#1\016x\017%s ",
- y, MARGIN+1+HSHIFT,
- (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3");
-
- if ( i >= cm->nentries ) {
- fputs(pad_line("", 0, WIDTH-2*MARGIN-4), stdout);
- } else {
- display_entry(cm->menu_entries[i],
- (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3",
- (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4",
- WIDTH-2*MARGIN-4);
- }
-
- if ( cm->nentries <= MENU_ROWS ) {
- printf(" \1#1\016x\017");
- } else if ( sbtop > 0 ) {
- if ( y >= sbtop && y <= sbbot )
- printf(" \1#7\016a\017");
- else
- printf(" \1#1\016x\017");
- } else {
- putchar(' '); /* Don't modify the scrollbar */
- }
+ int i = (y - 4 - VSHIFT) + top;
+ int dis = (i < cm->nentries) && is_disabled(cm->menu_entries[i]);
+
+ printf("\033[%d;%dH\1#1\016x\017%s ",
+ y, MARGIN + 1 + HSHIFT,
+ (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3");
+
+ if (i >= cm->nentries) {
+ fputs(pad_line("", 0, WIDTH - 2 * MARGIN - 4), stdout);
+ } else {
+ display_entry(cm->menu_entries[i],
+ (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3",
+ (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4",
+ WIDTH - 2 * MARGIN - 4);
+ }
+
+ if (cm->nentries <= MENU_ROWS) {
+ printf(" \1#1\016x\017");
+ } else if (sbtop > 0) {
+ if (y >= sbtop && y <= sbbot)
+ printf(" \1#7\016a\017");
+ else
+ printf(" \1#1\016x\017");
+ } else {
+ putchar(' '); /* Don't modify the scrollbar */
+ }
}
static jmp_buf timeout_jump;
int mygetkey(clock_t timeout)
{
- clock_t t0, t;
- clock_t tto, to;
- int key;
+ clock_t t0, t;
+ clock_t tto, to;
+ int key;
- if ( !totaltimeout )
- return get_key(stdin, timeout);
+ if (!totaltimeout)
+ return get_key(stdin, timeout);
- for (;;) {
- tto = min(totaltimeout, INT_MAX);
- to = timeout ? min(tto, timeout) : tto;
+ for (;;) {
+ tto = min(totaltimeout, INT_MAX);
+ to = timeout ? min(tto, timeout) : tto;
- t0 = times(NULL);
- key = get_key(stdin, to);
- t = times(NULL) - t0;
+ t0 = times(NULL);
+ key = get_key(stdin, to);
+ t = times(NULL) - t0;
- if ( totaltimeout <= t )
- longjmp(timeout_jump, 1);
+ if (totaltimeout <= t)
+ longjmp(timeout_jump, 1);
- totaltimeout -= t;
+ totaltimeout -= t;
- if ( key != KEY_NONE )
- return key;
+ if (key != KEY_NONE)
+ return key;
- if ( timeout ) {
- if ( timeout <= t )
- return KEY_NONE;
+ if (timeout) {
+ if (timeout <= t)
+ return KEY_NONE;
- timeout -= t;
+ timeout -= t;
+ }
}
- }
}
-static int
-ask_passwd(const char *menu_entry)
+static int ask_passwd(const char *menu_entry)
{
- char user_passwd[WIDTH], *p;
- int done;
- int key;
- int x;
- int rv;
-
- printf("\033[%d;%dH\2#11\016l", PASSWD_ROW, PASSWD_MARGIN+1);
- for ( x = 2 ; x <= WIDTH-2*PASSWD_MARGIN-1 ; x++ )
- putchar('q');
-
- printf("k\033[%d;%dHx", PASSWD_ROW+1, PASSWD_MARGIN+1);
- for ( x = 2 ; x <= WIDTH-2*PASSWD_MARGIN-1 ; x++ )
- putchar(' ');
-
- printf("x\033[%d;%dHm", PASSWD_ROW+2, PASSWD_MARGIN+1);
- for ( x = 2 ; x <= WIDTH-2*PASSWD_MARGIN-1 ; x++ )
- putchar('q');
-
- printf("j\017\033[%d;%dH\2#12 %s \033[%d;%dH\2#13",
- PASSWD_ROW, (WIDTH-(strlen(cm->messages[MSG_PASSPROMPT])+2))/2,
- cm->messages[MSG_PASSPROMPT], PASSWD_ROW+1, PASSWD_MARGIN+3);
-
- drain_keyboard();
-
- /* Actually allow user to type a password, then compare to the SHA1 */
- done = 0;
- p = user_passwd;
-
- while ( !done ) {
- key = mygetkey(0);
-
- switch ( key ) {
- case KEY_ENTER:
- case KEY_CTRL('J'):
- done = 1;
- break;
-
- case KEY_ESC:
- case KEY_CTRL('C'):
- p = user_passwd; /* No password entered */
- done = 1;
- break;
-
- case KEY_BACKSPACE:
- case KEY_DEL:
- case KEY_DELETE:
- if ( p > user_passwd ) {
- printf("\b \b");
- p--;
- }
- break;
-
- case KEY_CTRL('U'):
- while ( p > user_passwd ) {
- printf("\b \b");
- p--;
- }
- break;
+ char user_passwd[WIDTH], *p;
+ int done;
+ int key;
+ int x;
+ int rv;
+
+ printf("\033[%d;%dH\2#11\016l", PASSWD_ROW, PASSWD_MARGIN + 1);
+ for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++)
+ putchar('q');
+
+ printf("k\033[%d;%dHx", PASSWD_ROW + 1, PASSWD_MARGIN + 1);
+ for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++)
+ putchar(' ');
+
+ printf("x\033[%d;%dHm", PASSWD_ROW + 2, PASSWD_MARGIN + 1);
+ for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++)
+ putchar('q');
+
+ printf("j\017\033[%d;%dH\2#12 %s \033[%d;%dH\2#13",
+ PASSWD_ROW, (WIDTH - (strlen(cm->messages[MSG_PASSPROMPT]) + 2)) / 2,
+ cm->messages[MSG_PASSPROMPT], PASSWD_ROW + 1, PASSWD_MARGIN + 3);
+
+ drain_keyboard();
+
+ /* Actually allow user to type a password, then compare to the SHA1 */
+ done = 0;
+ p = user_passwd;
+
+ while (!done) {
+ key = mygetkey(0);
+
+ switch (key) {
+ case KEY_ENTER:
+ case KEY_CTRL('J'):
+ done = 1;
+ break;
+
+ case KEY_ESC:
+ case KEY_CTRL('C'):
+ p = user_passwd; /* No password entered */
+ done = 1;
+ break;
+
+ case KEY_BACKSPACE:
+ case KEY_DEL:
+ case KEY_DELETE:
+ if (p > user_passwd) {
+ printf("\b \b");
+ p--;
+ }
+ break;
+
+ case KEY_CTRL('U'):
+ while (p > user_passwd) {
+ printf("\b \b");
+ p--;
+ }
+ break;
- default:
- if ( key >= ' ' && key <= 0xFF &&
- (p-user_passwd) < WIDTH-2*PASSWD_MARGIN-5 ) {
- *p++ = key;
- putchar('*');
- }
- break;
+ default:
+ if (key >= ' ' && key <= 0xFF &&
+ (p - user_passwd) < WIDTH - 2 * PASSWD_MARGIN - 5) {
+ *p++ = key;
+ putchar('*');
+ }
+ break;
+ }
}
- }
- if ( p == user_passwd )
- return 0; /* No password entered */
+ if (p == user_passwd)
+ return 0; /* No password entered */
- *p = '\0';
+ *p = '\0';
- rv = (cm->menu_master_passwd &&
- passwd_compare(cm->menu_master_passwd, user_passwd))
- || (menu_entry && passwd_compare(menu_entry, user_passwd));
+ rv = (cm->menu_master_passwd &&
+ passwd_compare(cm->menu_master_passwd, user_passwd))
+ || (menu_entry && passwd_compare(menu_entry, user_passwd));
- /* Clean up */
- memset(user_passwd, 0, WIDTH);
- drain_keyboard();
+ /* Clean up */
+ memset(user_passwd, 0, WIDTH);
+ drain_keyboard();
- return rv;
+ return rv;
}
-
-static void
-draw_menu(int sel, int top, int edit_line)
+static void draw_menu(int sel, int top, int edit_line)
{
- int x, y;
- int sbtop = 0, sbbot = 0;
- const char *tabmsg;
- int tabmsg_len;
-
- if ( cm->nentries > MENU_ROWS ) {
- int sblen = max(MENU_ROWS*MENU_ROWS/cm->nentries, 1);
- sbtop = (MENU_ROWS-sblen+1)*top/(cm->nentries-MENU_ROWS+1);
- sbbot = sbtop+sblen-1;
- sbtop += 4; sbbot += 4; /* Starting row of scrollbar */
- }
-
- printf("\033[%d;%dH\1#1\016l", VSHIFT+1, HSHIFT+MARGIN+1);
- for ( x = 2+HSHIFT ; x <= (WIDTH-2*MARGIN-1)+HSHIFT ; x++ )
- putchar('q');
-
- printf("k\033[%d;%dH\1#1x\017\1#2 %s \1#1\016x",
- VSHIFT+2,
- HSHIFT+MARGIN+1,
- pad_line(cm->title, 1, WIDTH-2*MARGIN-4));
-
- printf("\033[%d;%dH\1#1t", VSHIFT+3, HSHIFT+MARGIN+1);
- for ( x = 2+HSHIFT ; x <= (WIDTH-2*MARGIN-1)+HSHIFT ; x++ )
- putchar('q');
- fputs("u\017", stdout);
-
- for ( y = 4+VSHIFT ; y < 4+VSHIFT+MENU_ROWS ; y++ )
- draw_row(y, sel, top, sbtop, sbbot);
-
- printf("\033[%d;%dH\1#1\016m", y, HSHIFT+MARGIN+1);
- for ( x = 2+HSHIFT ; x <= (WIDTH-2*MARGIN-1)+HSHIFT ; x++ )
- putchar('q');
- fputs("j\017", stdout);
-
- if ( edit_line && cm->allowedit && !cm->menu_master_passwd )
- tabmsg = cm->messages[MSG_TAB];
- else
- tabmsg = cm->messages[MSG_NOTAB];
-
- tabmsg_len = strlen(tabmsg);
-
- printf("\1#8\033[%d;%dH%s",
- TABMSG_ROW, 1+HSHIFT+((WIDTH-tabmsg_len)>>1), tabmsg);
- printf("\1#0\033[%d;1H", END_ROW);
+ int x, y;
+ int sbtop = 0, sbbot = 0;
+ const char *tabmsg;
+ int tabmsg_len;
+
+ if (cm->nentries > MENU_ROWS) {
+ int sblen = max(MENU_ROWS * MENU_ROWS / cm->nentries, 1);
+ sbtop = (MENU_ROWS - sblen + 1) * top / (cm->nentries - MENU_ROWS + 1);
+ sbbot = sbtop + sblen - 1;
+ sbtop += 4;
+ sbbot += 4; /* Starting row of scrollbar */
+ }
+
+ printf("\033[%d;%dH\1#1\016l", VSHIFT + 1, HSHIFT + MARGIN + 1);
+ for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++)
+ putchar('q');
+
+ printf("k\033[%d;%dH\1#1x\017\1#2 %s \1#1\016x",
+ VSHIFT + 2,
+ HSHIFT + MARGIN + 1, pad_line(cm->title, 1, WIDTH - 2 * MARGIN - 4));
+
+ printf("\033[%d;%dH\1#1t", VSHIFT + 3, HSHIFT + MARGIN + 1);
+ for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++)
+ putchar('q');
+ fputs("u\017", stdout);
+
+ for (y = 4 + VSHIFT; y < 4 + VSHIFT + MENU_ROWS; y++)
+ draw_row(y, sel, top, sbtop, sbbot);
+
+ printf("\033[%d;%dH\1#1\016m", y, HSHIFT + MARGIN + 1);
+ for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++)
+ putchar('q');
+ fputs("j\017", stdout);
+
+ if (edit_line && cm->allowedit && !cm->menu_master_passwd)
+ tabmsg = cm->messages[MSG_TAB];
+ else
+ tabmsg = cm->messages[MSG_NOTAB];
+
+ tabmsg_len = strlen(tabmsg);
+
+ printf("\1#8\033[%d;%dH%s",
+ TABMSG_ROW, 1 + HSHIFT + ((WIDTH - tabmsg_len) >> 1), tabmsg);
+ printf("\1#0\033[%d;1H", END_ROW);
}
-static void
-clear_screen(void)
+static void clear_screen(void)
{
- fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
+ fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
}
-static void
-display_help(const char *text)
+static void display_help(const char *text)
{
- int row;
- const char *p;
-
- if (!text) {
- text = "";
- printf("\1#0\033[%d;1H", HELPMSG_ROW);
- } else {
- printf("\2#16\033[%d;1H", HELPMSG_ROW);
- }
-
- for (p = text, row = HELPMSG_ROW; *p && row <= HELPMSGEND_ROW; p++) {
- switch (*p) {
- case '\r':
- case '\f':
- case '\v':
- case '\033':
- break;
- case '\n':
- printf("\033[K\033[%d;1H", ++row);
- break;
- default:
- putchar(*p);
+ int row;
+ const char *p;
+
+ if (!text) {
+ text = "";
+ printf("\1#0\033[%d;1H", HELPMSG_ROW);
+ } else {
+ printf("\2#16\033[%d;1H", HELPMSG_ROW);
}
- }
- fputs("\033[K", stdout);
+ for (p = text, row = HELPMSG_ROW; *p && row <= HELPMSGEND_ROW; p++) {
+ switch (*p) {
+ case '\r':
+ case '\f':
+ case '\v':
+ case '\033':
+ break;
+ case '\n':
+ printf("\033[K\033[%d;1H", ++row);
+ break;
+ default:
+ putchar(*p);
+ }
+ }
- while (row <= HELPMSGEND_ROW) {
- printf("\033[K\033[%d;1H", ++row);
- }
+ fputs("\033[K", stdout);
+
+ while (row <= HELPMSGEND_ROW) {
+ printf("\033[K\033[%d;1H", ++row);
+ }
}
static void show_fkey(int key)
{
- int fkey;
-
- while (1) {
- switch (key) {
- case KEY_F1: fkey = 0; break;
- case KEY_F2: fkey = 1; break;
- case KEY_F3: fkey = 2; break;
- case KEY_F4: fkey = 3; break;
- case KEY_F5: fkey = 4; break;
- case KEY_F6: fkey = 5; break;
- case KEY_F7: fkey = 6; break;
- case KEY_F8: fkey = 7; break;
- case KEY_F9: fkey = 8; break;
- case KEY_F10: fkey = 9; break;
- case KEY_F11: fkey = 10; break;
- case KEY_F12: fkey = 11; break;
- default: fkey = -1; break;
- }
+ int fkey;
+
+ while (1) {
+ switch (key) {
+ case KEY_F1:
+ fkey = 0;
+ break;
+ case KEY_F2:
+ fkey = 1;
+ break;
+ case KEY_F3:
+ fkey = 2;
+ break;
+ case KEY_F4:
+ fkey = 3;
+ break;
+ case KEY_F5:
+ fkey = 4;
+ break;
+ case KEY_F6:
+ fkey = 5;
+ break;
+ case KEY_F7:
+ fkey = 6;
+ break;
+ case KEY_F8:
+ fkey = 7;
+ break;
+ case KEY_F9:
+ fkey = 8;
+ break;
+ case KEY_F10:
+ fkey = 9;
+ break;
+ case KEY_F11:
+ fkey = 10;
+ break;
+ case KEY_F12:
+ fkey = 11;
+ break;
+ default:
+ fkey = -1;
+ break;
+ }
- if (fkey == -1)
- break;
+ if (fkey == -1)
+ break;
- if (cm->fkeyhelp[fkey].textname)
- key = show_message_file(cm->fkeyhelp[fkey].textname,
- cm->fkeyhelp[fkey].background);
- else
- break;
- }
+ if (cm->fkeyhelp[fkey].textname)
+ key = show_message_file(cm->fkeyhelp[fkey].textname,
+ cm->fkeyhelp[fkey].background);
+ else
+ break;
+ }
}
-static const char *
-edit_cmdline(const char *input, int top)
+static const char *edit_cmdline(const char *input, int top)
{
- static char cmdline[MAX_CMDLINE_LEN];
- int key, len, prev_len, cursor;
- int redraw = 1; /* We enter with the menu already drawn */
-
- strncpy(cmdline, input, MAX_CMDLINE_LEN);
- cmdline[MAX_CMDLINE_LEN-1] = '\0';
-
- len = cursor = strlen(cmdline);
- prev_len = 0;
-
- for (;;) {
- if ( redraw > 1 ) {
- /* Clear and redraw whole screen */
- /* Enable ASCII on G0 and DEC VT on G1; do it in this order
- to avoid confusing the Linux console */
- clear_screen();
- draw_menu(-1, top, 1);
- prev_len = 0;
- }
+ static char cmdline[MAX_CMDLINE_LEN];
+ int key, len, prev_len, cursor;
+ int redraw = 1; /* We enter with the menu already drawn */
+
+ strncpy(cmdline, input, MAX_CMDLINE_LEN);
+ cmdline[MAX_CMDLINE_LEN - 1] = '\0';
+
+ len = cursor = strlen(cmdline);
+ prev_len = 0;
+
+ for (;;) {
+ if (redraw > 1) {
+ /* Clear and redraw whole screen */
+ /* Enable ASCII on G0 and DEC VT on G1; do it in this order
+ to avoid confusing the Linux console */
+ clear_screen();
+ draw_menu(-1, top, 1);
+ prev_len = 0;
+ }
- if ( redraw > 0 ) {
- /* Redraw the command line */
- printf("\033[?25l\033[%d;1H\1#9> \2#10%s",
- CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len)));
- printf("\2#10\033[%d;3H%s\033[?25h",
- CMDLINE_ROW, pad_line(cmdline, 0, cursor));
- prev_len = len;
- redraw = 0;
- }
+ if (redraw > 0) {
+ /* Redraw the command line */
+ printf("\033[?25l\033[%d;1H\1#9> \2#10%s",
+ CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len)));
+ printf("\2#10\033[%d;3H%s\033[?25h",
+ CMDLINE_ROW, pad_line(cmdline, 0, cursor));
+ prev_len = len;
+ redraw = 0;
+ }
- key = mygetkey(0);
-
- switch( key ) {
- case KEY_CTRL('L'):
- redraw = 2;
- break;
-
- case KEY_ENTER:
- case KEY_CTRL('J'):
- return cmdline;
-
- case KEY_ESC:
- case KEY_CTRL('C'):
- return NULL;
-
- case KEY_BACKSPACE:
- case KEY_DEL:
- if ( cursor ) {
- memmove(cmdline+cursor-1, cmdline+cursor, len-cursor+1);
- len--;
- cursor--;
- redraw = 1;
- }
- break;
-
- case KEY_CTRL('D'):
- case KEY_DELETE:
- if ( cursor < len ) {
- memmove(cmdline+cursor, cmdline+cursor+1, len-cursor);
- len--;
- redraw = 1;
- }
- break;
-
- case KEY_CTRL('U'):
- if ( len ) {
- len = cursor = 0;
- cmdline[len] = '\0';
- redraw = 1;
- }
- break;
-
- case KEY_CTRL('W'):
- if ( cursor ) {
- int prevcursor = cursor;
-
- while ( cursor && my_isspace(cmdline[cursor-1]) )
- cursor--;
-
- while ( cursor && !my_isspace(cmdline[cursor-1]) )
- cursor--;
-
- memmove(cmdline+cursor, cmdline+prevcursor, len-prevcursor+1);
- len -= (cursor-prevcursor);
- redraw = 1;
- }
- break;
-
- case KEY_LEFT:
- case KEY_CTRL('B'):
- if ( cursor ) {
- cursor--;
- redraw = 1;
- }
- break;
-
- case KEY_RIGHT:
- case KEY_CTRL('F'):
- if ( cursor < len ) {
- putchar(cmdline[cursor++]);
- }
- break;
-
- case KEY_CTRL('K'):
- if ( cursor < len ) {
- cmdline[len = cursor] = '\0';
- redraw = 1;
- }
- break;
-
- case KEY_HOME:
- case KEY_CTRL('A'):
- if ( cursor ) {
- cursor = 0;
- redraw = 1;
- }
- break;
-
- case KEY_END:
- case KEY_CTRL('E'):
- if ( cursor != len ) {
- cursor = len;
- redraw = 1;
- }
- break;
-
- case KEY_F1:
- case KEY_F2:
- case KEY_F3:
- case KEY_F4:
- case KEY_F5:
- case KEY_F6:
- case KEY_F7:
- case KEY_F8:
- case KEY_F9:
- case KEY_F10:
- case KEY_F11:
- case KEY_F12:
- show_fkey(key);
- redraw = 1;
- break;
+ key = mygetkey(0);
+
+ switch (key) {
+ case KEY_CTRL('L'):
+ redraw = 2;
+ break;
+
+ case KEY_ENTER:
+ case KEY_CTRL('J'):
+ return cmdline;
+
+ case KEY_ESC:
+ case KEY_CTRL('C'):
+ return NULL;
+
+ case KEY_BACKSPACE:
+ case KEY_DEL:
+ if (cursor) {
+ memmove(cmdline + cursor - 1, cmdline + cursor,
+ len - cursor + 1);
+ len--;
+ cursor--;
+ redraw = 1;
+ }
+ break;
+
+ case KEY_CTRL('D'):
+ case KEY_DELETE:
+ if (cursor < len) {
+ memmove(cmdline + cursor, cmdline + cursor + 1, len - cursor);
+ len--;
+ redraw = 1;
+ }
+ break;
+
+ case KEY_CTRL('U'):
+ if (len) {
+ len = cursor = 0;
+ cmdline[len] = '\0';
+ redraw = 1;
+ }
+ break;
+
+ case KEY_CTRL('W'):
+ if (cursor) {
+ int prevcursor = cursor;
+
+ while (cursor && my_isspace(cmdline[cursor - 1]))
+ cursor--;
+
+ while (cursor && !my_isspace(cmdline[cursor - 1]))
+ cursor--;
+
+ memmove(cmdline + cursor, cmdline + prevcursor,
+ len - prevcursor + 1);
+ len -= (cursor - prevcursor);
+ redraw = 1;
+ }
+ break;
+
+ case KEY_LEFT:
+ case KEY_CTRL('B'):
+ if (cursor) {
+ cursor--;
+ redraw = 1;
+ }
+ break;
+
+ case KEY_RIGHT:
+ case KEY_CTRL('F'):
+ if (cursor < len) {
+ putchar(cmdline[cursor++]);
+ }
+ break;
+
+ case KEY_CTRL('K'):
+ if (cursor < len) {
+ cmdline[len = cursor] = '\0';
+ redraw = 1;
+ }
+ break;
+
+ case KEY_HOME:
+ case KEY_CTRL('A'):
+ if (cursor) {
+ cursor = 0;
+ redraw = 1;
+ }
+ break;
+
+ case KEY_END:
+ case KEY_CTRL('E'):
+ if (cursor != len) {
+ cursor = len;
+ redraw = 1;
+ }
+ break;
+
+ case KEY_F1:
+ case KEY_F2:
+ case KEY_F3:
+ case KEY_F4:
+ case KEY_F5:
+ case KEY_F6:
+ case KEY_F7:
+ case KEY_F8:
+ case KEY_F9:
+ case KEY_F10:
+ case KEY_F11:
+ case KEY_F12:
+ show_fkey(key);
+ redraw = 1;
+ break;
- default:
- if ( key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN-1 ) {
- if ( cursor == len ) {
- cmdline[len] = key;
- cmdline[++len] = '\0';
- cursor++;
- putchar(key);
- prev_len++;
- } else {
- memmove(cmdline+cursor+1, cmdline+cursor, len-cursor+1);
- cmdline[cursor++] = key;
- len++;
- redraw = 1;
+ default:
+ if (key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN - 1) {
+ if (cursor == len) {
+ cmdline[len] = key;
+ cmdline[++len] = '\0';
+ cursor++;
+ putchar(key);
+ prev_len++;
+ } else {
+ memmove(cmdline + cursor + 1, cmdline + cursor,
+ len - cursor + 1);
+ cmdline[cursor++] = key;
+ len++;
+ redraw = 1;
+ }
+ }
+ break;
}
- }
- break;
}
- }
}
-static inline int
-shift_is_held(void)
+static inline int shift_is_held(void)
{
- uint8_t shift_bits = *(uint8_t *)0x417;
+ uint8_t shift_bits = *(uint8_t *) 0x417;
- return !!(shift_bits & 0x5d); /* Caps/Scroll/Alt/Shift */
+ return !!(shift_bits & 0x5d); /* Caps/Scroll/Alt/Shift */
}
-static void
-print_timeout_message(int tol, int row, const char *msg)
+static void print_timeout_message(int tol, int row, const char *msg)
{
- char buf[256];
- int nc = 0, nnc;
- const char *tp = msg;
- char tc;
- char *tq = buf;
-
- while ((size_t)(tq-buf) < (sizeof buf-16) && (tc = *tp)) {
- tp++;
- if (tc == '#') {
- nnc = sprintf(tq, "\2#15%d\2#14", tol);
- tq += nnc;
- nc += nnc-8; /* 8 formatting characters */
- } else if (tc == '{') {
- /* Deal with {singular[,dual],plural} constructs */
- struct {
- const char *s, *e;
- } tx[3];
- const char *tpp;
- int n = 0;
-
- memset(tx, 0, sizeof tx);
-
- tx[0].s = tp;
-
- while (*tp && *tp != '}') {
- if (*tp == ',' && n < 2) {
- tx[n].e = tp;
- n++;
- tx[n].s = tp+1;
- }
+ char buf[256];
+ int nc = 0, nnc;
+ const char *tp = msg;
+ char tc;
+ char *tq = buf;
+
+ while ((size_t) (tq - buf) < (sizeof buf - 16) && (tc = *tp)) {
tp++;
- }
- tx[n].e = tp;
-
- if (*tp)
- tp++; /* Skip final bracket */
-
- if (!tx[1].s)
- tx[1] = tx[0];
- if (!tx[2].s)
- tx[2] = tx[1];
-
- /* Now [0] is singular, [1] is dual, and [2] is plural,
- even if the user only specified some of them. */
-
- switch (tol) {
- case 1: n = 0; break;
- case 2: n = 1; break;
- default: n = 2; break;
- }
-
- for (tpp = tx[n].s; tpp < tx[n].e; tpp++) {
- if ((size_t)(tq-buf) < (sizeof buf)) {
- *tq++ = *tpp;
- nc++;
+ if (tc == '#') {
+ nnc = sprintf(tq, "\2#15%d\2#14", tol);
+ tq += nnc;
+ nc += nnc - 8; /* 8 formatting characters */
+ } else if (tc == '{') {
+ /* Deal with {singular[,dual],plural} constructs */
+ struct {
+ const char *s, *e;
+ } tx[3];
+ const char *tpp;
+ int n = 0;
+
+ memset(tx, 0, sizeof tx);
+
+ tx[0].s = tp;
+
+ while (*tp && *tp != '}') {
+ if (*tp == ',' && n < 2) {
+ tx[n].e = tp;
+ n++;
+ tx[n].s = tp + 1;
+ }
+ tp++;
+ }
+ tx[n].e = tp;
+
+ if (*tp)
+ tp++; /* Skip final bracket */
+
+ if (!tx[1].s)
+ tx[1] = tx[0];
+ if (!tx[2].s)
+ tx[2] = tx[1];
+
+ /* Now [0] is singular, [1] is dual, and [2] is plural,
+ even if the user only specified some of them. */
+
+ switch (tol) {
+ case 1:
+ n = 0;
+ break;
+ case 2:
+ n = 1;
+ break;
+ default:
+ n = 2;
+ break;
+ }
+
+ for (tpp = tx[n].s; tpp < tx[n].e; tpp++) {
+ if ((size_t) (tq - buf) < (sizeof buf)) {
+ *tq++ = *tpp;
+ nc++;
+ }
+ }
+ } else {
+ *tq++ = tc;
+ nc++;
}
- }
- } else {
- *tq++ = tc;
- nc++;
}
- }
- *tq = '\0';
+ *tq = '\0';
- /* Let's hope 4 spaces on each side is enough... */
- printf("\033[%d;%dH\2#14 %s ", row, HSHIFT+1+((WIDTH-nc-8)>>1), buf);
+ /* Let's hope 4 spaces on each side is enough... */
+ printf("\033[%d;%dH\2#14 %s ", row,
+ HSHIFT + 1 + ((WIDTH - nc - 8) >> 1), buf);
}
/* Set the background screen, etc. */
-static void
-prepare_screen_for_menu(void)
+static void prepare_screen_for_menu(void)
{
- console_color_table = cm->color_table;
- console_color_table_size = menu_color_table_size;
- set_background(cm->menu_background);
+ console_color_table = cm->color_table;
+ console_color_table_size = menu_color_table_size;
+ set_background(cm->menu_background);
}
-static const char *
-do_hidden_menu(void)
+static const char *do_hidden_menu(void)
{
- int key;
- int timeout_left, this_timeout;
+ int key;
+ int timeout_left, this_timeout;
- clear_screen();
+ clear_screen();
- if ( !setjmp(timeout_jump) ) {
- timeout_left = cm->timeout;
+ if (!setjmp(timeout_jump)) {
+ timeout_left = cm->timeout;
- while (!cm->timeout || timeout_left) {
- int tol = timeout_left/CLK_TCK;
+ while (!cm->timeout || timeout_left) {
+ int tol = timeout_left / CLK_TCK;
- print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);
+ print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);
- this_timeout = min(timeout_left, CLK_TCK);
- key = mygetkey(this_timeout);
+ this_timeout = min(timeout_left, CLK_TCK);
+ key = mygetkey(this_timeout);
- if (key != KEY_NONE)
- return NULL; /* Key pressed */
+ if (key != KEY_NONE)
+ return NULL; /* Key pressed */
- timeout_left -= this_timeout;
+ timeout_left -= this_timeout;
+ }
}
- }
- return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
+ return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
}
-static const char *
-run_menu(void)
+static const char *run_menu(void)
{
- int key;
- int done = 0;
- volatile int entry = cm->curentry;
- int prev_entry = -1;
- volatile int top = cm->curtop;
- int prev_top = -1;
- int clear = 1, to_clear;
- const char *cmdline = NULL;
- volatile clock_t key_timeout, timeout_left, this_timeout;
- const struct menu_entry *me;
-
- /* Note: for both key_timeout and timeout == 0 means no limit */
- timeout_left = key_timeout = cm->timeout;
-
- /* If we're in shiftkey mode, exit immediately unless a shift key
- is pressed */
- if ( shiftkey && !shift_is_held() ) {
- return cm->menu_entries[cm->defentry]->cmdline;
- } else {
- shiftkey = 0;
- }
-
- /* Do this before hiddenmenu handling, so we show the background */
- prepare_screen_for_menu();
-
- /* Handle hiddenmenu */
- if ( hiddenmenu ) {
- cmdline = do_hidden_menu();
- if (cmdline)
- return cmdline;
-
- /* Otherwise display the menu now; the timeout has already been
- cancelled, since the user pressed a key. */
- hiddenmenu = 0;
- key_timeout = 0;
- }
-
- /* Handle both local and global timeout */
- if ( setjmp(timeout_jump) ) {
- entry = cm->defentry;
-
- if ( top < 0 || top < entry-MENU_ROWS+1 )
- top = max(0, entry-MENU_ROWS+1);
- else if ( top > entry || top > max(0, cm->nentries-MENU_ROWS) )
- top = min(entry, max(0, cm->nentries-MENU_ROWS));
-
- draw_menu(cm->ontimeout ? -1 : entry, top, 1);
- cmdline = cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline;
- done = 1;
- }
-
- while ( !done ) {
- if (entry <= 0) {
- entry = 0;
- while (entry < cm->nentries && is_disabled(cm->menu_entries[entry]))
- entry++;
- }
- if (entry >= cm->nentries) {
- entry = cm->nentries-1;
- while (entry > 0 && is_disabled(cm->menu_entries[entry]))
- entry--;
- }
-
- me = cm->menu_entries[entry];
-
- if ( top < 0 || top < entry-MENU_ROWS+1 )
- top = max(0, entry-MENU_ROWS+1);
- else if ( top > entry || top > max(0, cm->nentries-MENU_ROWS) )
- top = min(entry, max(0, cm->nentries-MENU_ROWS));
-
- /* Start with a clear screen */
- if ( clear ) {
- /* Clear and redraw whole screen */
- /* Enable ASCII on G0 and DEC VT on G1; do it in this order
- to avoid confusing the Linux console */
- if (clear >= 2)
- prepare_screen_for_menu();
- clear_screen();
- clear = 0;
- prev_entry = prev_top = -1;
- }
-
- if ( top != prev_top ) {
- draw_menu(entry, top, 1);
- display_help(me->helptext);
- } else if ( entry != prev_entry ) {
- draw_row(prev_entry-top+4+VSHIFT, entry, top, 0, 0);
- draw_row(entry-top+4+VSHIFT, entry, top, 0, 0);
- display_help(me->helptext);
+ int key;
+ int done = 0;
+ volatile int entry = cm->curentry;
+ int prev_entry = -1;
+ volatile int top = cm->curtop;
+ int prev_top = -1;
+ int clear = 1, to_clear;
+ const char *cmdline = NULL;
+ volatile clock_t key_timeout, timeout_left, this_timeout;
+ const struct menu_entry *me;
+
+ /* Note: for both key_timeout and timeout == 0 means no limit */
+ timeout_left = key_timeout = cm->timeout;
+
+ /* If we're in shiftkey mode, exit immediately unless a shift key
+ is pressed */
+ if (shiftkey && !shift_is_held()) {
+ return cm->menu_entries[cm->defentry]->cmdline;
+ } else {
+ shiftkey = 0;
}
- prev_entry = entry; prev_top = top;
- cm->curentry = entry;
- cm->curtop = top;
+ /* Do this before hiddenmenu handling, so we show the background */
+ prepare_screen_for_menu();
- /* Cursor movement cancels timeout */
- if ( entry != cm->defentry )
- key_timeout = 0;
+ /* Handle hiddenmenu */
+ if (hiddenmenu) {
+ cmdline = do_hidden_menu();
+ if (cmdline)
+ return cmdline;
- if ( key_timeout ) {
- int tol = timeout_left/CLK_TCK;
- print_timeout_message(tol, TIMEOUT_ROW, cm->messages[MSG_AUTOBOOT]);
- to_clear = 1;
- } else {
- to_clear = 0;
+ /* Otherwise display the menu now; the timeout has already been
+ cancelled, since the user pressed a key. */
+ hiddenmenu = 0;
+ key_timeout = 0;
}
- this_timeout = min(min(key_timeout, timeout_left), (clock_t)CLK_TCK);
- key = mygetkey(this_timeout);
+ /* Handle both local and global timeout */
+ if (setjmp(timeout_jump)) {
+ entry = cm->defentry;
- if ( key != KEY_NONE ) {
- timeout_left = key_timeout;
- if ( to_clear )
- printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW);
- }
+ if (top < 0 || top < entry - MENU_ROWS + 1)
+ top = max(0, entry - MENU_ROWS + 1);
+ else if (top > entry || top > max(0, cm->nentries - MENU_ROWS))
+ top = min(entry, max(0, cm->nentries - MENU_ROWS));
- switch ( key ) {
- case KEY_NONE: /* Timeout */
- /* This is somewhat hacky, but this at least lets the user
- know what's going on, and still deals with "phantom inputs"
- e.g. on serial ports.
-
- Warning: a timeout will boot the default entry without any
- password! */
- if ( key_timeout ) {
- if ( timeout_left <= this_timeout )
- longjmp(timeout_jump, 1);
-
- timeout_left -= this_timeout;
- }
- break;
-
- case KEY_CTRL('L'):
- clear = 1;
- break;
-
- case KEY_ENTER:
- case KEY_CTRL('J'):
- key_timeout = 0; /* Cancels timeout */
- if ( me->passwd ) {
- clear = 1;
- done = ask_passwd(me->passwd);
- } else {
+ draw_menu(cm->ontimeout ? -1 : entry, top, 1);
+ cmdline =
+ cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline;
done = 1;
- }
- cmdline = NULL;
- if (done) {
- switch (me->action) {
- case MA_CMD:
- cmdline = me->cmdline;
- break;
- case MA_SUBMENU:
- case MA_GOTO:
- case MA_EXIT:
- done = 0;
- clear = 2;
- cm = me->submenu;
- entry = cm->curentry;
- top = cm->curtop;
- break;
- case MA_QUIT:
- /* Quit menu system */
- done = 1;
- clear = 1;
- draw_row(entry-top+4+VSHIFT, -1, top, 0, 0);
- break;
- default:
- done = 0;
- break;
+ }
+
+ while (!done) {
+ if (entry <= 0) {
+ entry = 0;
+ while (entry < cm->nentries && is_disabled(cm->menu_entries[entry]))
+ entry++;
}
- }
- if (done && !me->passwd) {
- /* Only save a new default if we don't have a password... */
- if (me->save && me->label) {
- syslinux_setadv(ADV_MENUSAVE, strlen(me->label), me->label);
- syslinux_adv_write();
+ if (entry >= cm->nentries) {
+ entry = cm->nentries - 1;
+ while (entry > 0 && is_disabled(cm->menu_entries[entry]))
+ entry--;
}
- }
- break;
-
- case KEY_UP:
- case KEY_CTRL('P'):
- while (entry > 0) {
- entry--;
- if (entry < top)
- top -= MENU_ROWS;
- if (!is_disabled(cm->menu_entries[entry]))
- break;
- }
- break;
-
- case KEY_DOWN:
- case KEY_CTRL('N'):
- while (entry < cm->nentries-1) {
- entry++;
- if (entry >= top+MENU_ROWS)
- top += MENU_ROWS;
- if (!is_disabled(cm->menu_entries[entry]))
- break;
- }
- break;
-
- case KEY_PGUP:
- case KEY_LEFT:
- case KEY_CTRL('B'):
- case '<':
- entry -= MENU_ROWS;
- top -= MENU_ROWS;
- while (entry > 0 && is_disabled(cm->menu_entries[entry])) {
- entry--;
- if (entry < top)
- top -= MENU_ROWS;
- }
- break;
-
- case KEY_PGDN:
- case KEY_RIGHT:
- case KEY_CTRL('F'):
- case '>':
- case ' ':
- entry += MENU_ROWS;
- top += MENU_ROWS;
- while (entry < cm->nentries-1 && is_disabled(cm->menu_entries[entry])) {
- entry++;
- if (entry >= top+MENU_ROWS)
- top += MENU_ROWS;
- }
- break;
-
- case '-':
- while (entry > 0) {
- entry--;
- top--;
- if (!is_disabled(cm->menu_entries[entry]))
- break;
- }
- break;
-
- case '+':
- while (entry < cm->nentries-1) {
- entry++;
- top++;
- if (!is_disabled(cm->menu_entries[entry]))
- break;
- }
- break;
-
- case KEY_CTRL('A'):
- case KEY_HOME:
- top = entry = 0;
- break;
-
- case KEY_CTRL('E'):
- case KEY_END:
- entry = cm->nentries - 1;
- top = max(0, cm->nentries-MENU_ROWS);
- break;
-
- case KEY_F1:
- case KEY_F2:
- case KEY_F3:
- case KEY_F4:
- case KEY_F5:
- case KEY_F6:
- case KEY_F7:
- case KEY_F8:
- case KEY_F9:
- case KEY_F10:
- case KEY_F11:
- case KEY_F12:
- show_fkey(key);
- clear = 1;
- break;
-
- case KEY_TAB:
- if ( cm->allowedit && me->action == MA_CMD ) {
- int ok = 1;
-
- key_timeout = 0; /* Cancels timeout */
- draw_row(entry-top+4+VSHIFT, -1, top, 0, 0);
-
- if ( cm->menu_master_passwd ) {
- ok = ask_passwd(NULL);
- clear_screen();
- draw_menu(-1, top, 0);
- } else {
- /* Erase [Tab] message and help text*/
- printf("\033[%d;1H\1#0\033[K", TABMSG_ROW);
- display_help(NULL);
+
+ me = cm->menu_entries[entry];
+
+ if (top < 0 || top < entry - MENU_ROWS + 1)
+ top = max(0, entry - MENU_ROWS + 1);
+ else if (top > entry || top > max(0, cm->nentries - MENU_ROWS))
+ top = min(entry, max(0, cm->nentries - MENU_ROWS));
+
+ /* Start with a clear screen */
+ if (clear) {
+ /* Clear and redraw whole screen */
+ /* Enable ASCII on G0 and DEC VT on G1; do it in this order
+ to avoid confusing the Linux console */
+ if (clear >= 2)
+ prepare_screen_for_menu();
+ clear_screen();
+ clear = 0;
+ prev_entry = prev_top = -1;
+ }
+
+ if (top != prev_top) {
+ draw_menu(entry, top, 1);
+ display_help(me->helptext);
+ } else if (entry != prev_entry) {
+ draw_row(prev_entry - top + 4 + VSHIFT, entry, top, 0, 0);
+ draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0);
+ display_help(me->helptext);
}
- if ( ok ) {
- cmdline = edit_cmdline(me->cmdline, top);
- done = !!cmdline;
- clear = 1; /* In case we hit [Esc] and done is null */
+ prev_entry = entry;
+ prev_top = top;
+ cm->curentry = entry;
+ cm->curtop = top;
+
+ /* Cursor movement cancels timeout */
+ if (entry != cm->defentry)
+ key_timeout = 0;
+
+ if (key_timeout) {
+ int tol = timeout_left / CLK_TCK;
+ print_timeout_message(tol, TIMEOUT_ROW, cm->messages[MSG_AUTOBOOT]);
+ to_clear = 1;
} else {
- draw_row(entry-top+4+VSHIFT, entry, top, 0, 0);
+ to_clear = 0;
}
- }
- break;
- case KEY_CTRL('C'): /* Ctrl-C */
- case KEY_ESC: /* Esc */
- if ( cm->parent ) {
- cm = cm->parent;
- clear = 2;
- entry = cm->curentry;
- top = cm->curtop;
- } else if ( cm->allowedit ) {
- done = 1;
- clear = 1;
- key_timeout = 0;
- draw_row(entry-top+4+VSHIFT, -1, top, 0, 0);
+ this_timeout = min(min(key_timeout, timeout_left), (clock_t) CLK_TCK);
+ key = mygetkey(this_timeout);
- if ( cm->menu_master_passwd )
- done = ask_passwd(NULL);
- }
- break;
- default:
- if ( key > 0 && key < 0xFF ) {
- key &= ~0x20; /* Upper case */
- if ( cm->menu_hotkeys[key] ) {
- key_timeout = 0;
- entry = cm->menu_hotkeys[key]->entry;
- /* Should we commit at this point? */
+ if (key != KEY_NONE) {
+ timeout_left = key_timeout;
+ if (to_clear)
+ printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW);
+ }
+
+ switch (key) {
+ case KEY_NONE: /* Timeout */
+ /* This is somewhat hacky, but this at least lets the user
+ know what's going on, and still deals with "phantom inputs"
+ e.g. on serial ports.
+
+ Warning: a timeout will boot the default entry without any
+ password! */
+ if (key_timeout) {
+ if (timeout_left <= this_timeout)
+ longjmp(timeout_jump, 1);
+
+ timeout_left -= this_timeout;
+ }
+ break;
+
+ case KEY_CTRL('L'):
+ clear = 1;
+ break;
+
+ case KEY_ENTER:
+ case KEY_CTRL('J'):
+ key_timeout = 0; /* Cancels timeout */
+ if (me->passwd) {
+ clear = 1;
+ done = ask_passwd(me->passwd);
+ } else {
+ done = 1;
+ }
+ cmdline = NULL;
+ if (done) {
+ switch (me->action) {
+ case MA_CMD:
+ cmdline = me->cmdline;
+ break;
+ case MA_SUBMENU:
+ case MA_GOTO:
+ case MA_EXIT:
+ done = 0;
+ clear = 2;
+ cm = me->submenu;
+ entry = cm->curentry;
+ top = cm->curtop;
+ break;
+ case MA_QUIT:
+ /* Quit menu system */
+ done = 1;
+ clear = 1;
+ draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0);
+ break;
+ default:
+ done = 0;
+ break;
+ }
+ }
+ if (done && !me->passwd) {
+ /* Only save a new default if we don't have a password... */
+ if (me->save && me->label) {
+ syslinux_setadv(ADV_MENUSAVE, strlen(me->label), me->label);
+ syslinux_adv_write();
+ }
+ }
+ break;
+
+ case KEY_UP:
+ case KEY_CTRL('P'):
+ while (entry > 0) {
+ entry--;
+ if (entry < top)
+ top -= MENU_ROWS;
+ if (!is_disabled(cm->menu_entries[entry]))
+ break;
+ }
+ break;
+
+ case KEY_DOWN:
+ case KEY_CTRL('N'):
+ while (entry < cm->nentries - 1) {
+ entry++;
+ if (entry >= top + MENU_ROWS)
+ top += MENU_ROWS;
+ if (!is_disabled(cm->menu_entries[entry]))
+ break;
+ }
+ break;
+
+ case KEY_PGUP:
+ case KEY_LEFT:
+ case KEY_CTRL('B'):
+ case '<':
+ entry -= MENU_ROWS;
+ top -= MENU_ROWS;
+ while (entry > 0 && is_disabled(cm->menu_entries[entry])) {
+ entry--;
+ if (entry < top)
+ top -= MENU_ROWS;
+ }
+ break;
+
+ case KEY_PGDN:
+ case KEY_RIGHT:
+ case KEY_CTRL('F'):
+ case '>':
+ case ' ':
+ entry += MENU_ROWS;
+ top += MENU_ROWS;
+ while (entry < cm->nentries - 1
+ && is_disabled(cm->menu_entries[entry])) {
+ entry++;
+ if (entry >= top + MENU_ROWS)
+ top += MENU_ROWS;
+ }
+ break;
+
+ case '-':
+ while (entry > 0) {
+ entry--;
+ top--;
+ if (!is_disabled(cm->menu_entries[entry]))
+ break;
+ }
+ break;
+
+ case '+':
+ while (entry < cm->nentries - 1) {
+ entry++;
+ top++;
+ if (!is_disabled(cm->menu_entries[entry]))
+ break;
+ }
+ break;
+
+ case KEY_CTRL('A'):
+ case KEY_HOME:
+ top = entry = 0;
+ break;
+
+ case KEY_CTRL('E'):
+ case KEY_END:
+ entry = cm->nentries - 1;
+ top = max(0, cm->nentries - MENU_ROWS);
+ break;
+
+ case KEY_F1:
+ case KEY_F2:
+ case KEY_F3:
+ case KEY_F4:
+ case KEY_F5:
+ case KEY_F6:
+ case KEY_F7:
+ case KEY_F8:
+ case KEY_F9:
+ case KEY_F10:
+ case KEY_F11:
+ case KEY_F12:
+ show_fkey(key);
+ clear = 1;
+ break;
+
+ case KEY_TAB:
+ if (cm->allowedit && me->action == MA_CMD) {
+ int ok = 1;
+
+ key_timeout = 0; /* Cancels timeout */
+ draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0);
+
+ if (cm->menu_master_passwd) {
+ ok = ask_passwd(NULL);
+ clear_screen();
+ draw_menu(-1, top, 0);
+ } else {
+ /* Erase [Tab] message and help text */
+ printf("\033[%d;1H\1#0\033[K", TABMSG_ROW);
+ display_help(NULL);
+ }
+
+ if (ok) {
+ cmdline = edit_cmdline(me->cmdline, top);
+ done = !!cmdline;
+ clear = 1; /* In case we hit [Esc] and done is null */
+ } else {
+ draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0);
+ }
+ }
+ break;
+ case KEY_CTRL('C'): /* Ctrl-C */
+ case KEY_ESC: /* Esc */
+ if (cm->parent) {
+ cm = cm->parent;
+ clear = 2;
+ entry = cm->curentry;
+ top = cm->curtop;
+ } else if (cm->allowedit) {
+ done = 1;
+ clear = 1;
+ key_timeout = 0;
+
+ draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0);
+
+ if (cm->menu_master_passwd)
+ done = ask_passwd(NULL);
+ }
+ break;
+ default:
+ if (key > 0 && key < 0xFF) {
+ key &= ~0x20; /* Upper case */
+ if (cm->menu_hotkeys[key]) {
+ key_timeout = 0;
+ entry = cm->menu_hotkeys[key]->entry;
+ /* Should we commit at this point? */
+ }
+ }
+ break;
}
- }
- break;
}
- }
- printf("\033[?25h"); /* Show cursor */
+ printf("\033[?25h"); /* Show cursor */
- /* Return the label name so localboot and ipappend work */
- return cmdline;
+ /* Return the label name so localboot and ipappend work */
+ return cmdline;
}
int menu_main(int argc, char *argv[])
{
- const char *cmdline;
- struct menu *m;
- int rows, cols;
- int i;
-
- (void)argc;
-
- if (getscreensize(1, &rows, &cols)) {
- /* Unknown screen size? */
- rows = 24;
- cols = 80;
- }
-
- parse_configs(argv+1);
-
- /* Some postprocessing for all menus */
- for (m = menu_list; m; m = m->next) {
- if (!m->mparm[P_WIDTH])
- m->mparm[P_WIDTH] = cols;
-
- /* If anyone has specified negative parameters, consider them
- relative to the bottom row of the screen. */
- for (i = 0; i < NPARAMS; i++)
- if (m->mparm[i] < 0)
- m->mparm[i] = max(m->mparm[i]+rows, 0);
- }
-
- if ( !cm->nentries ) {
- fputs("Initial menu has no LABEL entries!\n", stdout);
- return 1; /* Error! */
- }
-
- cm = start_menu;
- for(;;) {
- cmdline = run_menu();
-
- printf("\033[?25h\033[%d;1H\033[0m", END_ROW);
-
- if ( cmdline ) {
- execute(cmdline, KT_NONE);
- if ( cm->onerror )
- execute(cm->onerror, KT_NONE);
- } else {
- return 0; /* Exit */
+ const char *cmdline;
+ struct menu *m;
+ int rows, cols;
+ int i;
+
+ (void)argc;
+
+ if (getscreensize(1, &rows, &cols)) {
+ /* Unknown screen size? */
+ rows = 24;
+ cols = 80;
+ }
+
+ parse_configs(argv + 1);
+
+ /* Some postprocessing for all menus */
+ for (m = menu_list; m; m = m->next) {
+ if (!m->mparm[P_WIDTH])
+ m->mparm[P_WIDTH] = cols;
+
+ /* If anyone has specified negative parameters, consider them
+ relative to the bottom row of the screen. */
+ for (i = 0; i < NPARAMS; i++)
+ if (m->mparm[i] < 0)
+ m->mparm[i] = max(m->mparm[i] + rows, 0);
+ }
+
+ if (!cm->nentries) {
+ fputs("Initial menu has no LABEL entries!\n", stdout);
+ return 1; /* Error! */
+ }
+
+ cm = start_menu;
+ for (;;) {
+ cmdline = run_menu();
+
+ printf("\033[?25h\033[%d;1H\033[0m", END_ROW);
+
+ if (cmdline) {
+ execute(cmdline, KT_NONE);
+ if (cm->onerror)
+ execute(cm->onerror, KT_NONE);
+ } else {
+ return 0; /* Exit */
+ }
}
- }
}