xref: /rk3399_rockchip-uboot/scripts/kconfig/lxdialog/inputbox.c (revision 5b8031ccb4ed6e84457d883198d77efc307085dc)
10a9064fbSMasahiro Yamada /*
20a9064fbSMasahiro Yamada  *  inputbox.c -- implements the input box
30a9064fbSMasahiro Yamada  *
40a9064fbSMasahiro Yamada  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
50a9064fbSMasahiro Yamada  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
60a9064fbSMasahiro Yamada  *
7*5b8031ccSTom Rini  * SPDX-License-Identifier:	GPL-2.0+
80a9064fbSMasahiro Yamada  */
90a9064fbSMasahiro Yamada 
100a9064fbSMasahiro Yamada #include "dialog.h"
110a9064fbSMasahiro Yamada 
120a9064fbSMasahiro Yamada char dialog_input_result[MAX_LEN + 1];
130a9064fbSMasahiro Yamada 
140a9064fbSMasahiro Yamada /*
150a9064fbSMasahiro Yamada  *  Print the termination buttons
160a9064fbSMasahiro Yamada  */
print_buttons(WINDOW * dialog,int height,int width,int selected)170a9064fbSMasahiro Yamada static void print_buttons(WINDOW * dialog, int height, int width, int selected)
180a9064fbSMasahiro Yamada {
190a9064fbSMasahiro Yamada 	int x = width / 2 - 11;
200a9064fbSMasahiro Yamada 	int y = height - 2;
210a9064fbSMasahiro Yamada 
220a9064fbSMasahiro Yamada 	print_button(dialog, gettext("  Ok  "), y, x, selected == 0);
230a9064fbSMasahiro Yamada 	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
240a9064fbSMasahiro Yamada 
250a9064fbSMasahiro Yamada 	wmove(dialog, y, x + 1 + 14 * selected);
260a9064fbSMasahiro Yamada 	wrefresh(dialog);
270a9064fbSMasahiro Yamada }
280a9064fbSMasahiro Yamada 
290a9064fbSMasahiro Yamada /*
300a9064fbSMasahiro Yamada  * Display a dialog box for inputing a string
310a9064fbSMasahiro Yamada  */
dialog_inputbox(const char * title,const char * prompt,int height,int width,const char * init)320a9064fbSMasahiro Yamada int dialog_inputbox(const char *title, const char *prompt, int height, int width,
330a9064fbSMasahiro Yamada 		    const char *init)
340a9064fbSMasahiro Yamada {
350a9064fbSMasahiro Yamada 	int i, x, y, box_y, box_x, box_width;
360a9064fbSMasahiro Yamada 	int input_x = 0, key = 0, button = -1;
370a9064fbSMasahiro Yamada 	int show_x, len, pos;
380a9064fbSMasahiro Yamada 	char *instr = dialog_input_result;
390a9064fbSMasahiro Yamada 	WINDOW *dialog;
400a9064fbSMasahiro Yamada 
410a9064fbSMasahiro Yamada 	if (!init)
420a9064fbSMasahiro Yamada 		instr[0] = '\0';
430a9064fbSMasahiro Yamada 	else
440a9064fbSMasahiro Yamada 		strcpy(instr, init);
450a9064fbSMasahiro Yamada 
460a9064fbSMasahiro Yamada do_resize:
470a9064fbSMasahiro Yamada 	if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
480a9064fbSMasahiro Yamada 		return -ERRDISPLAYTOOSMALL;
490a9064fbSMasahiro Yamada 	if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
500a9064fbSMasahiro Yamada 		return -ERRDISPLAYTOOSMALL;
510a9064fbSMasahiro Yamada 
520a9064fbSMasahiro Yamada 	/* center dialog box on screen */
530a9064fbSMasahiro Yamada 	x = (getmaxx(stdscr) - width) / 2;
540a9064fbSMasahiro Yamada 	y = (getmaxy(stdscr) - height) / 2;
550a9064fbSMasahiro Yamada 
560a9064fbSMasahiro Yamada 	draw_shadow(stdscr, y, x, height, width);
570a9064fbSMasahiro Yamada 
580a9064fbSMasahiro Yamada 	dialog = newwin(height, width, y, x);
590a9064fbSMasahiro Yamada 	keypad(dialog, TRUE);
600a9064fbSMasahiro Yamada 
610a9064fbSMasahiro Yamada 	draw_box(dialog, 0, 0, height, width,
620a9064fbSMasahiro Yamada 		 dlg.dialog.atr, dlg.border.atr);
630a9064fbSMasahiro Yamada 	wattrset(dialog, dlg.border.atr);
640a9064fbSMasahiro Yamada 	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
650a9064fbSMasahiro Yamada 	for (i = 0; i < width - 2; i++)
660a9064fbSMasahiro Yamada 		waddch(dialog, ACS_HLINE);
670a9064fbSMasahiro Yamada 	wattrset(dialog, dlg.dialog.atr);
680a9064fbSMasahiro Yamada 	waddch(dialog, ACS_RTEE);
690a9064fbSMasahiro Yamada 
700a9064fbSMasahiro Yamada 	print_title(dialog, title, width);
710a9064fbSMasahiro Yamada 
720a9064fbSMasahiro Yamada 	wattrset(dialog, dlg.dialog.atr);
730a9064fbSMasahiro Yamada 	print_autowrap(dialog, prompt, width - 2, 1, 3);
740a9064fbSMasahiro Yamada 
750a9064fbSMasahiro Yamada 	/* Draw the input field box */
760a9064fbSMasahiro Yamada 	box_width = width - 6;
770a9064fbSMasahiro Yamada 	getyx(dialog, y, x);
780a9064fbSMasahiro Yamada 	box_y = y + 2;
790a9064fbSMasahiro Yamada 	box_x = (width - box_width) / 2;
800a9064fbSMasahiro Yamada 	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
810a9064fbSMasahiro Yamada 		 dlg.dialog.atr, dlg.border.atr);
820a9064fbSMasahiro Yamada 
830a9064fbSMasahiro Yamada 	print_buttons(dialog, height, width, 0);
840a9064fbSMasahiro Yamada 
850a9064fbSMasahiro Yamada 	/* Set up the initial value */
860a9064fbSMasahiro Yamada 	wmove(dialog, box_y, box_x);
870a9064fbSMasahiro Yamada 	wattrset(dialog, dlg.inputbox.atr);
880a9064fbSMasahiro Yamada 
890a9064fbSMasahiro Yamada 	len = strlen(instr);
900a9064fbSMasahiro Yamada 	pos = len;
910a9064fbSMasahiro Yamada 
920a9064fbSMasahiro Yamada 	if (len >= box_width) {
930a9064fbSMasahiro Yamada 		show_x = len - box_width + 1;
940a9064fbSMasahiro Yamada 		input_x = box_width - 1;
950a9064fbSMasahiro Yamada 		for (i = 0; i < box_width - 1; i++)
960a9064fbSMasahiro Yamada 			waddch(dialog, instr[show_x + i]);
970a9064fbSMasahiro Yamada 	} else {
980a9064fbSMasahiro Yamada 		show_x = 0;
990a9064fbSMasahiro Yamada 		input_x = len;
1000a9064fbSMasahiro Yamada 		waddstr(dialog, instr);
1010a9064fbSMasahiro Yamada 	}
1020a9064fbSMasahiro Yamada 
1030a9064fbSMasahiro Yamada 	wmove(dialog, box_y, box_x + input_x);
1040a9064fbSMasahiro Yamada 
1050a9064fbSMasahiro Yamada 	wrefresh(dialog);
1060a9064fbSMasahiro Yamada 
1070a9064fbSMasahiro Yamada 	while (key != KEY_ESC) {
1080a9064fbSMasahiro Yamada 		key = wgetch(dialog);
1090a9064fbSMasahiro Yamada 
1100a9064fbSMasahiro Yamada 		if (button == -1) {	/* Input box selected */
1110a9064fbSMasahiro Yamada 			switch (key) {
1120a9064fbSMasahiro Yamada 			case TAB:
1130a9064fbSMasahiro Yamada 			case KEY_UP:
1140a9064fbSMasahiro Yamada 			case KEY_DOWN:
1150a9064fbSMasahiro Yamada 				break;
1160a9064fbSMasahiro Yamada 			case KEY_BACKSPACE:
1170a9064fbSMasahiro Yamada 			case 127:
1180a9064fbSMasahiro Yamada 				if (pos) {
1190a9064fbSMasahiro Yamada 					wattrset(dialog, dlg.inputbox.atr);
1200a9064fbSMasahiro Yamada 					if (input_x == 0) {
1210a9064fbSMasahiro Yamada 						show_x--;
1220a9064fbSMasahiro Yamada 					} else
1230a9064fbSMasahiro Yamada 						input_x--;
1240a9064fbSMasahiro Yamada 
1250a9064fbSMasahiro Yamada 					if (pos < len) {
1260a9064fbSMasahiro Yamada 						for (i = pos - 1; i < len; i++) {
1270a9064fbSMasahiro Yamada 							instr[i] = instr[i+1];
1280a9064fbSMasahiro Yamada 						}
1290a9064fbSMasahiro Yamada 					}
1300a9064fbSMasahiro Yamada 
1310a9064fbSMasahiro Yamada 					pos--;
1320a9064fbSMasahiro Yamada 					len--;
1330a9064fbSMasahiro Yamada 					instr[len] = '\0';
1340a9064fbSMasahiro Yamada 					wmove(dialog, box_y, box_x);
1350a9064fbSMasahiro Yamada 					for (i = 0; i < box_width; i++) {
1360a9064fbSMasahiro Yamada 						if (!instr[show_x + i]) {
1370a9064fbSMasahiro Yamada 							waddch(dialog, ' ');
1380a9064fbSMasahiro Yamada 							break;
1390a9064fbSMasahiro Yamada 						}
1400a9064fbSMasahiro Yamada 						waddch(dialog, instr[show_x + i]);
1410a9064fbSMasahiro Yamada 					}
1420a9064fbSMasahiro Yamada 					wmove(dialog, box_y, input_x + box_x);
1430a9064fbSMasahiro Yamada 					wrefresh(dialog);
1440a9064fbSMasahiro Yamada 				}
1450a9064fbSMasahiro Yamada 				continue;
1460a9064fbSMasahiro Yamada 			case KEY_LEFT:
1470a9064fbSMasahiro Yamada 				if (pos > 0) {
1480a9064fbSMasahiro Yamada 					if (input_x > 0) {
1490a9064fbSMasahiro Yamada 						wmove(dialog, box_y, --input_x + box_x);
1500a9064fbSMasahiro Yamada 					} else if (input_x == 0) {
1510a9064fbSMasahiro Yamada 						show_x--;
1520a9064fbSMasahiro Yamada 						wmove(dialog, box_y, box_x);
1530a9064fbSMasahiro Yamada 						for (i = 0; i < box_width; i++) {
1540a9064fbSMasahiro Yamada 							if (!instr[show_x + i]) {
1550a9064fbSMasahiro Yamada 								waddch(dialog, ' ');
1560a9064fbSMasahiro Yamada 								break;
1570a9064fbSMasahiro Yamada 							}
1580a9064fbSMasahiro Yamada 							waddch(dialog, instr[show_x + i]);
1590a9064fbSMasahiro Yamada 						}
1600a9064fbSMasahiro Yamada 						wmove(dialog, box_y, box_x);
1610a9064fbSMasahiro Yamada 					}
1620a9064fbSMasahiro Yamada 					pos--;
1630a9064fbSMasahiro Yamada 				}
1640a9064fbSMasahiro Yamada 				continue;
1650a9064fbSMasahiro Yamada 			case KEY_RIGHT:
1660a9064fbSMasahiro Yamada 				if (pos < len) {
1670a9064fbSMasahiro Yamada 					if (input_x < box_width - 1) {
1680a9064fbSMasahiro Yamada 						wmove(dialog, box_y, ++input_x + box_x);
1690a9064fbSMasahiro Yamada 					} else if (input_x == box_width - 1) {
1700a9064fbSMasahiro Yamada 						show_x++;
1710a9064fbSMasahiro Yamada 						wmove(dialog, box_y, box_x);
1720a9064fbSMasahiro Yamada 						for (i = 0; i < box_width; i++) {
1730a9064fbSMasahiro Yamada 							if (!instr[show_x + i]) {
1740a9064fbSMasahiro Yamada 								waddch(dialog, ' ');
1750a9064fbSMasahiro Yamada 								break;
1760a9064fbSMasahiro Yamada 							}
1770a9064fbSMasahiro Yamada 							waddch(dialog, instr[show_x + i]);
1780a9064fbSMasahiro Yamada 						}
1790a9064fbSMasahiro Yamada 						wmove(dialog, box_y, input_x + box_x);
1800a9064fbSMasahiro Yamada 					}
1810a9064fbSMasahiro Yamada 					pos++;
1820a9064fbSMasahiro Yamada 				}
1830a9064fbSMasahiro Yamada 				continue;
1840a9064fbSMasahiro Yamada 			default:
1850a9064fbSMasahiro Yamada 				if (key < 0x100 && isprint(key)) {
1860a9064fbSMasahiro Yamada 					if (len < MAX_LEN) {
1870a9064fbSMasahiro Yamada 						wattrset(dialog, dlg.inputbox.atr);
1880a9064fbSMasahiro Yamada 						if (pos < len) {
1890a9064fbSMasahiro Yamada 							for (i = len; i > pos; i--)
1900a9064fbSMasahiro Yamada 								instr[i] = instr[i-1];
1910a9064fbSMasahiro Yamada 							instr[pos] = key;
1920a9064fbSMasahiro Yamada 						} else {
1930a9064fbSMasahiro Yamada 							instr[len] = key;
1940a9064fbSMasahiro Yamada 						}
1950a9064fbSMasahiro Yamada 						pos++;
1960a9064fbSMasahiro Yamada 						len++;
1970a9064fbSMasahiro Yamada 						instr[len] = '\0';
1980a9064fbSMasahiro Yamada 
1990a9064fbSMasahiro Yamada 						if (input_x == box_width - 1) {
2000a9064fbSMasahiro Yamada 							show_x++;
2010a9064fbSMasahiro Yamada 						} else {
2020a9064fbSMasahiro Yamada 							input_x++;
2030a9064fbSMasahiro Yamada 						}
2040a9064fbSMasahiro Yamada 
2050a9064fbSMasahiro Yamada 						wmove(dialog, box_y, box_x);
2060a9064fbSMasahiro Yamada 						for (i = 0; i < box_width; i++) {
2070a9064fbSMasahiro Yamada 							if (!instr[show_x + i]) {
2080a9064fbSMasahiro Yamada 								waddch(dialog, ' ');
2090a9064fbSMasahiro Yamada 								break;
2100a9064fbSMasahiro Yamada 							}
2110a9064fbSMasahiro Yamada 							waddch(dialog, instr[show_x + i]);
2120a9064fbSMasahiro Yamada 						}
2130a9064fbSMasahiro Yamada 						wmove(dialog, box_y, input_x + box_x);
2140a9064fbSMasahiro Yamada 						wrefresh(dialog);
2150a9064fbSMasahiro Yamada 					} else
2160a9064fbSMasahiro Yamada 						flash();	/* Alarm user about overflow */
2170a9064fbSMasahiro Yamada 					continue;
2180a9064fbSMasahiro Yamada 				}
2190a9064fbSMasahiro Yamada 			}
2200a9064fbSMasahiro Yamada 		}
2210a9064fbSMasahiro Yamada 		switch (key) {
2220a9064fbSMasahiro Yamada 		case 'O':
2230a9064fbSMasahiro Yamada 		case 'o':
2240a9064fbSMasahiro Yamada 			delwin(dialog);
2250a9064fbSMasahiro Yamada 			return 0;
2260a9064fbSMasahiro Yamada 		case 'H':
2270a9064fbSMasahiro Yamada 		case 'h':
2280a9064fbSMasahiro Yamada 			delwin(dialog);
2290a9064fbSMasahiro Yamada 			return 1;
2300a9064fbSMasahiro Yamada 		case KEY_UP:
2310a9064fbSMasahiro Yamada 		case KEY_LEFT:
2320a9064fbSMasahiro Yamada 			switch (button) {
2330a9064fbSMasahiro Yamada 			case -1:
2340a9064fbSMasahiro Yamada 				button = 1;	/* Indicates "Help" button is selected */
2350a9064fbSMasahiro Yamada 				print_buttons(dialog, height, width, 1);
2360a9064fbSMasahiro Yamada 				break;
2370a9064fbSMasahiro Yamada 			case 0:
2380a9064fbSMasahiro Yamada 				button = -1;	/* Indicates input box is selected */
2390a9064fbSMasahiro Yamada 				print_buttons(dialog, height, width, 0);
2400a9064fbSMasahiro Yamada 				wmove(dialog, box_y, box_x + input_x);
2410a9064fbSMasahiro Yamada 				wrefresh(dialog);
2420a9064fbSMasahiro Yamada 				break;
2430a9064fbSMasahiro Yamada 			case 1:
2440a9064fbSMasahiro Yamada 				button = 0;	/* Indicates "OK" button is selected */
2450a9064fbSMasahiro Yamada 				print_buttons(dialog, height, width, 0);
2460a9064fbSMasahiro Yamada 				break;
2470a9064fbSMasahiro Yamada 			}
2480a9064fbSMasahiro Yamada 			break;
2490a9064fbSMasahiro Yamada 		case TAB:
2500a9064fbSMasahiro Yamada 		case KEY_DOWN:
2510a9064fbSMasahiro Yamada 		case KEY_RIGHT:
2520a9064fbSMasahiro Yamada 			switch (button) {
2530a9064fbSMasahiro Yamada 			case -1:
2540a9064fbSMasahiro Yamada 				button = 0;	/* Indicates "OK" button is selected */
2550a9064fbSMasahiro Yamada 				print_buttons(dialog, height, width, 0);
2560a9064fbSMasahiro Yamada 				break;
2570a9064fbSMasahiro Yamada 			case 0:
2580a9064fbSMasahiro Yamada 				button = 1;	/* Indicates "Help" button is selected */
2590a9064fbSMasahiro Yamada 				print_buttons(dialog, height, width, 1);
2600a9064fbSMasahiro Yamada 				break;
2610a9064fbSMasahiro Yamada 			case 1:
2620a9064fbSMasahiro Yamada 				button = -1;	/* Indicates input box is selected */
2630a9064fbSMasahiro Yamada 				print_buttons(dialog, height, width, 0);
2640a9064fbSMasahiro Yamada 				wmove(dialog, box_y, box_x + input_x);
2650a9064fbSMasahiro Yamada 				wrefresh(dialog);
2660a9064fbSMasahiro Yamada 				break;
2670a9064fbSMasahiro Yamada 			}
2680a9064fbSMasahiro Yamada 			break;
2690a9064fbSMasahiro Yamada 		case ' ':
2700a9064fbSMasahiro Yamada 		case '\n':
2710a9064fbSMasahiro Yamada 			delwin(dialog);
2720a9064fbSMasahiro Yamada 			return (button == -1 ? 0 : button);
2730a9064fbSMasahiro Yamada 		case 'X':
2740a9064fbSMasahiro Yamada 		case 'x':
2750a9064fbSMasahiro Yamada 			key = KEY_ESC;
2760a9064fbSMasahiro Yamada 			break;
2770a9064fbSMasahiro Yamada 		case KEY_ESC:
2780a9064fbSMasahiro Yamada 			key = on_key_esc(dialog);
2790a9064fbSMasahiro Yamada 			break;
2800a9064fbSMasahiro Yamada 		case KEY_RESIZE:
2810a9064fbSMasahiro Yamada 			delwin(dialog);
2820a9064fbSMasahiro Yamada 			on_key_resize();
2830a9064fbSMasahiro Yamada 			goto do_resize;
2840a9064fbSMasahiro Yamada 		}
2850a9064fbSMasahiro Yamada 	}
2860a9064fbSMasahiro Yamada 
2870a9064fbSMasahiro Yamada 	delwin(dialog);
2880a9064fbSMasahiro Yamada 	return KEY_ESC;		/* ESC pressed */
2890a9064fbSMasahiro Yamada }
290