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*84d9c625SLionel Sambuc #if !defined(__minix) 66*84d9c625SLionel Sambuc bootmenu(void) 67*84d9c625SLionel Sambuc #else 689733fcdbSDavid van Moolenbroek prompt(int allowreturn) 69*84d9c625SLionel Sambuc #endif /* !defined(__minix) */ 7058a2b000SEvgeniy Ivanov { 7158a2b000SEvgeniy Ivanov char input[80]; 7258a2b000SEvgeniy Ivanov 7358a2b000SEvgeniy Ivanov for (;;) { 7458a2b000SEvgeniy Ivanov char *c = input; 7558a2b000SEvgeniy Ivanov 76f14fb602SLionel Sambuc input[0] = '\0'; 7758a2b000SEvgeniy Ivanov printf("> "); 78*84d9c625SLionel Sambuc #if !defined(__minix) 79*84d9c625SLionel Sambuc gets(input); 80*84d9c625SLionel Sambuc #else 819733fcdbSDavid van Moolenbroek editline(input, sizeof(input), NULL); 82*84d9c625SLionel Sambuc #endif /* !defined(__minix) */ 8358a2b000SEvgeniy Ivanov 8458a2b000SEvgeniy Ivanov /* 8558a2b000SEvgeniy Ivanov * Skip leading whitespace. 8658a2b000SEvgeniy Ivanov */ 8758a2b000SEvgeniy Ivanov while (*c == ' ') 8858a2b000SEvgeniy Ivanov c++; 89*84d9c625SLionel Sambuc #if defined(__minix) 909733fcdbSDavid van Moolenbroek if (allowreturn && !strcmp(c, "menu")) 919733fcdbSDavid van Moolenbroek break; 92*84d9c625SLionel Sambuc #endif /* defined(__minix) */ 9358a2b000SEvgeniy Ivanov if (*c) 9458a2b000SEvgeniy Ivanov docommand(c); 9558a2b000SEvgeniy Ivanov } 9658a2b000SEvgeniy Ivanov } 979733fcdbSDavid van Moolenbroek 98*84d9c625SLionel Sambuc #if defined(__minix) 999733fcdbSDavid van Moolenbroek void 1009733fcdbSDavid van Moolenbroek bootmenu(void) 1019733fcdbSDavid van Moolenbroek { 1029733fcdbSDavid van Moolenbroek prompt(0); 1039733fcdbSDavid van Moolenbroek } 1049733fcdbSDavid van Moolenbroek 1059733fcdbSDavid van Moolenbroek /* Derived from libsa gets(). */ 1069733fcdbSDavid van Moolenbroek void 1079733fcdbSDavid van Moolenbroek editline(char *buf, size_t size, char *input) 1089733fcdbSDavid van Moolenbroek { 1099733fcdbSDavid van Moolenbroek int c, i, pos, len = 0; 1109733fcdbSDavid van Moolenbroek 1119733fcdbSDavid van Moolenbroek /* If an initial input has been given, copy and print this first. */ 1129733fcdbSDavid van Moolenbroek if (input != NULL) { 1139733fcdbSDavid van Moolenbroek while (*input && len < size - 1) 1149733fcdbSDavid van Moolenbroek putchar(buf[len++] = *input++); 1159733fcdbSDavid van Moolenbroek } 1169733fcdbSDavid van Moolenbroek pos = len; 1179733fcdbSDavid van Moolenbroek 1189733fcdbSDavid van Moolenbroek for (;;) { 1199733fcdbSDavid van Moolenbroek c = getchar_ex(); 1209733fcdbSDavid van Moolenbroek switch (c & 0177) { 1219733fcdbSDavid van Moolenbroek case '\0': 1229733fcdbSDavid van Moolenbroek switch (c) { 1239733fcdbSDavid van Moolenbroek case 0x4b00: /* Left arrow: move cursor to left. */ 1249733fcdbSDavid van Moolenbroek if (pos > 0) { 1259733fcdbSDavid van Moolenbroek putchar('\b'); 1269733fcdbSDavid van Moolenbroek pos--; 1279733fcdbSDavid van Moolenbroek } 1289733fcdbSDavid van Moolenbroek break; 1299733fcdbSDavid van Moolenbroek case 0x4d00: /* Right arrow: move cursor to right. */ 1309733fcdbSDavid van Moolenbroek if (pos < len) putchar(buf[pos++]); 1319733fcdbSDavid van Moolenbroek break; 1329733fcdbSDavid van Moolenbroek } 1339733fcdbSDavid van Moolenbroek break; 1349733fcdbSDavid van Moolenbroek case 'b' & 037: /* Ctrl+B: move cursor to left. */ 1359733fcdbSDavid van Moolenbroek if (pos > 0) { 1369733fcdbSDavid van Moolenbroek putchar('\b'); 1379733fcdbSDavid van Moolenbroek pos--; 1389733fcdbSDavid van Moolenbroek } 1399733fcdbSDavid van Moolenbroek break; 1409733fcdbSDavid van Moolenbroek case 'f' & 037: /* Ctrl+F: move cursor to right. */ 1419733fcdbSDavid van Moolenbroek if (pos < len) putchar(buf[pos++]); 1429733fcdbSDavid van Moolenbroek break; 1439733fcdbSDavid van Moolenbroek case 'a' & 037: /* Ctrl+A: move cursor to start of line. */ 1449733fcdbSDavid van Moolenbroek for ( ; pos > 0; pos--) putchar('\b'); 1459733fcdbSDavid van Moolenbroek break; 1469733fcdbSDavid van Moolenbroek case 'e' & 037: /* Ctrl+E: move cursor to end of line. */ 1479733fcdbSDavid van Moolenbroek for ( ; pos < len; pos++) putchar(buf[pos]); 1489733fcdbSDavid van Moolenbroek break; 1499733fcdbSDavid van Moolenbroek case '\n': /* Enter: return line. */ 1509733fcdbSDavid van Moolenbroek case '\r': 1519733fcdbSDavid van Moolenbroek for ( ; pos < len; pos++) putchar(buf[pos]); 1529733fcdbSDavid van Moolenbroek buf[len] = '\0'; 1539733fcdbSDavid van Moolenbroek putchar('\n'); 1549733fcdbSDavid van Moolenbroek return; 1559733fcdbSDavid van Moolenbroek #if HASH_ERASE 1569733fcdbSDavid van Moolenbroek case '#': 1579733fcdbSDavid van Moolenbroek #endif 1589733fcdbSDavid van Moolenbroek case '\b': /* Backspace: erase character before cursor. */ 1599733fcdbSDavid van Moolenbroek case '\177': 1609733fcdbSDavid van Moolenbroek if (pos > 0) { 1619733fcdbSDavid van Moolenbroek pos--; 1629733fcdbSDavid van Moolenbroek len--; 1639733fcdbSDavid van Moolenbroek putchar('\b'); 1649733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) 1659733fcdbSDavid van Moolenbroek putchar(buf[i] = buf[i + 1]); 1669733fcdbSDavid van Moolenbroek putchar(' '); 1679733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) putchar('\b'); 1689733fcdbSDavid van Moolenbroek putchar('\b'); 1699733fcdbSDavid van Moolenbroek } 1709733fcdbSDavid van Moolenbroek break; 1719733fcdbSDavid van Moolenbroek case 'r' & 037: /* Ctrl+R: reprint line. */ 1729733fcdbSDavid van Moolenbroek putchar('\n'); 1739733fcdbSDavid van Moolenbroek for (i = 0; i < len; i++) putchar(buf[i]); 1749733fcdbSDavid van Moolenbroek for (i = len; i > pos; i--) putchar('\b'); 1759733fcdbSDavid van Moolenbroek break; 1769733fcdbSDavid van Moolenbroek #if AT_ERASE 1779733fcdbSDavid van Moolenbroek case '@': 1789733fcdbSDavid van Moolenbroek #endif 1799733fcdbSDavid van Moolenbroek case 'u' & 037: /* Ctrl+U: clear entire line. */ 1809733fcdbSDavid van Moolenbroek case 'w' & 037: 1819733fcdbSDavid van Moolenbroek for ( ; pos > 0; pos--) putchar('\b'); 1829733fcdbSDavid van Moolenbroek for ( ; pos < len; pos++) putchar(' '); 1839733fcdbSDavid van Moolenbroek for ( ; pos > 0; pos--) putchar('\b'); 1849733fcdbSDavid van Moolenbroek len = 0; 1859733fcdbSDavid van Moolenbroek break; 1869733fcdbSDavid van Moolenbroek case '\a': /* Ctrl+G: sound bell but do not store character. */ 1879733fcdbSDavid van Moolenbroek putchar(c); 1889733fcdbSDavid van Moolenbroek break; 1899733fcdbSDavid van Moolenbroek case '\t': /* Tab: convert to single space. */ 1909733fcdbSDavid van Moolenbroek c = ' '; 1919733fcdbSDavid van Moolenbroek /*FALLTHROUGH*/ 1929733fcdbSDavid van Moolenbroek default: /* Insert character at cursor position. */ 1939733fcdbSDavid van Moolenbroek if (len < size - 1) { 1949733fcdbSDavid van Moolenbroek for (i = len; i > pos; i--) 1959733fcdbSDavid van Moolenbroek buf[i] = buf[i - 1]; 1969733fcdbSDavid van Moolenbroek buf[pos] = c; 1979733fcdbSDavid van Moolenbroek pos++; 1989733fcdbSDavid van Moolenbroek len++; 1999733fcdbSDavid van Moolenbroek putchar(c); 2009733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) putchar(buf[i]); 2019733fcdbSDavid van Moolenbroek for (i = pos; i < len; i++) putchar('\b'); 2029733fcdbSDavid van Moolenbroek } else { 2039733fcdbSDavid van Moolenbroek putchar('\a'); 2049733fcdbSDavid van Moolenbroek } 2059733fcdbSDavid van Moolenbroek break; 2069733fcdbSDavid van Moolenbroek } 2079733fcdbSDavid van Moolenbroek } 2089733fcdbSDavid van Moolenbroek /*NOTREACHED*/ 2099733fcdbSDavid van Moolenbroek } 210*84d9c625SLionel Sambuc #endif /* defined(__minix) */ 211