diff options
Diffstat (limited to 'com32')
-rw-r--r-- | com32/menu/menumain.c | 1846 |
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 */ + } } - } } |