18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  inputbox.c -- implements the input box
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
68c2ecf20Sopenharmony_ci *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "dialog.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cichar dialog_input_result[MAX_LEN + 1];
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/*
148c2ecf20Sopenharmony_ci *  Print the termination buttons
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_cistatic void print_buttons(WINDOW * dialog, int height, int width, int selected)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	int x = width / 2 - 11;
198c2ecf20Sopenharmony_ci	int y = height - 2;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	print_button(dialog, "  Ok  ", y, x, selected == 0);
228c2ecf20Sopenharmony_ci	print_button(dialog, " Help ", y, x + 14, selected == 1);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	wmove(dialog, y, x + 1 + 14 * selected);
258c2ecf20Sopenharmony_ci	wrefresh(dialog);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/*
298c2ecf20Sopenharmony_ci * Display a dialog box for inputing a string
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_ciint dialog_inputbox(const char *title, const char *prompt, int height, int width,
328c2ecf20Sopenharmony_ci		    const char *init)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	int i, x, y, box_y, box_x, box_width;
358c2ecf20Sopenharmony_ci	int input_x = 0, key = 0, button = -1;
368c2ecf20Sopenharmony_ci	int show_x, len, pos;
378c2ecf20Sopenharmony_ci	char *instr = dialog_input_result;
388c2ecf20Sopenharmony_ci	WINDOW *dialog;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	if (!init)
418c2ecf20Sopenharmony_ci		instr[0] = '\0';
428c2ecf20Sopenharmony_ci	else
438c2ecf20Sopenharmony_ci		strcpy(instr, init);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cido_resize:
468c2ecf20Sopenharmony_ci	if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
478c2ecf20Sopenharmony_ci		return -ERRDISPLAYTOOSMALL;
488c2ecf20Sopenharmony_ci	if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
498c2ecf20Sopenharmony_ci		return -ERRDISPLAYTOOSMALL;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	/* center dialog box on screen */
528c2ecf20Sopenharmony_ci	x = (getmaxx(stdscr) - width) / 2;
538c2ecf20Sopenharmony_ci	y = (getmaxy(stdscr) - height) / 2;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	draw_shadow(stdscr, y, x, height, width);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	dialog = newwin(height, width, y, x);
588c2ecf20Sopenharmony_ci	keypad(dialog, TRUE);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	draw_box(dialog, 0, 0, height, width,
618c2ecf20Sopenharmony_ci		 dlg.dialog.atr, dlg.border.atr);
628c2ecf20Sopenharmony_ci	wattrset(dialog, dlg.border.atr);
638c2ecf20Sopenharmony_ci	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
648c2ecf20Sopenharmony_ci	for (i = 0; i < width - 2; i++)
658c2ecf20Sopenharmony_ci		waddch(dialog, ACS_HLINE);
668c2ecf20Sopenharmony_ci	wattrset(dialog, dlg.dialog.atr);
678c2ecf20Sopenharmony_ci	waddch(dialog, ACS_RTEE);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	print_title(dialog, title, width);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	wattrset(dialog, dlg.dialog.atr);
728c2ecf20Sopenharmony_ci	print_autowrap(dialog, prompt, width - 2, 1, 3);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* Draw the input field box */
758c2ecf20Sopenharmony_ci	box_width = width - 6;
768c2ecf20Sopenharmony_ci	getyx(dialog, y, x);
778c2ecf20Sopenharmony_ci	box_y = y + 2;
788c2ecf20Sopenharmony_ci	box_x = (width - box_width) / 2;
798c2ecf20Sopenharmony_ci	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
808c2ecf20Sopenharmony_ci		 dlg.dialog.atr, dlg.border.atr);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	print_buttons(dialog, height, width, 0);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	/* Set up the initial value */
858c2ecf20Sopenharmony_ci	wmove(dialog, box_y, box_x);
868c2ecf20Sopenharmony_ci	wattrset(dialog, dlg.inputbox.atr);
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	len = strlen(instr);
898c2ecf20Sopenharmony_ci	pos = len;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	if (len >= box_width) {
928c2ecf20Sopenharmony_ci		show_x = len - box_width + 1;
938c2ecf20Sopenharmony_ci		input_x = box_width - 1;
948c2ecf20Sopenharmony_ci		for (i = 0; i < box_width - 1; i++)
958c2ecf20Sopenharmony_ci			waddch(dialog, instr[show_x + i]);
968c2ecf20Sopenharmony_ci	} else {
978c2ecf20Sopenharmony_ci		show_x = 0;
988c2ecf20Sopenharmony_ci		input_x = len;
998c2ecf20Sopenharmony_ci		waddstr(dialog, instr);
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	wmove(dialog, box_y, box_x + input_x);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	wrefresh(dialog);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	while (key != KEY_ESC) {
1078c2ecf20Sopenharmony_ci		key = wgetch(dialog);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci		if (button == -1) {	/* Input box selected */
1108c2ecf20Sopenharmony_ci			switch (key) {
1118c2ecf20Sopenharmony_ci			case TAB:
1128c2ecf20Sopenharmony_ci			case KEY_UP:
1138c2ecf20Sopenharmony_ci			case KEY_DOWN:
1148c2ecf20Sopenharmony_ci				break;
1158c2ecf20Sopenharmony_ci			case KEY_BACKSPACE:
1168c2ecf20Sopenharmony_ci			case 8:   /* ^H */
1178c2ecf20Sopenharmony_ci			case 127: /* ^? */
1188c2ecf20Sopenharmony_ci				if (pos) {
1198c2ecf20Sopenharmony_ci					wattrset(dialog, dlg.inputbox.atr);
1208c2ecf20Sopenharmony_ci					if (input_x == 0) {
1218c2ecf20Sopenharmony_ci						show_x--;
1228c2ecf20Sopenharmony_ci					} else
1238c2ecf20Sopenharmony_ci						input_x--;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci					if (pos < len) {
1268c2ecf20Sopenharmony_ci						for (i = pos - 1; i < len; i++) {
1278c2ecf20Sopenharmony_ci							instr[i] = instr[i+1];
1288c2ecf20Sopenharmony_ci						}
1298c2ecf20Sopenharmony_ci					}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci					pos--;
1328c2ecf20Sopenharmony_ci					len--;
1338c2ecf20Sopenharmony_ci					instr[len] = '\0';
1348c2ecf20Sopenharmony_ci					wmove(dialog, box_y, box_x);
1358c2ecf20Sopenharmony_ci					for (i = 0; i < box_width; i++) {
1368c2ecf20Sopenharmony_ci						if (!instr[show_x + i]) {
1378c2ecf20Sopenharmony_ci							waddch(dialog, ' ');
1388c2ecf20Sopenharmony_ci							break;
1398c2ecf20Sopenharmony_ci						}
1408c2ecf20Sopenharmony_ci						waddch(dialog, instr[show_x + i]);
1418c2ecf20Sopenharmony_ci					}
1428c2ecf20Sopenharmony_ci					wmove(dialog, box_y, input_x + box_x);
1438c2ecf20Sopenharmony_ci					wrefresh(dialog);
1448c2ecf20Sopenharmony_ci				}
1458c2ecf20Sopenharmony_ci				continue;
1468c2ecf20Sopenharmony_ci			case KEY_LEFT:
1478c2ecf20Sopenharmony_ci				if (pos > 0) {
1488c2ecf20Sopenharmony_ci					if (input_x > 0) {
1498c2ecf20Sopenharmony_ci						wmove(dialog, box_y, --input_x + box_x);
1508c2ecf20Sopenharmony_ci					} else if (input_x == 0) {
1518c2ecf20Sopenharmony_ci						show_x--;
1528c2ecf20Sopenharmony_ci						wmove(dialog, box_y, box_x);
1538c2ecf20Sopenharmony_ci						for (i = 0; i < box_width; i++) {
1548c2ecf20Sopenharmony_ci							if (!instr[show_x + i]) {
1558c2ecf20Sopenharmony_ci								waddch(dialog, ' ');
1568c2ecf20Sopenharmony_ci								break;
1578c2ecf20Sopenharmony_ci							}
1588c2ecf20Sopenharmony_ci							waddch(dialog, instr[show_x + i]);
1598c2ecf20Sopenharmony_ci						}
1608c2ecf20Sopenharmony_ci						wmove(dialog, box_y, box_x);
1618c2ecf20Sopenharmony_ci					}
1628c2ecf20Sopenharmony_ci					pos--;
1638c2ecf20Sopenharmony_ci				}
1648c2ecf20Sopenharmony_ci				continue;
1658c2ecf20Sopenharmony_ci			case KEY_RIGHT:
1668c2ecf20Sopenharmony_ci				if (pos < len) {
1678c2ecf20Sopenharmony_ci					if (input_x < box_width - 1) {
1688c2ecf20Sopenharmony_ci						wmove(dialog, box_y, ++input_x + box_x);
1698c2ecf20Sopenharmony_ci					} else if (input_x == box_width - 1) {
1708c2ecf20Sopenharmony_ci						show_x++;
1718c2ecf20Sopenharmony_ci						wmove(dialog, box_y, box_x);
1728c2ecf20Sopenharmony_ci						for (i = 0; i < box_width; i++) {
1738c2ecf20Sopenharmony_ci							if (!instr[show_x + i]) {
1748c2ecf20Sopenharmony_ci								waddch(dialog, ' ');
1758c2ecf20Sopenharmony_ci								break;
1768c2ecf20Sopenharmony_ci							}
1778c2ecf20Sopenharmony_ci							waddch(dialog, instr[show_x + i]);
1788c2ecf20Sopenharmony_ci						}
1798c2ecf20Sopenharmony_ci						wmove(dialog, box_y, input_x + box_x);
1808c2ecf20Sopenharmony_ci					}
1818c2ecf20Sopenharmony_ci					pos++;
1828c2ecf20Sopenharmony_ci				}
1838c2ecf20Sopenharmony_ci				continue;
1848c2ecf20Sopenharmony_ci			default:
1858c2ecf20Sopenharmony_ci				if (key < 0x100 && isprint(key)) {
1868c2ecf20Sopenharmony_ci					if (len < MAX_LEN) {
1878c2ecf20Sopenharmony_ci						wattrset(dialog, dlg.inputbox.atr);
1888c2ecf20Sopenharmony_ci						if (pos < len) {
1898c2ecf20Sopenharmony_ci							for (i = len; i > pos; i--)
1908c2ecf20Sopenharmony_ci								instr[i] = instr[i-1];
1918c2ecf20Sopenharmony_ci							instr[pos] = key;
1928c2ecf20Sopenharmony_ci						} else {
1938c2ecf20Sopenharmony_ci							instr[len] = key;
1948c2ecf20Sopenharmony_ci						}
1958c2ecf20Sopenharmony_ci						pos++;
1968c2ecf20Sopenharmony_ci						len++;
1978c2ecf20Sopenharmony_ci						instr[len] = '\0';
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci						if (input_x == box_width - 1) {
2008c2ecf20Sopenharmony_ci							show_x++;
2018c2ecf20Sopenharmony_ci						} else {
2028c2ecf20Sopenharmony_ci							input_x++;
2038c2ecf20Sopenharmony_ci						}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci						wmove(dialog, box_y, box_x);
2068c2ecf20Sopenharmony_ci						for (i = 0; i < box_width; i++) {
2078c2ecf20Sopenharmony_ci							if (!instr[show_x + i]) {
2088c2ecf20Sopenharmony_ci								waddch(dialog, ' ');
2098c2ecf20Sopenharmony_ci								break;
2108c2ecf20Sopenharmony_ci							}
2118c2ecf20Sopenharmony_ci							waddch(dialog, instr[show_x + i]);
2128c2ecf20Sopenharmony_ci						}
2138c2ecf20Sopenharmony_ci						wmove(dialog, box_y, input_x + box_x);
2148c2ecf20Sopenharmony_ci						wrefresh(dialog);
2158c2ecf20Sopenharmony_ci					} else
2168c2ecf20Sopenharmony_ci						flash();	/* Alarm user about overflow */
2178c2ecf20Sopenharmony_ci					continue;
2188c2ecf20Sopenharmony_ci				}
2198c2ecf20Sopenharmony_ci			}
2208c2ecf20Sopenharmony_ci		}
2218c2ecf20Sopenharmony_ci		switch (key) {
2228c2ecf20Sopenharmony_ci		case 'O':
2238c2ecf20Sopenharmony_ci		case 'o':
2248c2ecf20Sopenharmony_ci			delwin(dialog);
2258c2ecf20Sopenharmony_ci			return 0;
2268c2ecf20Sopenharmony_ci		case 'H':
2278c2ecf20Sopenharmony_ci		case 'h':
2288c2ecf20Sopenharmony_ci			delwin(dialog);
2298c2ecf20Sopenharmony_ci			return 1;
2308c2ecf20Sopenharmony_ci		case KEY_UP:
2318c2ecf20Sopenharmony_ci		case KEY_LEFT:
2328c2ecf20Sopenharmony_ci			switch (button) {
2338c2ecf20Sopenharmony_ci			case -1:
2348c2ecf20Sopenharmony_ci				button = 1;	/* Indicates "Help" button is selected */
2358c2ecf20Sopenharmony_ci				print_buttons(dialog, height, width, 1);
2368c2ecf20Sopenharmony_ci				break;
2378c2ecf20Sopenharmony_ci			case 0:
2388c2ecf20Sopenharmony_ci				button = -1;	/* Indicates input box is selected */
2398c2ecf20Sopenharmony_ci				print_buttons(dialog, height, width, 0);
2408c2ecf20Sopenharmony_ci				wmove(dialog, box_y, box_x + input_x);
2418c2ecf20Sopenharmony_ci				wrefresh(dialog);
2428c2ecf20Sopenharmony_ci				break;
2438c2ecf20Sopenharmony_ci			case 1:
2448c2ecf20Sopenharmony_ci				button = 0;	/* Indicates "OK" button is selected */
2458c2ecf20Sopenharmony_ci				print_buttons(dialog, height, width, 0);
2468c2ecf20Sopenharmony_ci				break;
2478c2ecf20Sopenharmony_ci			}
2488c2ecf20Sopenharmony_ci			break;
2498c2ecf20Sopenharmony_ci		case TAB:
2508c2ecf20Sopenharmony_ci		case KEY_DOWN:
2518c2ecf20Sopenharmony_ci		case KEY_RIGHT:
2528c2ecf20Sopenharmony_ci			switch (button) {
2538c2ecf20Sopenharmony_ci			case -1:
2548c2ecf20Sopenharmony_ci				button = 0;	/* Indicates "OK" button is selected */
2558c2ecf20Sopenharmony_ci				print_buttons(dialog, height, width, 0);
2568c2ecf20Sopenharmony_ci				break;
2578c2ecf20Sopenharmony_ci			case 0:
2588c2ecf20Sopenharmony_ci				button = 1;	/* Indicates "Help" button is selected */
2598c2ecf20Sopenharmony_ci				print_buttons(dialog, height, width, 1);
2608c2ecf20Sopenharmony_ci				break;
2618c2ecf20Sopenharmony_ci			case 1:
2628c2ecf20Sopenharmony_ci				button = -1;	/* Indicates input box is selected */
2638c2ecf20Sopenharmony_ci				print_buttons(dialog, height, width, 0);
2648c2ecf20Sopenharmony_ci				wmove(dialog, box_y, box_x + input_x);
2658c2ecf20Sopenharmony_ci				wrefresh(dialog);
2668c2ecf20Sopenharmony_ci				break;
2678c2ecf20Sopenharmony_ci			}
2688c2ecf20Sopenharmony_ci			break;
2698c2ecf20Sopenharmony_ci		case ' ':
2708c2ecf20Sopenharmony_ci		case '\n':
2718c2ecf20Sopenharmony_ci			delwin(dialog);
2728c2ecf20Sopenharmony_ci			return (button == -1 ? 0 : button);
2738c2ecf20Sopenharmony_ci		case 'X':
2748c2ecf20Sopenharmony_ci		case 'x':
2758c2ecf20Sopenharmony_ci			key = KEY_ESC;
2768c2ecf20Sopenharmony_ci			break;
2778c2ecf20Sopenharmony_ci		case KEY_ESC:
2788c2ecf20Sopenharmony_ci			key = on_key_esc(dialog);
2798c2ecf20Sopenharmony_ci			break;
2808c2ecf20Sopenharmony_ci		case KEY_RESIZE:
2818c2ecf20Sopenharmony_ci			delwin(dialog);
2828c2ecf20Sopenharmony_ci			on_key_resize();
2838c2ecf20Sopenharmony_ci			goto do_resize;
2848c2ecf20Sopenharmony_ci		}
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	delwin(dialog);
2888c2ecf20Sopenharmony_ci	return KEY_ESC;		/* ESC pressed */
2898c2ecf20Sopenharmony_ci}
290