176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- * 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2009-2014 Intel Corporation; author: H. Peter Anvin 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or modify 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * it under the terms of the GNU General Public License as published by 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Boston MA 02110-1301, USA; either version 2 of the License, or 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (at your option) any later version; incorporated herein by reference. 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */ 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * menumain.c 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Simple menu system which displays a list and allows the user to select 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * a command line and/or edit it. 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <ctype.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <consoles.h> 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <getkey.h> 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <minmax.h> 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <setjmp.h> 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <limits.h> 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <com32.h> 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <core.h> 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/adv.h> 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/boot.h> 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "menu.h" 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The symbol "cm" always refers to the current menu across this file... */ 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct menu *cm; 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst struct menu_parameter mparm[NPARAMS] = { 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_WIDTH] = {"width", 0}, 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_MARGIN] = {"margin", 10}, 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_PASSWD_MARGIN] = {"passwordmargin", 3}, 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_MENU_ROWS] = {"rows", 12}, 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_TABMSG_ROW] = {"tabmsgrow", 18}, 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_CMDLINE_ROW] = {"cmdlinerow", 18}, 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_END_ROW] = {"endrow", -1}, 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_PASSWD_ROW] = {"passwordrow", 11}, 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_TIMEOUT_ROW] = {"timeoutrow", 20}, 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_HELPMSG_ROW] = {"helpmsgrow", 22}, 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_HELPMSGEND_ROW] = {"helpmsgendrow", -1}, 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_HSHIFT] = {"hshift", 0}, 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_VSHIFT] = {"vshift", 0}, 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman [P_HIDDEN_ROW] = {"hiddenrow", -2}, 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* These macros assume "cm" is a pointer to the current menu */ 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define WIDTH (cm->mparm[P_WIDTH]) 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MARGIN (cm->mparm[P_MARGIN]) 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PASSWD_MARGIN (cm->mparm[P_PASSWD_MARGIN]) 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MENU_ROWS (cm->mparm[P_MENU_ROWS]) 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TABMSG_ROW (cm->mparm[P_TABMSG_ROW]+VSHIFT) 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define CMDLINE_ROW (cm->mparm[P_CMDLINE_ROW]+VSHIFT) 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define END_ROW (cm->mparm[P_END_ROW]) 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PASSWD_ROW (cm->mparm[P_PASSWD_ROW]+VSHIFT) 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define TIMEOUT_ROW (cm->mparm[P_TIMEOUT_ROW]+VSHIFT) 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define HELPMSG_ROW (cm->mparm[P_HELPMSG_ROW]+VSHIFT) 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define HELPMSGEND_ROW (cm->mparm[P_HELPMSGEND_ROW]) 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define HSHIFT (cm->mparm[P_HSHIFT]) 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define VSHIFT (cm->mparm[P_VSHIFT]) 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define HIDDEN_ROW (cm->mparm[P_HIDDEN_ROW]) 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic char *pad_line(const char *text, int align, int width) 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static char buffer[MAX_CMDLINE_LEN]; 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int n, p; 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (width >= (int)sizeof buffer) 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return NULL; /* Can't do it */ 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n = strlen(text); 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (n >= width) 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n = width; 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(buffer, ' ', width); 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman buffer[width] = 0; 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p = ((width - n) * align) >> 1; 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(buffer + p, text, n); 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return buffer; 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Display an entry, with possible hotkey highlight. Assumes 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman that the current attribute is the non-hotkey one, and will 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman guarantee that as an exit condition as well. */ 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmandisplay_entry(const struct menu_entry *entry, const char *attrib, 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *hotattrib, int width) 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *p = entry->displayname; 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char marker; 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!p) 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p = ""; 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (entry->action) { 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_SUBMENU: 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman marker = '>'; 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_EXIT: 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman marker = '<'; 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman marker = 0; 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (marker) 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman width -= 2; 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (width) { 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (*p) { 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (*p == '^') { 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p++; 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (*p && ((unsigned char)*p & ~0x20) == entry->hotkey) { 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs(hotattrib, stdout); 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(*p++); 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs(attrib, stdout); 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman width--; 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(*p++); 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman width--; 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(' '); 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman width--; 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (marker) { 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(' '); 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(marker); 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void draw_row(int y, int sel, int top, int sbtop, int sbbot) 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i = (y - 4 - VSHIFT) + top; 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int dis = (i < cm->nentries) && is_disabled(cm->menu_entries[i]); 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;%dH\1#1\016x\017%s ", 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman y, MARGIN + 1 + HSHIFT, 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3"); 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (i >= cm->nentries) { 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs(pad_line("", 0, WIDTH - 2 * MARGIN - 4), stdout); 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman display_entry(cm->menu_entries[i], 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3", 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4", 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman WIDTH - 2 * MARGIN - 4); 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->nentries <= MENU_ROWS) { 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf(" \1#1\016x\017"); 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (sbtop > 0) { 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (y >= sbtop && y <= sbbot) 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf(" \1#7\016a\017"); 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf(" \1#1\016x\017"); 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(' '); /* Don't modify the scrollbar */ 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic jmp_buf timeout_jump; 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint mygetkey(clock_t timeout) 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clock_t t0, t; 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clock_t tto, to; 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int key; 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!totaltimeout) 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return get_key(stdin, timeout); 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (;;) { 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tto = min(totaltimeout, INT_MAX); 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to = timeout ? min(tto, timeout) : tto; 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman t0 = times(NULL); 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = get_key(stdin, to); 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman t = times(NULL) - t0; 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (totaltimeout <= t) 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman longjmp(timeout_jump, 1); 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman totaltimeout -= t; 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key != KEY_NONE) 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return key; 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (timeout) { 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (timeout <= t) 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return KEY_NONE; 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman timeout -= t; 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int ask_passwd(const char *menu_entry) 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char user_passwd[WIDTH], *p; 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int done; 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int key; 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int x; 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rv; 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;%dH\2#11\016l", PASSWD_ROW, PASSWD_MARGIN + 1); 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++) 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar('q'); 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("k\033[%d;%dHx", PASSWD_ROW + 1, PASSWD_MARGIN + 1); 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++) 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(' '); 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("x\033[%d;%dHm", PASSWD_ROW + 2, PASSWD_MARGIN + 1); 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++) 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar('q'); 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("j\017\033[%d;%dH\2#12 %s \033[%d;%dH\2#13", 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PASSWD_ROW, (WIDTH - (strlen(cm->messages[MSG_PASSPROMPT]) + 2)) / 2, 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm->messages[MSG_PASSPROMPT], PASSWD_ROW + 1, PASSWD_MARGIN + 3); 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drain_keyboard(); 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Actually allow user to type a password, then compare to the SHA1 */ 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 0; 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p = user_passwd; 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!done) { 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = mygetkey(0); 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (key) { 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_ENTER: 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('J'): 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 1; 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_ESC: 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('C'): 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p = user_passwd; /* No password entered */ 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 1; 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_BACKSPACE: 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_DEL: 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_DELETE: 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (p > user_passwd) { 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\b \b"); 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p--; 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('U'): 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (p > user_passwd) { 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\b \b"); 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman p--; 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key >= ' ' && key <= 0xFF && 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (p - user_passwd) < WIDTH - 2 * PASSWD_MARGIN - 5) { 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *p++ = key; 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar('*'); 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (p == user_passwd) 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; /* No password entered */ 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *p = '\0'; 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = (cm->menu_master_passwd && 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman passwd_compare(cm->menu_master_passwd, user_passwd)) 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman || (menu_entry && passwd_compare(menu_entry, user_passwd)); 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clean up */ 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(user_passwd, 0, WIDTH); 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drain_keyboard(); 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rv; 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void draw_menu(int sel, int top, int edit_line) 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int x, y; 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int sbtop = 0, sbbot = 0; 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *tabmsg; 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int tabmsg_len; 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->nentries > MENU_ROWS) { 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int sblen = max(MENU_ROWS * MENU_ROWS / cm->nentries, 1); 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sbtop = (MENU_ROWS - sblen + 1) * top / (cm->nentries - MENU_ROWS + 1); 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sbbot = sbtop + sblen - 1; 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sbtop += 4; 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sbbot += 4; /* Starting row of scrollbar */ 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;%dH\1#1\016l", VSHIFT + 1, HSHIFT + MARGIN + 1); 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar('q'); 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("k\033[%d;%dH\1#1x\017\1#2 %s \1#1\016x", 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman VSHIFT + 2, 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman HSHIFT + MARGIN + 1, pad_line(cm->title, 1, WIDTH - 2 * MARGIN - 4)); 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;%dH\1#1t", VSHIFT + 3, HSHIFT + MARGIN + 1); 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar('q'); 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs("u\017", stdout); 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (y = 4 + VSHIFT; y < 4 + VSHIFT + MENU_ROWS; y++) 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(y, sel, top, sbtop, sbbot); 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;%dH\1#1\016m", y, HSHIFT + MARGIN + 1); 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar('q'); 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs("j\017", stdout); 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (edit_line && cm->allowedit && !cm->menu_master_passwd) 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tabmsg = cm->messages[MSG_TAB]; 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tabmsg = cm->messages[MSG_NOTAB]; 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tabmsg_len = strlen(tabmsg); 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\1#8\033[%d;%dH%s", 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman TABMSG_ROW, 1 + HSHIFT + ((WIDTH - tabmsg_len) >> 1), tabmsg); 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\1#0\033[%d;1H", END_ROW); 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void clear_screen(void) 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout); 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void display_help(const char *text) 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int row; 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *p; 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!text) { 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman text = ""; 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\1#0\033[%d;1H", HELPMSG_ROW); 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\2#16\033[%d;1H", HELPMSG_ROW); 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (p = text, row = HELPMSG_ROW; *p && row <= HELPMSGEND_ROW; p++) { 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (*p) { 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '\r': 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '\f': 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '\v': 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '\033': 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '\n': 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[K\033[%d;1H", ++row); 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(*p); 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs("\033[K", stdout); 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (row <= HELPMSGEND_ROW) { 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[K\033[%d;1H", ++row); 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void show_fkey(int key) 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int fkey; 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (1) { 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (key) { 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F1: 39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 0; 39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F2: 39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 1; 39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F3: 40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 2; 40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F4: 40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 3; 40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F5: 40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 4; 40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F6: 40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 5; 41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F7: 41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 6; 41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F8: 41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 7; 41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F9: 41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 8; 41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F10: 42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 9; 42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F11: 42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 10; 42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F12: 42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = 11; 42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fkey = -1; 43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (fkey == -1) 43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->fkeyhelp[fkey].textname) 43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = show_message_file(cm->fkeyhelp[fkey].textname, 43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm->fkeyhelp[fkey].background); 44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *edit_cmdline(const char *input, int top) 44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static char cmdline[MAX_CMDLINE_LEN]; 44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int key, len, prev_len, cursor; 44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int redraw = 1; /* We enter with the menu already drawn */ 45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman strlcpy(cmdline, input, MAX_CMDLINE_LEN); 45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline[MAX_CMDLINE_LEN - 1] = '\0'; 45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = cursor = strlen(cmdline); 45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_len = 0; 45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (;;) { 45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (redraw > 1) { 45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clear and redraw whole screen */ 46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Enable ASCII on G0 and DEC VT on G1; do it in this order 46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to avoid confusing the Linux console */ 46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear_screen(); 46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_menu(-1, top, 1); 46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_len = 0; 46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (redraw > 0) { 46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Redraw the command line */ 46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[?25l\033[%d;1H\1#9> \2#10%s", 47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len))); 47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\2#10\033[%d;3H%s\033[?25h", 47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman CMDLINE_ROW, pad_line(cmdline, 0, cursor)); 47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_len = len; 47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 0; 47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = mygetkey(0); 47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (key) { 48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('L'): 48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 2; 48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_ENTER: 48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('J'): 48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return cmdline; 48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_ESC: 48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('C'): 49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return NULL; 49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_BACKSPACE: 49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_DEL: 49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor) { 49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memmove(cmdline + cursor - 1, cmdline + cursor, 49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len - cursor + 1); 49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len--; 49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor--; 49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('D'): 50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_DELETE: 50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor < len) { 50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memmove(cmdline + cursor, cmdline + cursor + 1, len - cursor); 50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len--; 50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('U'): 51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (len) { 51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = cursor = 0; 51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline[len] = '\0'; 51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('W'): 52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor) { 52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int prevcursor = cursor; 52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (cursor && my_isspace(cmdline[cursor - 1])) 52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor--; 52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (cursor && !my_isspace(cmdline[cursor - 1])) 52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor--; 52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memmove(cmdline + cursor, cmdline + prevcursor, 53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len - prevcursor + 1); 53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len -= (prevcursor - cursor); 53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_LEFT: 53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('B'): 53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor) { 54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor--; 54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_RIGHT: 54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('F'): 54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor < len) { 54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(cmdline[cursor++]); 54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('K'): 55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor < len) { 55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline[len = cursor] = '\0'; 55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_HOME: 56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('A'): 56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor) { 56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor = 0; 56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_END: 56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('E'): 56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor != len) { 57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor = len; 57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F1: 57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F2: 57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F3: 57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F4: 57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F5: 58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F6: 58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F7: 58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F8: 58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F9: 58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F10: 58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F11: 58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F12: 58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman show_fkey(key); 58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN - 1) { 59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cursor == len) { 59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline[len] = key; 59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline[++len] = '\0'; 59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cursor++; 59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman putchar(key); 59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_len++; 59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memmove(cmdline + cursor + 1, cmdline + cursor, 60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len - cursor + 1); 60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline[cursor++] = key; 60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len++; 60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman redraw = 1; 60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void print_timeout_message(int tol, int row, const char *msg) 61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static int last_msg_len = 0; 61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char buf[256]; 61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int nc = 0, nnc, padc; 61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *tp = msg; 61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char tc; 61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char *tq = buf; 62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while ((size_t) (tq - buf) < (sizeof buf - 16) && (tc = *tp)) { 62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tp++; 62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (tc == '#') { 62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nnc = sprintf(tq, "\2#15%d\2#14", tol); 62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tq += nnc; 62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nc += nnc - 8; /* 8 formatting characters */ 62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (tc == '{') { 62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Deal with {singular[,dual],plural} constructs */ 62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct { 63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *s, *e; 63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } tx[3]; 63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *tpp; 63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int n = 0; 63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(tx, 0, sizeof tx); 63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx[0].s = tp; 63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (*tp && *tp != '}') { 64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (*tp == ',' && n < 2) { 64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx[n].e = tp; 64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n++; 64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx[n].s = tp + 1; 64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tp++; 64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx[n].e = tp; 64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (*tp) 65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tp++; /* Skip final bracket */ 65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!tx[1].s) 65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx[1] = tx[0]; 65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!tx[2].s) 65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx[2] = tx[1]; 65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Now [0] is singular, [1] is dual, and [2] is plural, 65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman even if the user only specified some of them. */ 65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (tol) { 66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case 1: 66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n = 0; 66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case 2: 66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n = 1; 66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n = 2; 66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (tpp = tx[n].s; tpp < tx[n].e; tpp++) { 67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((size_t) (tq - buf) < (sizeof buf)) { 67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *tq++ = *tpp; 67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nc++; 67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *tq++ = tc; 68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nc++; 68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *tq = '\0'; 68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (nc >= last_msg_len) { 68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman padc = 0; 68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman padc = (last_msg_len - nc + 1) >> 1; 68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;%dH\2#14%*s%s%*s", row, 69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman HSHIFT + 1 + ((WIDTH - nc) >> 1) - padc, 69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman padc, "", buf, padc, ""); 69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman last_msg_len = nc; 69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Set the background screen, etc. */ 69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void prepare_screen_for_menu(void) 70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman console_color_table = cm->color_table; 70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman console_color_table_size = menu_color_table_size; 70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman set_background(cm->menu_background); 70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *do_hidden_menu(void) 70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int key; 70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int timeout_left, this_timeout; 71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear_screen(); 71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!setjmp(timeout_jump)) { 71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman timeout_left = cm->timeout; 71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!cm->timeout || timeout_left) { 71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int tol = timeout_left / CLK_TCK; 71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]); 72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman this_timeout = min(timeout_left, CLK_TCK); 72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = mygetkey(this_timeout); 72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key != KEY_NONE) { 72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clear the message from the screen */ 72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman print_timeout_message(0, HIDDEN_ROW, ""); 72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return hide_key[key]; /* NULL if no MENU HIDEKEY in effect */ 72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman timeout_left -= this_timeout; 73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clear the message from the screen */ 73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman print_timeout_message(0, HIDDEN_ROW, ""); 73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->ontimeout) 73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return cm->ontimeout; 73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */ 74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *run_menu(void) 74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int key; 74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int done = 0; 74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman volatile int entry = cm->curentry; 74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int prev_entry = -1; 74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman volatile int top = cm->curtop; 75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int prev_top = -1; 75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int clear = 1, to_clear; 75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *cmdline = NULL; 75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman volatile clock_t key_timeout, timeout_left, this_timeout; 75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const struct menu_entry *me; 75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bool hotkey = false; 75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Note: for both key_timeout and timeout == 0 means no limit */ 75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman timeout_left = key_timeout = cm->timeout; 75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* If we're in shiftkey mode, exit immediately unless a shift key 76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman is pressed */ 76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (shiftkey && !shift_is_held()) { 76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return cm->menu_entries[cm->defentry]->cmdline; 76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman shiftkey = 0; 76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Do this before hiddenmenu handling, so we show the background */ 76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prepare_screen_for_menu(); 77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Handle hiddenmenu */ 77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (hiddenmenu) { 77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline = do_hidden_menu(); 77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cmdline) 77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return cmdline; 77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Otherwise display the menu now; the timeout has already been 77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cancelled, since the user pressed a key. */ 77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hiddenmenu = 0; 78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_timeout = 0; 78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Handle both local and global timeout */ 78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (setjmp(timeout_jump)) { 78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = cm->defentry; 78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (top < 0 || top < entry - MENU_ROWS + 1) 78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = max(0, entry - MENU_ROWS + 1); 78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (top > entry || top > max(0, cm->nentries - MENU_ROWS)) 79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = min(entry, max(0, cm->nentries - MENU_ROWS)); 79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_menu(cm->ontimeout ? -1 : entry, top, 1); 79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline = 79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline; 79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 1; 79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!done) { 79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry <= 0) { 80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = 0; 80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry < cm->nentries && is_disabled(cm->menu_entries[entry])) 80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry++; 80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry >= cm->nentries - 1) { 80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = cm->nentries - 1; 80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry > 0 && is_disabled(cm->menu_entries[entry])) 80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry--; 80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman me = cm->menu_entries[entry]; 81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (top < 0 || top < entry - MENU_ROWS + 1) 81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = max(0, entry - MENU_ROWS + 1); 81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (top > entry || top > max(0, cm->nentries - MENU_ROWS)) 81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = min(entry, max(0, cm->nentries - MENU_ROWS)); 81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Start with a clear screen */ 81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (clear) { 81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clear and redraw whole screen */ 82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Enable ASCII on G0 and DEC VT on G1; do it in this order 82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to avoid confusing the Linux console */ 82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (clear >= 2) 82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prepare_screen_for_menu(); 82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear_screen(); 82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 0; 82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_entry = prev_top = -1; 82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (top != prev_top) { 83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_menu(entry, top, 1); 83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman display_help(me->helptext); 83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (entry != prev_entry) { 83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(prev_entry - top + 4 + VSHIFT, entry, top, 0, 0); 83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0); 83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman display_help(me->helptext); 83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_entry = entry; 83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prev_top = top; 84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm->curentry = entry; 84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm->curtop = top; 84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Cursor movement cancels timeout */ 84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry != cm->defentry) 84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_timeout = 0; 84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key_timeout) { 84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int tol = timeout_left / CLK_TCK; 84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman print_timeout_message(tol, TIMEOUT_ROW, cm->messages[MSG_AUTOBOOT]); 85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to_clear = 1; 85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to_clear = 0; 85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (hotkey && me->immediate) { 85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* If the hotkey was flagged immediate, simulate pressing ENTER */ 85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = KEY_ENTER; 85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman this_timeout = min(min(key_timeout, timeout_left), 86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (clock_t) CLK_TCK); 86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = mygetkey(this_timeout); 86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key != KEY_NONE) { 86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman timeout_left = key_timeout; 86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (to_clear) 86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW); 86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hotkey = false; 87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (key) { 87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_NONE: /* Timeout */ 87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* This is somewhat hacky, but this at least lets the user 87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman know what's going on, and still deals with "phantom inputs" 87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman e.g. on serial ports. 87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Warning: a timeout will boot the default entry without any 87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman password! */ 88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key_timeout) { 88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (timeout_left <= this_timeout) 88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman longjmp(timeout_jump, 1); 88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman timeout_left -= this_timeout; 88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 88676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('L'): 88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; 89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 89176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 89276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_ENTER: 89376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('J'): 89476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_timeout = 0; /* Cancels timeout */ 89576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (me->passwd) { 89676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; 89776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = ask_passwd(me->passwd); 89876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 89976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 1; 90076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 90176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline = NULL; 90276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (done) { 90376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (me->action) { 90476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_CMD: 90576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline = me->cmdline; 90676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 90776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_SUBMENU: 90876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_GOTO: 90976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_EXIT: 91076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 0; 91176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 2; 91276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm = me->submenu; 91376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = cm->curentry; 91476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = cm->curtop; 91576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 91676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_QUIT: 91776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Quit menu system */ 91876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 1; 91976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; 92076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0); 92176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 92276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case MA_HELP: 92376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key = show_message_file(me->cmdline, me->background); 92476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* If the exit was an F-key, display that help screen */ 92576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman show_fkey(key); 92676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 0; 92776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; 92876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 92976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 93076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 0; 93176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 93276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 93376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 93476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (done && !me->passwd) { 93576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Only save a new default if we don't have a password... */ 93676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (me->save && me->label) { 93776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_setadv(ADV_MENUSAVE, strlen(me->label), me->label); 93876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_adv_write(); 93976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 94076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 94176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 94276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 94376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_UP: 94476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('P'): 94576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry > 0) { 94676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry--; 94776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry < top) 94876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top -= MENU_ROWS; 94976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!is_disabled(cm->menu_entries[entry])) 95076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 95176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 95276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 95376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 95476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_DOWN: 95576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('N'): 95676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry < cm->nentries - 1) { 95776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry++; 95876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry >= top + MENU_ROWS) 95976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top += MENU_ROWS; 96076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!is_disabled(cm->menu_entries[entry])) 96176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 96276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 96376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 96476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 96576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_PGUP: 96676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_LEFT: 96776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('B'): 96876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '<': 96976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry -= MENU_ROWS; 97076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top -= MENU_ROWS; 97176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry > 0 && is_disabled(cm->menu_entries[entry])) { 97276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry--; 97376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry < top) 97476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top -= MENU_ROWS; 97576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 97676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 97776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 97876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_PGDN: 97976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_RIGHT: 98076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('F'): 98176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '>': 98276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case ' ': 98376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry += MENU_ROWS; 98476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top += MENU_ROWS; 98576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry < cm->nentries - 1 98676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman && is_disabled(cm->menu_entries[entry])) { 98776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry++; 98876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry >= top + MENU_ROWS) 98976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top += MENU_ROWS; 99076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 99176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 99276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 99376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '-': 99476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry > 0) { 99576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry--; 99676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top--; 99776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!is_disabled(cm->menu_entries[entry])) 99876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 99976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 100076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 100176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 100276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case '+': 100376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (entry < cm->nentries - 1) { 100476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry++; 100576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top++; 100676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!is_disabled(cm->menu_entries[entry])) 100776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 100876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 100976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 101076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 101176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('A'): 101276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_HOME: 101376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = entry = 0; 101476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 101576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 101676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('E'): 101776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_END: 101876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = cm->nentries - 1; 101976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = max(0, cm->nentries - MENU_ROWS); 102076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 102176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 102276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F1: 102376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F2: 102476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F3: 102576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F4: 102676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F5: 102776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F6: 102876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F7: 102976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F8: 103076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F9: 103176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F10: 103276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F11: 103376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_F12: 103476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman show_fkey(key); 103576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; 103676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 103776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 103876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_TAB: 103976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->allowedit && me->action == MA_CMD) { 104076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ok = 1; 104176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 104276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_timeout = 0; /* Cancels timeout */ 104376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0); 104476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 104576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->menu_master_passwd) { 104676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ok = ask_passwd(NULL); 104776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear_screen(); 104876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_menu(-1, top, 0); 104976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 105076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Erase [Tab] message and help text */ 105176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[%d;1H\1#0\033[K", TABMSG_ROW); 105276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman display_help(NULL); 105376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 105476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 105576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ok) { 105676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline = edit_cmdline(me->cmdline, top); 105776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = !!cmdline; 105876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; /* In case we hit [Esc] and done is null */ 105976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 106076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0); 106176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 106276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 106376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 106476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_CTRL('C'): /* Ctrl-C */ 106576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case KEY_ESC: /* Esc */ 106676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->parent) { 106776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm = cm->parent; 106876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 2; 106976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = cm->curentry; 107076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman top = cm->curtop; 107176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (cm->allowedit) { 107276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = 1; 107376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear = 1; 107476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_timeout = 0; 107576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 107676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0); 107776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 107876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->menu_master_passwd) 107976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = ask_passwd(NULL); 108076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 108176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 108276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 108376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (key > 0 && key < 0xFF) { 108476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key &= ~0x20; /* Upper case */ 108576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->menu_hotkeys[key]) { 108676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_timeout = 0; 108776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = cm->menu_hotkeys[key]->entry; 108876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Should we commit at this point? */ 108976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hotkey = true; 109076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 109176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 109276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 109376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 109476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 109576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 109676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[?25h"); /* Show cursor */ 109776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 109876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Return the label name so localboot and ipappend work */ 109976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return cmdline; 110076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 110176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 110276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint main(int argc, char *argv[]) 110376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 110476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *cmdline; 110576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct menu *m; 110676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rows, cols; 110776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 110876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 110976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (void)argc; 111076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 111176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman parse_configs(argv + 1); 111276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 111376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 111476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * We don't start the console until we have parsed the configuration 111576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * file, since the configuration file might impact the console 111676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * configuration, e.g. MENU RESOLUTION. 111776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 111876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman start_console(); 111976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (getscreensize(1, &rows, &cols)) { 112076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Unknown screen size? */ 112176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rows = 24; 112276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cols = 80; 112376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 112476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 112576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Some postprocessing for all menus */ 112676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (m = menu_list; m; m = m->next) { 112776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!m->mparm[P_WIDTH]) 112876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman m->mparm[P_WIDTH] = cols; 112976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 113076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* If anyone has specified negative parameters, consider them 113176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman relative to the bottom row of the screen. */ 113276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < NPARAMS; i++) 113376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (m->mparm[i] < 0) 113476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman m->mparm[i] = max(m->mparm[i] + rows, 0); 113576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 113676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 113776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cm = start_menu; 113876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 113976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!cm->nentries) { 114076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fputs("Initial menu has no LABEL entries!\n", stdout); 114176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; /* Error! */ 114276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 114376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 114476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (;;) { 114576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman local_cursor_enable(true); 114676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cmdline = run_menu(); 114776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 114876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (clearmenu) 114976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman clear_screen(); 115076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 115176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman local_cursor_enable(false); 115276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\033[?25h\033[%d;1H\033[0m", END_ROW); 115376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 115476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cmdline) { 115576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t type = parse_image_type(cmdline); 115676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 115776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman execute(cmdline, type, false); 115876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cm->onerror) { 115976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman type = parse_image_type(cm->onerror); 116076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman execute(cm->onerror, type, true); 116176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 116276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 116376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; /* Exit */ 116476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 116576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 116676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 1167