162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  inputbox.c -- implements the input box
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
662306a36Sopenharmony_ci *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "dialog.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cichar dialog_input_result[MAX_LEN + 1];
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci *  Print the termination buttons
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_cistatic void print_buttons(WINDOW * dialog, int height, int width, int selected)
1762306a36Sopenharmony_ci{
1862306a36Sopenharmony_ci	int x = width / 2 - 11;
1962306a36Sopenharmony_ci	int y = height - 2;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	print_button(dialog, "  Ok  ", y, x, selected == 0);
2262306a36Sopenharmony_ci	print_button(dialog, " Help ", y, x + 14, selected == 1);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	wmove(dialog, y, x + 1 + 14 * selected);
2562306a36Sopenharmony_ci	wrefresh(dialog);
2662306a36Sopenharmony_ci}
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Display a dialog box for inputing a string
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_ciint dialog_inputbox(const char *title, const char *prompt, int height, int width,
3262306a36Sopenharmony_ci		    const char *init)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	int i, x, y, box_y, box_x, box_width;
3562306a36Sopenharmony_ci	int input_x = 0, key = 0, button = -1;
3662306a36Sopenharmony_ci	int show_x, len, pos;
3762306a36Sopenharmony_ci	char *instr = dialog_input_result;
3862306a36Sopenharmony_ci	WINDOW *dialog;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	if (!init)
4162306a36Sopenharmony_ci		instr[0] = '\0';
4262306a36Sopenharmony_ci	else
4362306a36Sopenharmony_ci		strcpy(instr, init);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cido_resize:
4662306a36Sopenharmony_ci	if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
4762306a36Sopenharmony_ci		return -ERRDISPLAYTOOSMALL;
4862306a36Sopenharmony_ci	if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
4962306a36Sopenharmony_ci		return -ERRDISPLAYTOOSMALL;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	/* center dialog box on screen */
5262306a36Sopenharmony_ci	x = (getmaxx(stdscr) - width) / 2;
5362306a36Sopenharmony_ci	y = (getmaxy(stdscr) - height) / 2;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	draw_shadow(stdscr, y, x, height, width);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	dialog = newwin(height, width, y, x);
5862306a36Sopenharmony_ci	keypad(dialog, TRUE);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	draw_box(dialog, 0, 0, height, width,
6162306a36Sopenharmony_ci		 dlg.dialog.atr, dlg.border.atr);
6262306a36Sopenharmony_ci	wattrset(dialog, dlg.border.atr);
6362306a36Sopenharmony_ci	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
6462306a36Sopenharmony_ci	for (i = 0; i < width - 2; i++)
6562306a36Sopenharmony_ci		waddch(dialog, ACS_HLINE);
6662306a36Sopenharmony_ci	wattrset(dialog, dlg.dialog.atr);
6762306a36Sopenharmony_ci	waddch(dialog, ACS_RTEE);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	print_title(dialog, title, width);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	wattrset(dialog, dlg.dialog.atr);
7262306a36Sopenharmony_ci	print_autowrap(dialog, prompt, width - 2, 1, 3);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/* Draw the input field box */
7562306a36Sopenharmony_ci	box_width = width - 6;
7662306a36Sopenharmony_ci	getyx(dialog, y, x);
7762306a36Sopenharmony_ci	box_y = y + 2;
7862306a36Sopenharmony_ci	box_x = (width - box_width) / 2;
7962306a36Sopenharmony_ci	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
8062306a36Sopenharmony_ci		 dlg.dialog.atr, dlg.border.atr);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	print_buttons(dialog, height, width, 0);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	/* Set up the initial value */
8562306a36Sopenharmony_ci	wmove(dialog, box_y, box_x);
8662306a36Sopenharmony_ci	wattrset(dialog, dlg.inputbox.atr);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	len = strlen(instr);
8962306a36Sopenharmony_ci	pos = len;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	if (len >= box_width) {
9262306a36Sopenharmony_ci		show_x = len - box_width + 1;
9362306a36Sopenharmony_ci		input_x = box_width - 1;
9462306a36Sopenharmony_ci		for (i = 0; i < box_width - 1; i++)
9562306a36Sopenharmony_ci			waddch(dialog, instr[show_x + i]);
9662306a36Sopenharmony_ci	} else {
9762306a36Sopenharmony_ci		show_x = 0;
9862306a36Sopenharmony_ci		input_x = len;
9962306a36Sopenharmony_ci		waddstr(dialog, instr);
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	wmove(dialog, box_y, box_x + input_x);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	wrefresh(dialog);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	while (key != KEY_ESC) {
10762306a36Sopenharmony_ci		key = wgetch(dialog);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci		if (button == -1) {	/* Input box selected */
11062306a36Sopenharmony_ci			switch (key) {
11162306a36Sopenharmony_ci			case TAB:
11262306a36Sopenharmony_ci			case KEY_UP:
11362306a36Sopenharmony_ci			case KEY_DOWN:
11462306a36Sopenharmony_ci				break;
11562306a36Sopenharmony_ci			case KEY_BACKSPACE:
11662306a36Sopenharmony_ci			case 8:   /* ^H */
11762306a36Sopenharmony_ci			case 127: /* ^? */
11862306a36Sopenharmony_ci				if (pos) {
11962306a36Sopenharmony_ci					wattrset(dialog, dlg.inputbox.atr);
12062306a36Sopenharmony_ci					if (input_x == 0) {
12162306a36Sopenharmony_ci						show_x--;
12262306a36Sopenharmony_ci					} else
12362306a36Sopenharmony_ci						input_x--;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci					if (pos < len) {
12662306a36Sopenharmony_ci						for (i = pos - 1; i < len; i++) {
12762306a36Sopenharmony_ci							instr[i] = instr[i+1];
12862306a36Sopenharmony_ci						}
12962306a36Sopenharmony_ci					}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci					pos--;
13262306a36Sopenharmony_ci					len--;
13362306a36Sopenharmony_ci					instr[len] = '\0';
13462306a36Sopenharmony_ci					wmove(dialog, box_y, box_x);
13562306a36Sopenharmony_ci					for (i = 0; i < box_width; i++) {
13662306a36Sopenharmony_ci						if (!instr[show_x + i]) {
13762306a36Sopenharmony_ci							waddch(dialog, ' ');
13862306a36Sopenharmony_ci							break;
13962306a36Sopenharmony_ci						}
14062306a36Sopenharmony_ci						waddch(dialog, instr[show_x + i]);
14162306a36Sopenharmony_ci					}
14262306a36Sopenharmony_ci					wmove(dialog, box_y, input_x + box_x);
14362306a36Sopenharmony_ci					wrefresh(dialog);
14462306a36Sopenharmony_ci				}
14562306a36Sopenharmony_ci				continue;
14662306a36Sopenharmony_ci			case KEY_LEFT:
14762306a36Sopenharmony_ci				if (pos > 0) {
14862306a36Sopenharmony_ci					if (input_x > 0) {
14962306a36Sopenharmony_ci						wmove(dialog, box_y, --input_x + box_x);
15062306a36Sopenharmony_ci					} else if (input_x == 0) {
15162306a36Sopenharmony_ci						show_x--;
15262306a36Sopenharmony_ci						wmove(dialog, box_y, box_x);
15362306a36Sopenharmony_ci						for (i = 0; i < box_width; i++) {
15462306a36Sopenharmony_ci							if (!instr[show_x + i]) {
15562306a36Sopenharmony_ci								waddch(dialog, ' ');
15662306a36Sopenharmony_ci								break;
15762306a36Sopenharmony_ci							}
15862306a36Sopenharmony_ci							waddch(dialog, instr[show_x + i]);
15962306a36Sopenharmony_ci						}
16062306a36Sopenharmony_ci						wmove(dialog, box_y, box_x);
16162306a36Sopenharmony_ci					}
16262306a36Sopenharmony_ci					pos--;
16362306a36Sopenharmony_ci				}
16462306a36Sopenharmony_ci				continue;
16562306a36Sopenharmony_ci			case KEY_RIGHT:
16662306a36Sopenharmony_ci				if (pos < len) {
16762306a36Sopenharmony_ci					if (input_x < box_width - 1) {
16862306a36Sopenharmony_ci						wmove(dialog, box_y, ++input_x + box_x);
16962306a36Sopenharmony_ci					} else if (input_x == box_width - 1) {
17062306a36Sopenharmony_ci						show_x++;
17162306a36Sopenharmony_ci						wmove(dialog, box_y, box_x);
17262306a36Sopenharmony_ci						for (i = 0; i < box_width; i++) {
17362306a36Sopenharmony_ci							if (!instr[show_x + i]) {
17462306a36Sopenharmony_ci								waddch(dialog, ' ');
17562306a36Sopenharmony_ci								break;
17662306a36Sopenharmony_ci							}
17762306a36Sopenharmony_ci							waddch(dialog, instr[show_x + i]);
17862306a36Sopenharmony_ci						}
17962306a36Sopenharmony_ci						wmove(dialog, box_y, input_x + box_x);
18062306a36Sopenharmony_ci					}
18162306a36Sopenharmony_ci					pos++;
18262306a36Sopenharmony_ci				}
18362306a36Sopenharmony_ci				continue;
18462306a36Sopenharmony_ci			default:
18562306a36Sopenharmony_ci				if (key < 0x100 && isprint(key)) {
18662306a36Sopenharmony_ci					if (len < MAX_LEN) {
18762306a36Sopenharmony_ci						wattrset(dialog, dlg.inputbox.atr);
18862306a36Sopenharmony_ci						if (pos < len) {
18962306a36Sopenharmony_ci							for (i = len; i > pos; i--)
19062306a36Sopenharmony_ci								instr[i] = instr[i-1];
19162306a36Sopenharmony_ci							instr[pos] = key;
19262306a36Sopenharmony_ci						} else {
19362306a36Sopenharmony_ci							instr[len] = key;
19462306a36Sopenharmony_ci						}
19562306a36Sopenharmony_ci						pos++;
19662306a36Sopenharmony_ci						len++;
19762306a36Sopenharmony_ci						instr[len] = '\0';
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci						if (input_x == box_width - 1) {
20062306a36Sopenharmony_ci							show_x++;
20162306a36Sopenharmony_ci						} else {
20262306a36Sopenharmony_ci							input_x++;
20362306a36Sopenharmony_ci						}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci						wmove(dialog, box_y, box_x);
20662306a36Sopenharmony_ci						for (i = 0; i < box_width; i++) {
20762306a36Sopenharmony_ci							if (!instr[show_x + i]) {
20862306a36Sopenharmony_ci								waddch(dialog, ' ');
20962306a36Sopenharmony_ci								break;
21062306a36Sopenharmony_ci							}
21162306a36Sopenharmony_ci							waddch(dialog, instr[show_x + i]);
21262306a36Sopenharmony_ci						}
21362306a36Sopenharmony_ci						wmove(dialog, box_y, input_x + box_x);
21462306a36Sopenharmony_ci						wrefresh(dialog);
21562306a36Sopenharmony_ci					} else
21662306a36Sopenharmony_ci						flash();	/* Alarm user about overflow */
21762306a36Sopenharmony_ci					continue;
21862306a36Sopenharmony_ci				}
21962306a36Sopenharmony_ci			}
22062306a36Sopenharmony_ci		}
22162306a36Sopenharmony_ci		switch (key) {
22262306a36Sopenharmony_ci		case 'O':
22362306a36Sopenharmony_ci		case 'o':
22462306a36Sopenharmony_ci			delwin(dialog);
22562306a36Sopenharmony_ci			return 0;
22662306a36Sopenharmony_ci		case 'H':
22762306a36Sopenharmony_ci		case 'h':
22862306a36Sopenharmony_ci			delwin(dialog);
22962306a36Sopenharmony_ci			return 1;
23062306a36Sopenharmony_ci		case KEY_UP:
23162306a36Sopenharmony_ci		case KEY_LEFT:
23262306a36Sopenharmony_ci			switch (button) {
23362306a36Sopenharmony_ci			case -1:
23462306a36Sopenharmony_ci				button = 1;	/* Indicates "Help" button is selected */
23562306a36Sopenharmony_ci				print_buttons(dialog, height, width, 1);
23662306a36Sopenharmony_ci				break;
23762306a36Sopenharmony_ci			case 0:
23862306a36Sopenharmony_ci				button = -1;	/* Indicates input box is selected */
23962306a36Sopenharmony_ci				print_buttons(dialog, height, width, 0);
24062306a36Sopenharmony_ci				wmove(dialog, box_y, box_x + input_x);
24162306a36Sopenharmony_ci				wrefresh(dialog);
24262306a36Sopenharmony_ci				break;
24362306a36Sopenharmony_ci			case 1:
24462306a36Sopenharmony_ci				button = 0;	/* Indicates "OK" button is selected */
24562306a36Sopenharmony_ci				print_buttons(dialog, height, width, 0);
24662306a36Sopenharmony_ci				break;
24762306a36Sopenharmony_ci			}
24862306a36Sopenharmony_ci			break;
24962306a36Sopenharmony_ci		case TAB:
25062306a36Sopenharmony_ci		case KEY_DOWN:
25162306a36Sopenharmony_ci		case KEY_RIGHT:
25262306a36Sopenharmony_ci			switch (button) {
25362306a36Sopenharmony_ci			case -1:
25462306a36Sopenharmony_ci				button = 0;	/* Indicates "OK" button is selected */
25562306a36Sopenharmony_ci				print_buttons(dialog, height, width, 0);
25662306a36Sopenharmony_ci				break;
25762306a36Sopenharmony_ci			case 0:
25862306a36Sopenharmony_ci				button = 1;	/* Indicates "Help" button is selected */
25962306a36Sopenharmony_ci				print_buttons(dialog, height, width, 1);
26062306a36Sopenharmony_ci				break;
26162306a36Sopenharmony_ci			case 1:
26262306a36Sopenharmony_ci				button = -1;	/* Indicates input box is selected */
26362306a36Sopenharmony_ci				print_buttons(dialog, height, width, 0);
26462306a36Sopenharmony_ci				wmove(dialog, box_y, box_x + input_x);
26562306a36Sopenharmony_ci				wrefresh(dialog);
26662306a36Sopenharmony_ci				break;
26762306a36Sopenharmony_ci			}
26862306a36Sopenharmony_ci			break;
26962306a36Sopenharmony_ci		case ' ':
27062306a36Sopenharmony_ci		case '\n':
27162306a36Sopenharmony_ci			delwin(dialog);
27262306a36Sopenharmony_ci			return (button == -1 ? 0 : button);
27362306a36Sopenharmony_ci		case 'X':
27462306a36Sopenharmony_ci		case 'x':
27562306a36Sopenharmony_ci			key = KEY_ESC;
27662306a36Sopenharmony_ci			break;
27762306a36Sopenharmony_ci		case KEY_ESC:
27862306a36Sopenharmony_ci			key = on_key_esc(dialog);
27962306a36Sopenharmony_ci			break;
28062306a36Sopenharmony_ci		case KEY_RESIZE:
28162306a36Sopenharmony_ci			delwin(dialog);
28262306a36Sopenharmony_ci			on_key_resize();
28362306a36Sopenharmony_ci			goto do_resize;
28462306a36Sopenharmony_ci		}
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	delwin(dialog);
28862306a36Sopenharmony_ci	return KEY_ESC;		/* ESC pressed */
28962306a36Sopenharmony_ci}
290