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