158a2b000SEvgeniy Ivanov /* $NetBSD: menuutils.c,v 1.3 2008/12/14 18:46:33 christos Exp $ */ 258a2b000SEvgeniy Ivanov 358a2b000SEvgeniy Ivanov /* 458a2b000SEvgeniy Ivanov * Copyright (c) 1996, 1997 558a2b000SEvgeniy Ivanov * Matthias Drochner. All rights reserved. 658a2b000SEvgeniy Ivanov * Copyright (c) 1996, 1997 758a2b000SEvgeniy Ivanov * Perry E. Metzger. All rights reserved. 858a2b000SEvgeniy Ivanov * Copyright (c) 1997 958a2b000SEvgeniy Ivanov * Jason R. Thorpe. All rights reserved 1058a2b000SEvgeniy Ivanov * 1158a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 1258a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 1358a2b000SEvgeniy Ivanov * are met: 1458a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 1558a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 1658a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 1758a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 1858a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 1958a2b000SEvgeniy Ivanov * 3. All advertising materials mentioning features or use of this software 2058a2b000SEvgeniy Ivanov * must display the following acknowledgements: 2158a2b000SEvgeniy Ivanov * This product includes software developed for the NetBSD Project 2258a2b000SEvgeniy Ivanov * by Matthias Drochner. 2358a2b000SEvgeniy Ivanov * This product includes software developed for the NetBSD Project 2458a2b000SEvgeniy Ivanov * by Perry E. Metzger. 2558a2b000SEvgeniy Ivanov * 4. The names of the authors may not be used to endorse or promote products 2658a2b000SEvgeniy Ivanov * derived from this software without specific prior written permission. 2758a2b000SEvgeniy Ivanov * 2858a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2958a2b000SEvgeniy Ivanov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 3058a2b000SEvgeniy Ivanov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 3158a2b000SEvgeniy Ivanov * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 3258a2b000SEvgeniy Ivanov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3358a2b000SEvgeniy Ivanov * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3458a2b000SEvgeniy Ivanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3558a2b000SEvgeniy Ivanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3658a2b000SEvgeniy Ivanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3758a2b000SEvgeniy Ivanov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3858a2b000SEvgeniy Ivanov */ 3958a2b000SEvgeniy Ivanov 4058a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h> 4158a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h> 4258a2b000SEvgeniy Ivanov 4358a2b000SEvgeniy Ivanov #include "libi386.h" 4458a2b000SEvgeniy Ivanov 4558a2b000SEvgeniy Ivanov void 4658a2b000SEvgeniy Ivanov docommand(char *arg) 4758a2b000SEvgeniy Ivanov { 4858a2b000SEvgeniy Ivanov char *options; 4958a2b000SEvgeniy Ivanov int i; 5058a2b000SEvgeniy Ivanov 5158a2b000SEvgeniy Ivanov options = gettrailer(arg); 5258a2b000SEvgeniy Ivanov 5358a2b000SEvgeniy Ivanov for (i = 0; commands[i].c_name != NULL; i++) { 5458a2b000SEvgeniy Ivanov if (strcmp(arg, commands[i].c_name) == 0) { 5558a2b000SEvgeniy Ivanov (*commands[i].c_fn)(options); 5658a2b000SEvgeniy Ivanov return; 5758a2b000SEvgeniy Ivanov } 5858a2b000SEvgeniy Ivanov } 5958a2b000SEvgeniy Ivanov 6058a2b000SEvgeniy Ivanov printf("unknown command\n"); 6158a2b000SEvgeniy Ivanov command_help(NULL); 6258a2b000SEvgeniy Ivanov } 6358a2b000SEvgeniy Ivanov 6458a2b000SEvgeniy Ivanov void 65*9733fcdbSDavid van Moolenbroek prompt(int allowreturn) 6658a2b000SEvgeniy Ivanov { 6758a2b000SEvgeniy Ivanov char input[80]; 6858a2b000SEvgeniy Ivanov 6958a2b000SEvgeniy Ivanov for (;;) { 7058a2b000SEvgeniy Ivanov char *c = input; 7158a2b000SEvgeniy Ivanov 7258a2b000SEvgeniy Ivanov printf("> "); 73*9733fcdbSDavid van Moolenbroek editline(input, sizeof(input), NULL); 7458a2b000SEvgeniy Ivanov 7558a2b000SEvgeniy Ivanov /* 7658a2b000SEvgeniy Ivanov * Skip leading whitespace. 7758a2b000SEvgeniy Ivanov */ 7858a2b000SEvgeniy Ivanov while (*c == ' ') 7958a2b000SEvgeniy Ivanov c++; 80*9733fcdbSDavid van Moolenbroek if (allowreturn && !strcmp(c, "menu")) 81*9733fcdbSDavid van Moolenbroek break; 8258a2b000SEvgeniy Ivanov if (*c) 8358a2b000SEvgeniy Ivanov docommand(c); 8458a2b000SEvgeniy Ivanov } 8558a2b000SEvgeniy Ivanov } 86*9733fcdbSDavid van Moolenbroek 87*9733fcdbSDavid van Moolenbroek void 88*9733fcdbSDavid van Moolenbroek bootmenu(void) 89*9733fcdbSDavid van Moolenbroek { 90*9733fcdbSDavid van Moolenbroek prompt(0); 91*9733fcdbSDavid van Moolenbroek } 92*9733fcdbSDavid van Moolenbroek 93*9733fcdbSDavid van Moolenbroek /* Derived from libsa gets(). */ 94*9733fcdbSDavid van Moolenbroek void 95*9733fcdbSDavid van Moolenbroek editline(char *buf, size_t size, char *input) 96*9733fcdbSDavid van Moolenbroek { 97*9733fcdbSDavid van Moolenbroek int c, i, pos, len = 0; 98*9733fcdbSDavid van Moolenbroek 99*9733fcdbSDavid van Moolenbroek /* If an initial input has been given, copy and print this first. */ 100*9733fcdbSDavid van Moolenbroek if (input != NULL) { 101*9733fcdbSDavid van Moolenbroek while (*input && len < size - 1) 102*9733fcdbSDavid van Moolenbroek putchar(buf[len++] = *input++); 103*9733fcdbSDavid van Moolenbroek } 104*9733fcdbSDavid van Moolenbroek pos = len; 105*9733fcdbSDavid van Moolenbroek 106*9733fcdbSDavid van Moolenbroek for (;;) { 107*9733fcdbSDavid van Moolenbroek c = getchar_ex(); 108*9733fcdbSDavid van Moolenbroek switch (c & 0177) { 109*9733fcdbSDavid van Moolenbroek case '\0': 110*9733fcdbSDavid van Moolenbroek switch (c) { 111*9733fcdbSDavid van Moolenbroek case 0x4b00: /* Left arrow: move cursor to left. */ 112*9733fcdbSDavid van Moolenbroek if (pos > 0) { 113*9733fcdbSDavid van Moolenbroek putchar('\b'); 114*9733fcdbSDavid van Moolenbroek pos--; 115*9733fcdbSDavid van Moolenbroek } 116*9733fcdbSDavid van Moolenbroek break; 117*9733fcdbSDavid van Moolenbroek case 0x4d00: /* Right arrow: move cursor to right. */ 118*9733fcdbSDavid van Moolenbroek if (pos < len) putchar(buf[pos++]); 119*9733fcdbSDavid van Moolenbroek break; 120*9733fcdbSDavid van Moolenbroek } 121*9733fcdbSDavid van Moolenbroek break; 122*9733fcdbSDavid van Moolenbroek case 'b' & 037: /* Ctrl+B: move cursor to left. */ 123*9733fcdbSDavid van Moolenbroek if (pos > 0) { 124*9733fcdbSDavid van Moolenbroek putchar('\b'); 125*9733fcdbSDavid van Moolenbroek pos--; 126*9733fcdbSDavid van Moolenbroek } 127*9733fcdbSDavid van Moolenbroek break; 128*9733fcdbSDavid van Moolenbroek case 'f' & 037: /* Ctrl+F: move cursor to right. */ 129*9733fcdbSDavid van Moolenbroek if (pos < len) putchar(buf[pos++]); 130*9733fcdbSDavid van Moolenbroek break; 131*9733fcdbSDavid van Moolenbroek case 'a' & 037: /* Ctrl+A: move cursor to start of line. */ 132*9733fcdbSDavid van Moolenbroek for ( ; pos > 0; pos--) putchar('\b'); 133*9733fcdbSDavid van Moolenbroek break; 134*9733fcdbSDavid van Moolenbroek case 'e' & 037: /* Ctrl+E: move cursor to end of line. */ 135*9733fcdbSDavid van Moolenbroek for ( ; pos < len; pos++) putchar(buf[pos]); 136*9733fcdbSDavid van Moolenbroek break; 137*9733fcdbSDavid van Moolenbroek case '\n': /* Enter: return line. */ 138*9733fcdbSDavid van Moolenbroek case '\r': 139*9733fcdbSDavid van Moolenbroek for ( ; pos < len; pos++) putchar(buf[pos]); 140*9733fcdbSDavid van Moolenbroek buf[len] = '\0'; 141*9733fcdbSDavid van Moolenbroek putchar('\n'); 142*9733fcdbSDavid van Moolenbroek return; 143*9733fcdbSDavid van Moolenbroek #if HASH_ERASE 144*9733fcdbSDavid van Moolenbroek case '#': 145*9733fcdbSDavid van Moolenbroek #endif 146*9733fcdbSDavid van Moolenbroek case '\b': /* Backspace: erase character before cursor. */ 147*9733fcdbSDavid van Moolenbroek case '\177': 148*9733fcdbSDavid van Moolenbroek if (pos > 0) { 149*9733fcdbSDavid van Moolenbroek pos--; 150*9733fcdbSDavid van Moolenbroek len--; 151*9733fcdbSDavid van Moolenbroek putchar('\b'); 152*9733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) 153*9733fcdbSDavid van Moolenbroek putchar(buf[i] = buf[i + 1]); 154*9733fcdbSDavid van Moolenbroek putchar(' '); 155*9733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) putchar('\b'); 156*9733fcdbSDavid van Moolenbroek putchar('\b'); 157*9733fcdbSDavid van Moolenbroek } 158*9733fcdbSDavid van Moolenbroek break; 159*9733fcdbSDavid van Moolenbroek case 'r' & 037: /* Ctrl+R: reprint line. */ 160*9733fcdbSDavid van Moolenbroek putchar('\n'); 161*9733fcdbSDavid van Moolenbroek for (i = 0; i < len; i++) putchar(buf[i]); 162*9733fcdbSDavid van Moolenbroek for (i = len; i > pos; i--) putchar('\b'); 163*9733fcdbSDavid van Moolenbroek break; 164*9733fcdbSDavid van Moolenbroek #if AT_ERASE 165*9733fcdbSDavid van Moolenbroek case '@': 166*9733fcdbSDavid van Moolenbroek #endif 167*9733fcdbSDavid van Moolenbroek case 'u' & 037: /* Ctrl+U: clear entire line. */ 168*9733fcdbSDavid van Moolenbroek case 'w' & 037: 169*9733fcdbSDavid van Moolenbroek for ( ; pos > 0; pos--) putchar('\b'); 170*9733fcdbSDavid van Moolenbroek for ( ; pos < len; pos++) putchar(' '); 171*9733fcdbSDavid van Moolenbroek for ( ; pos > 0; pos--) putchar('\b'); 172*9733fcdbSDavid van Moolenbroek len = 0; 173*9733fcdbSDavid van Moolenbroek break; 174*9733fcdbSDavid van Moolenbroek case '\a': /* Ctrl+G: sound bell but do not store character. */ 175*9733fcdbSDavid van Moolenbroek putchar(c); 176*9733fcdbSDavid van Moolenbroek break; 177*9733fcdbSDavid van Moolenbroek case '\t': /* Tab: convert to single space. */ 178*9733fcdbSDavid van Moolenbroek c = ' '; 179*9733fcdbSDavid van Moolenbroek /*FALLTHROUGH*/ 180*9733fcdbSDavid van Moolenbroek default: /* Insert character at cursor position. */ 181*9733fcdbSDavid van Moolenbroek if (len < size - 1) { 182*9733fcdbSDavid van Moolenbroek for (i = len; i > pos; i--) 183*9733fcdbSDavid van Moolenbroek buf[i] = buf[i - 1]; 184*9733fcdbSDavid van Moolenbroek buf[pos] = c; 185*9733fcdbSDavid van Moolenbroek pos++; 186*9733fcdbSDavid van Moolenbroek len++; 187*9733fcdbSDavid van Moolenbroek putchar(c); 188*9733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) putchar(buf[i]); 189*9733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) putchar('\b'); 190*9733fcdbSDavid van Moolenbroek } else { 191*9733fcdbSDavid van Moolenbroek putchar('\a'); 192*9733fcdbSDavid van Moolenbroek } 193*9733fcdbSDavid van Moolenbroek break; 194*9733fcdbSDavid van Moolenbroek } 195*9733fcdbSDavid van Moolenbroek } 196*9733fcdbSDavid van Moolenbroek /*NOTREACHED*/ 197*9733fcdbSDavid van Moolenbroek } 198