summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux/syslinux-4.03/com32/menu/menumain.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/com32/menu/menumain.c')
-rw-r--r--contrib/syslinux/syslinux-4.03/com32/menu/menumain.c1164
1 files changed, 0 insertions, 1164 deletions
diff --git a/contrib/syslinux/syslinux-4.03/com32/menu/menumain.c b/contrib/syslinux/syslinux-4.03/com32/menu/menumain.c
deleted file mode 100644
index 06725f3..0000000
--- a/contrib/syslinux/syslinux-4.03/com32/menu/menumain.c
+++ /dev/null
@@ -1,1164 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
- *
- * 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.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * menumain.c
- *
- * Simple menu system which displays a list and allows the user to select
- * a command line and/or edit it.
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <consoles.h>
-#include <getkey.h>
-#include <minmax.h>
-#include <setjmp.h>
-#include <limits.h>
-#include <com32.h>
-#include <syslinux/adv.h>
-
-#include "menu.h"
-
-/* The symbol "cm" always refers to the current menu across this file... */
-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},
-};
-
-/* These macros assume "cm" is a pointer to the current menu */
-#define WIDTH (cm->mparm[P_WIDTH])
-#define MARGIN (cm->mparm[P_MARGIN])
-#define PASSWD_MARGIN (cm->mparm[P_PASSWD_MARGIN])
-#define MENU_ROWS (cm->mparm[P_MENU_ROWS])
-#define TABMSG_ROW (cm->mparm[P_TABMSG_ROW]+VSHIFT)
-#define CMDLINE_ROW (cm->mparm[P_CMDLINE_ROW]+VSHIFT)
-#define END_ROW (cm->mparm[P_END_ROW])
-#define PASSWD_ROW (cm->mparm[P_PASSWD_ROW]+VSHIFT)
-#define TIMEOUT_ROW (cm->mparm[P_TIMEOUT_ROW]+VSHIFT)
-#define HELPMSG_ROW (cm->mparm[P_HELPMSG_ROW]+VSHIFT)
-#define HELPMSGEND_ROW (cm->mparm[P_HELPMSGEND_ROW])
-#define HSHIFT (cm->mparm[P_HSHIFT])
-#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 buffer[MAX_CMDLINE_LEN];
- int n, p;
-
- if (width >= (int)sizeof buffer)
- return NULL; /* Can't do it */
-
- n = strlen(text);
- if (n >= width)
- n = width;
-
- memset(buffer, ' ', width);
- buffer[width] = 0;
- p = ((width - n) * align) >> 1;
- memcpy(buffer + p, text, n);
-
- return buffer;
-}
-
-/* Display an entry, with possible hotkey highlight. Assumes
- that the current attribute is the non-hotkey one, and will
- guarantee that as an exit condition as well. */
-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--;
- }
- } else {
- putchar(*p++);
- width--;
- }
- } else {
- putchar(' ');
- width--;
- }
- }
-
- if (marker) {
- putchar(' ');
- putchar(marker);
- }
-}
-
-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 */
- }
-}
-
-static jmp_buf timeout_jump;
-
-int mygetkey(clock_t timeout)
-{
- clock_t t0, t;
- clock_t tto, to;
- int key;
-
- if (!totaltimeout)
- return get_key(stdin, timeout);
-
- for (;;) {
- tto = min(totaltimeout, INT_MAX);
- to = timeout ? min(tto, timeout) : tto;
-
- t0 = times(NULL);
- key = get_key(stdin, to);
- t = times(NULL) - t0;
-
- if (totaltimeout <= t)
- longjmp(timeout_jump, 1);
-
- totaltimeout -= t;
-
- if (key != KEY_NONE)
- return key;
-
- if (timeout) {
- if (timeout <= t)
- return KEY_NONE;
-
- timeout -= t;
- }
- }
-}
-
-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;
-
- 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 */
-
- *p = '\0';
-
- 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();
-
- return rv;
-}
-
-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);
-}
-
-static void clear_screen(void)
-{
- fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
-}
-
-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);
- }
- }
-
- 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;
- }
-
- if (fkey == -1)
- 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 char cmdline[MAX_CMDLINE_LEN];
- int key, len, prev_len, cursor;
- int redraw = 1; /* We enter with the menu already drawn */
-
- strlcpy(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;
- }
-
- 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 -= (prevcursor - cursor);
- 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;
- }
- }
- break;
- }
- }
-}
-
-static inline int shift_is_held(void)
-{
- uint8_t shift_bits = *(uint8_t *) 0x417;
-
- return !!(shift_bits & 0x5d); /* Caps/Scroll/Alt/Shift */
-}
-
-static void print_timeout_message(int tol, int row, const char *msg)
-{
- static int last_msg_len = 0;
- char buf[256];
- int nc = 0, nnc, padc;
- 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;
- }
- 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++;
- }
- }
- *tq = '\0';
-
- if (nc >= last_msg_len) {
- padc = 0;
- } else {
- padc = (last_msg_len - nc + 1) >> 1;
- }
-
- printf("\033[%d;%dH\2#14%*s%s%*s", row,
- HSHIFT + 1 + ((WIDTH - nc) >> 1) - padc,
- padc, "", buf, padc, "");
-
- last_msg_len = nc;
-}
-
-/* Set the background screen, etc. */
-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);
-}
-
-static const char *do_hidden_menu(void)
-{
- int key;
- int timeout_left, this_timeout;
-
- clear_screen();
-
- if (!setjmp(timeout_jump)) {
- timeout_left = cm->timeout;
-
- while (!cm->timeout || timeout_left) {
- int tol = timeout_left / CLK_TCK;
-
- print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);
-
- this_timeout = min(timeout_left, CLK_TCK);
- key = mygetkey(this_timeout);
-
- if (key != KEY_NONE)
- return NULL; /* Key pressed */
-
- timeout_left -= this_timeout;
- }
- }
-
- /* Clear the message from the screen */
- print_timeout_message(0, HIDDEN_ROW, "");
-
- if (cm->ontimeout)
- return cm->ontimeout;
- else
- return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
-}
-
-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;
- bool hotkey = false;
-
- /* 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);
- }
-
- 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 {
- to_clear = 0;
- }
-
- if (hotkey && me->immediate) {
- /* If the hotkey was flagged immediate, simulate pressing ENTER */
- key = KEY_ENTER;
- } else {
- this_timeout = min(min(key_timeout, timeout_left),
- (clock_t) CLK_TCK);
- key = mygetkey(this_timeout);
-
- if (key != KEY_NONE) {
- timeout_left = key_timeout;
- if (to_clear)
- printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW);
- }
- }
-
- hotkey = false;
-
- 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;
- case MA_HELP:
- key = show_message_file(me->cmdline, me->background);
- /* If the exit was an F-key, display that help screen */
- show_fkey(key);
- done = 0;
- clear = 1;
- 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? */
- hotkey = true;
- }
- }
- break;
- }
- }
-
- printf("\033[?25h"); /* Show cursor */
-
- /* Return the label name so localboot and ipappend work */
- return cmdline;
-}
-
-int main(int argc, char *argv[])
-{
- const char *cmdline;
- struct menu *m;
- int rows, cols;
- int i;
-
- (void)argc;
-
- parse_configs(argv + 1);
-
- /*
- * We don't start the console until we have parsed the configuration
- * file, since the configuration file might impact the console
- * configuration, e.g. MENU RESOLUTION.
- */
- start_console();
- if (getscreensize(1, &rows, &cols)) {
- /* Unknown screen size? */
- rows = 24;
- cols = 80;
- }
-
- /* 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);
- }
-
- cm = start_menu;
-
- if (!cm->nentries) {
- fputs("Initial menu has no LABEL entries!\n", stdout);
- return 1; /* Error! */
- }
-
- for (;;) {
- local_cursor_enable(true);
- cmdline = run_menu();
-
- if (clearmenu)
- clear_screen();
-
- local_cursor_enable(false);
- 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 */
- }
- }
-}