xref: /minix3/sys/arch/i386/stand/lib/menuutils.c (revision 9733fcdb434080d4d3357d784d6b3cdeac9f5980)
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