xref: /aosp_15_r20/external/toybox/kconfig/lxdialog/inputbox.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /*
2*cf5a6c84SAndroid Build Coastguard Worker  *  inputbox.c -- implements the input box
3*cf5a6c84SAndroid Build Coastguard Worker  *
4*cf5a6c84SAndroid Build Coastguard Worker  *  ORIGINAL AUTHOR: Savio Lam ([email protected])
5*cf5a6c84SAndroid Build Coastguard Worker  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap ([email protected])
6*cf5a6c84SAndroid Build Coastguard Worker  *
7*cf5a6c84SAndroid Build Coastguard Worker  *  This program is free software; you can redistribute it and/or
8*cf5a6c84SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU General Public License
9*cf5a6c84SAndroid Build Coastguard Worker  *  as published by the Free Software Foundation; either version 2
10*cf5a6c84SAndroid Build Coastguard Worker  *  of the License, or (at your option) any later version.
11*cf5a6c84SAndroid Build Coastguard Worker  *
12*cf5a6c84SAndroid Build Coastguard Worker  *  This program is distributed in the hope that it will be useful,
13*cf5a6c84SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14*cf5a6c84SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*cf5a6c84SAndroid Build Coastguard Worker  *  GNU General Public License for more details.
16*cf5a6c84SAndroid Build Coastguard Worker  *
17*cf5a6c84SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU General Public License
18*cf5a6c84SAndroid Build Coastguard Worker  *  along with this program; if not, write to the Free Software
19*cf5a6c84SAndroid Build Coastguard Worker  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*cf5a6c84SAndroid Build Coastguard Worker  */
21*cf5a6c84SAndroid Build Coastguard Worker 
22*cf5a6c84SAndroid Build Coastguard Worker #include "dialog.h"
23*cf5a6c84SAndroid Build Coastguard Worker 
24*cf5a6c84SAndroid Build Coastguard Worker char dialog_input_result[MAX_LEN + 1];
25*cf5a6c84SAndroid Build Coastguard Worker 
26*cf5a6c84SAndroid Build Coastguard Worker /*
27*cf5a6c84SAndroid Build Coastguard Worker  *  Print the termination buttons
28*cf5a6c84SAndroid Build Coastguard Worker  */
print_buttons(WINDOW * dialog,int height,int width,int selected)29*cf5a6c84SAndroid Build Coastguard Worker static void print_buttons(WINDOW * dialog, int height, int width, int selected)
30*cf5a6c84SAndroid Build Coastguard Worker {
31*cf5a6c84SAndroid Build Coastguard Worker 	int x = width / 2 - 11;
32*cf5a6c84SAndroid Build Coastguard Worker 	int y = height - 2;
33*cf5a6c84SAndroid Build Coastguard Worker 
34*cf5a6c84SAndroid Build Coastguard Worker 	print_button(dialog, "  Ok  ", y, x, selected == 0);
35*cf5a6c84SAndroid Build Coastguard Worker 	print_button(dialog, " Help ", y, x + 14, selected == 1);
36*cf5a6c84SAndroid Build Coastguard Worker 
37*cf5a6c84SAndroid Build Coastguard Worker 	wmove(dialog, y, x + 1 + 14 * selected);
38*cf5a6c84SAndroid Build Coastguard Worker 	wrefresh(dialog);
39*cf5a6c84SAndroid Build Coastguard Worker }
40*cf5a6c84SAndroid Build Coastguard Worker 
41*cf5a6c84SAndroid Build Coastguard Worker /*
42*cf5a6c84SAndroid Build Coastguard Worker  * Display a dialog box for inputing a string
43*cf5a6c84SAndroid Build Coastguard Worker  */
dialog_inputbox(const char * title,const char * prompt,int height,int width,const char * init)44*cf5a6c84SAndroid Build Coastguard Worker int dialog_inputbox(const char *title, const char *prompt, int height, int width,
45*cf5a6c84SAndroid Build Coastguard Worker                     const char *init)
46*cf5a6c84SAndroid Build Coastguard Worker {
47*cf5a6c84SAndroid Build Coastguard Worker 	int i, x, y, box_y, box_x, box_width;
48*cf5a6c84SAndroid Build Coastguard Worker 	int input_x = 0, scroll = 0, key = 0, button = -1;
49*cf5a6c84SAndroid Build Coastguard Worker 	char *instr = dialog_input_result;
50*cf5a6c84SAndroid Build Coastguard Worker 	WINDOW *dialog;
51*cf5a6c84SAndroid Build Coastguard Worker 
52*cf5a6c84SAndroid Build Coastguard Worker 	if (!init)
53*cf5a6c84SAndroid Build Coastguard Worker 		instr[0] = '\0';
54*cf5a6c84SAndroid Build Coastguard Worker 	else
55*cf5a6c84SAndroid Build Coastguard Worker 		strcpy(instr, init);
56*cf5a6c84SAndroid Build Coastguard Worker 
57*cf5a6c84SAndroid Build Coastguard Worker do_resize:
58*cf5a6c84SAndroid Build Coastguard Worker 	if (getmaxy(stdscr) <= (height - 2))
59*cf5a6c84SAndroid Build Coastguard Worker 		return -ERRDISPLAYTOOSMALL;
60*cf5a6c84SAndroid Build Coastguard Worker 	if (getmaxx(stdscr) <= (width - 2))
61*cf5a6c84SAndroid Build Coastguard Worker 		return -ERRDISPLAYTOOSMALL;
62*cf5a6c84SAndroid Build Coastguard Worker 
63*cf5a6c84SAndroid Build Coastguard Worker 	/* center dialog box on screen */
64*cf5a6c84SAndroid Build Coastguard Worker 	x = (COLS - width) / 2;
65*cf5a6c84SAndroid Build Coastguard Worker 	y = (LINES - height) / 2;
66*cf5a6c84SAndroid Build Coastguard Worker 
67*cf5a6c84SAndroid Build Coastguard Worker 	draw_shadow(stdscr, y, x, height, width);
68*cf5a6c84SAndroid Build Coastguard Worker 
69*cf5a6c84SAndroid Build Coastguard Worker 	dialog = newwin(height, width, y, x);
70*cf5a6c84SAndroid Build Coastguard Worker 	keypad(dialog, TRUE);
71*cf5a6c84SAndroid Build Coastguard Worker 
72*cf5a6c84SAndroid Build Coastguard Worker 	draw_box(dialog, 0, 0, height, width,
73*cf5a6c84SAndroid Build Coastguard Worker 		 dlg.dialog.atr, dlg.border.atr);
74*cf5a6c84SAndroid Build Coastguard Worker 	wattrset(dialog, dlg.border.atr);
75*cf5a6c84SAndroid Build Coastguard Worker 	mvwaddch(dialog, height - 3, 0, ACS_LTEE);
76*cf5a6c84SAndroid Build Coastguard Worker 	for (i = 0; i < width - 2; i++)
77*cf5a6c84SAndroid Build Coastguard Worker 		waddch(dialog, ACS_HLINE);
78*cf5a6c84SAndroid Build Coastguard Worker 	wattrset(dialog, dlg.dialog.atr);
79*cf5a6c84SAndroid Build Coastguard Worker 	waddch(dialog, ACS_RTEE);
80*cf5a6c84SAndroid Build Coastguard Worker 
81*cf5a6c84SAndroid Build Coastguard Worker 	print_title(dialog, title, width);
82*cf5a6c84SAndroid Build Coastguard Worker 
83*cf5a6c84SAndroid Build Coastguard Worker 	wattrset(dialog, dlg.dialog.atr);
84*cf5a6c84SAndroid Build Coastguard Worker 	print_autowrap(dialog, prompt, width - 2, 1, 3);
85*cf5a6c84SAndroid Build Coastguard Worker 
86*cf5a6c84SAndroid Build Coastguard Worker 	/* Draw the input field box */
87*cf5a6c84SAndroid Build Coastguard Worker 	box_width = width - 6;
88*cf5a6c84SAndroid Build Coastguard Worker 	getyx(dialog, y, x);
89*cf5a6c84SAndroid Build Coastguard Worker 	box_y = y + 2;
90*cf5a6c84SAndroid Build Coastguard Worker 	box_x = (width - box_width) / 2;
91*cf5a6c84SAndroid Build Coastguard Worker 	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
92*cf5a6c84SAndroid Build Coastguard Worker 		 dlg.border.atr, dlg.dialog.atr);
93*cf5a6c84SAndroid Build Coastguard Worker 
94*cf5a6c84SAndroid Build Coastguard Worker 	print_buttons(dialog, height, width, 0);
95*cf5a6c84SAndroid Build Coastguard Worker 
96*cf5a6c84SAndroid Build Coastguard Worker 	/* Set up the initial value */
97*cf5a6c84SAndroid Build Coastguard Worker 	wmove(dialog, box_y, box_x);
98*cf5a6c84SAndroid Build Coastguard Worker 	wattrset(dialog, dlg.inputbox.atr);
99*cf5a6c84SAndroid Build Coastguard Worker 
100*cf5a6c84SAndroid Build Coastguard Worker 	input_x = strlen(instr);
101*cf5a6c84SAndroid Build Coastguard Worker 
102*cf5a6c84SAndroid Build Coastguard Worker 	if (input_x >= box_width) {
103*cf5a6c84SAndroid Build Coastguard Worker 		scroll = input_x - box_width + 1;
104*cf5a6c84SAndroid Build Coastguard Worker 		input_x = box_width - 1;
105*cf5a6c84SAndroid Build Coastguard Worker 		for (i = 0; i < box_width - 1; i++)
106*cf5a6c84SAndroid Build Coastguard Worker 			waddch(dialog, instr[scroll + i]);
107*cf5a6c84SAndroid Build Coastguard Worker 	} else {
108*cf5a6c84SAndroid Build Coastguard Worker 		waddstr(dialog, instr);
109*cf5a6c84SAndroid Build Coastguard Worker 	}
110*cf5a6c84SAndroid Build Coastguard Worker 
111*cf5a6c84SAndroid Build Coastguard Worker 	wmove(dialog, box_y, box_x + input_x);
112*cf5a6c84SAndroid Build Coastguard Worker 
113*cf5a6c84SAndroid Build Coastguard Worker 	wrefresh(dialog);
114*cf5a6c84SAndroid Build Coastguard Worker 
115*cf5a6c84SAndroid Build Coastguard Worker 	while (key != KEY_ESC) {
116*cf5a6c84SAndroid Build Coastguard Worker 		key = wgetch(dialog);
117*cf5a6c84SAndroid Build Coastguard Worker 
118*cf5a6c84SAndroid Build Coastguard Worker 		if (button == -1) {	/* Input box selected */
119*cf5a6c84SAndroid Build Coastguard Worker 			switch (key) {
120*cf5a6c84SAndroid Build Coastguard Worker 			case TAB:
121*cf5a6c84SAndroid Build Coastguard Worker 			case KEY_UP:
122*cf5a6c84SAndroid Build Coastguard Worker 			case KEY_DOWN:
123*cf5a6c84SAndroid Build Coastguard Worker 				break;
124*cf5a6c84SAndroid Build Coastguard Worker 			case KEY_LEFT:
125*cf5a6c84SAndroid Build Coastguard Worker 				continue;
126*cf5a6c84SAndroid Build Coastguard Worker 			case KEY_RIGHT:
127*cf5a6c84SAndroid Build Coastguard Worker 				continue;
128*cf5a6c84SAndroid Build Coastguard Worker 			case KEY_BACKSPACE:
129*cf5a6c84SAndroid Build Coastguard Worker 			case 127:
130*cf5a6c84SAndroid Build Coastguard Worker 				if (input_x || scroll) {
131*cf5a6c84SAndroid Build Coastguard Worker 					wattrset(dialog, dlg.inputbox.atr);
132*cf5a6c84SAndroid Build Coastguard Worker 					if (!input_x) {
133*cf5a6c84SAndroid Build Coastguard Worker 						scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
134*cf5a6c84SAndroid Build Coastguard Worker 						wmove(dialog, box_y, box_x);
135*cf5a6c84SAndroid Build Coastguard Worker 						for (i = 0; i < box_width; i++)
136*cf5a6c84SAndroid Build Coastguard Worker 							waddch(dialog,
137*cf5a6c84SAndroid Build Coastguard Worker 							       instr[scroll + input_x + i] ?
138*cf5a6c84SAndroid Build Coastguard Worker 							       instr[scroll + input_x + i] : ' ');
139*cf5a6c84SAndroid Build Coastguard Worker 						input_x = strlen(instr) - scroll;
140*cf5a6c84SAndroid Build Coastguard Worker 					} else
141*cf5a6c84SAndroid Build Coastguard Worker 						input_x--;
142*cf5a6c84SAndroid Build Coastguard Worker 					instr[scroll + input_x] = '\0';
143*cf5a6c84SAndroid Build Coastguard Worker 					mvwaddch(dialog, box_y, input_x + box_x, ' ');
144*cf5a6c84SAndroid Build Coastguard Worker 					wmove(dialog, box_y, input_x + box_x);
145*cf5a6c84SAndroid Build Coastguard Worker 					wrefresh(dialog);
146*cf5a6c84SAndroid Build Coastguard Worker 				}
147*cf5a6c84SAndroid Build Coastguard Worker 				continue;
148*cf5a6c84SAndroid Build Coastguard Worker 			default:
149*cf5a6c84SAndroid Build Coastguard Worker 				if (key < 0x100 && isprint(key)) {
150*cf5a6c84SAndroid Build Coastguard Worker 					if (scroll + input_x < MAX_LEN) {
151*cf5a6c84SAndroid Build Coastguard Worker 						wattrset(dialog, dlg.inputbox.atr);
152*cf5a6c84SAndroid Build Coastguard Worker 						instr[scroll + input_x] = key;
153*cf5a6c84SAndroid Build Coastguard Worker 						instr[scroll + input_x + 1] = '\0';
154*cf5a6c84SAndroid Build Coastguard Worker 						if (input_x == box_width - 1) {
155*cf5a6c84SAndroid Build Coastguard Worker 							scroll++;
156*cf5a6c84SAndroid Build Coastguard Worker 							wmove(dialog, box_y, box_x);
157*cf5a6c84SAndroid Build Coastguard Worker 							for (i = 0; i < box_width - 1; i++)
158*cf5a6c84SAndroid Build Coastguard Worker 								waddch(dialog, instr [scroll + i]);
159*cf5a6c84SAndroid Build Coastguard Worker 						} else {
160*cf5a6c84SAndroid Build Coastguard Worker 							wmove(dialog, box_y, input_x++ + box_x);
161*cf5a6c84SAndroid Build Coastguard Worker 							waddch(dialog, key);
162*cf5a6c84SAndroid Build Coastguard Worker 						}
163*cf5a6c84SAndroid Build Coastguard Worker 						wrefresh(dialog);
164*cf5a6c84SAndroid Build Coastguard Worker 					} else
165*cf5a6c84SAndroid Build Coastguard Worker 						flash();	/* Alarm user about overflow */
166*cf5a6c84SAndroid Build Coastguard Worker 					continue;
167*cf5a6c84SAndroid Build Coastguard Worker 				}
168*cf5a6c84SAndroid Build Coastguard Worker 			}
169*cf5a6c84SAndroid Build Coastguard Worker 		}
170*cf5a6c84SAndroid Build Coastguard Worker 		switch (key) {
171*cf5a6c84SAndroid Build Coastguard Worker 		case 'O':
172*cf5a6c84SAndroid Build Coastguard Worker 		case 'o':
173*cf5a6c84SAndroid Build Coastguard Worker 			delwin(dialog);
174*cf5a6c84SAndroid Build Coastguard Worker 			return 0;
175*cf5a6c84SAndroid Build Coastguard Worker 		case 'H':
176*cf5a6c84SAndroid Build Coastguard Worker 		case 'h':
177*cf5a6c84SAndroid Build Coastguard Worker 			delwin(dialog);
178*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
179*cf5a6c84SAndroid Build Coastguard Worker 		case KEY_UP:
180*cf5a6c84SAndroid Build Coastguard Worker 		case KEY_LEFT:
181*cf5a6c84SAndroid Build Coastguard Worker 			switch (button) {
182*cf5a6c84SAndroid Build Coastguard Worker 			case -1:
183*cf5a6c84SAndroid Build Coastguard Worker 				button = 1;	/* Indicates "Cancel" button is selected */
184*cf5a6c84SAndroid Build Coastguard Worker 				print_buttons(dialog, height, width, 1);
185*cf5a6c84SAndroid Build Coastguard Worker 				break;
186*cf5a6c84SAndroid Build Coastguard Worker 			case 0:
187*cf5a6c84SAndroid Build Coastguard Worker 				button = -1;	/* Indicates input box is selected */
188*cf5a6c84SAndroid Build Coastguard Worker 				print_buttons(dialog, height, width, 0);
189*cf5a6c84SAndroid Build Coastguard Worker 				wmove(dialog, box_y, box_x + input_x);
190*cf5a6c84SAndroid Build Coastguard Worker 				wrefresh(dialog);
191*cf5a6c84SAndroid Build Coastguard Worker 				break;
192*cf5a6c84SAndroid Build Coastguard Worker 			case 1:
193*cf5a6c84SAndroid Build Coastguard Worker 				button = 0;	/* Indicates "OK" button is selected */
194*cf5a6c84SAndroid Build Coastguard Worker 				print_buttons(dialog, height, width, 0);
195*cf5a6c84SAndroid Build Coastguard Worker 				break;
196*cf5a6c84SAndroid Build Coastguard Worker 			}
197*cf5a6c84SAndroid Build Coastguard Worker 			break;
198*cf5a6c84SAndroid Build Coastguard Worker 		case TAB:
199*cf5a6c84SAndroid Build Coastguard Worker 		case KEY_DOWN:
200*cf5a6c84SAndroid Build Coastguard Worker 		case KEY_RIGHT:
201*cf5a6c84SAndroid Build Coastguard Worker 			switch (button) {
202*cf5a6c84SAndroid Build Coastguard Worker 			case -1:
203*cf5a6c84SAndroid Build Coastguard Worker 				button = 0;	/* Indicates "OK" button is selected */
204*cf5a6c84SAndroid Build Coastguard Worker 				print_buttons(dialog, height, width, 0);
205*cf5a6c84SAndroid Build Coastguard Worker 				break;
206*cf5a6c84SAndroid Build Coastguard Worker 			case 0:
207*cf5a6c84SAndroid Build Coastguard Worker 				button = 1;	/* Indicates "Cancel" button is selected */
208*cf5a6c84SAndroid Build Coastguard Worker 				print_buttons(dialog, height, width, 1);
209*cf5a6c84SAndroid Build Coastguard Worker 				break;
210*cf5a6c84SAndroid Build Coastguard Worker 			case 1:
211*cf5a6c84SAndroid Build Coastguard Worker 				button = -1;	/* Indicates input box is selected */
212*cf5a6c84SAndroid Build Coastguard Worker 				print_buttons(dialog, height, width, 0);
213*cf5a6c84SAndroid Build Coastguard Worker 				wmove(dialog, box_y, box_x + input_x);
214*cf5a6c84SAndroid Build Coastguard Worker 				wrefresh(dialog);
215*cf5a6c84SAndroid Build Coastguard Worker 				break;
216*cf5a6c84SAndroid Build Coastguard Worker 			}
217*cf5a6c84SAndroid Build Coastguard Worker 			break;
218*cf5a6c84SAndroid Build Coastguard Worker 		case ' ':
219*cf5a6c84SAndroid Build Coastguard Worker 		case '\n':
220*cf5a6c84SAndroid Build Coastguard Worker 			delwin(dialog);
221*cf5a6c84SAndroid Build Coastguard Worker 			return (button == -1 ? 0 : button);
222*cf5a6c84SAndroid Build Coastguard Worker 		case 'X':
223*cf5a6c84SAndroid Build Coastguard Worker 		case 'x':
224*cf5a6c84SAndroid Build Coastguard Worker 			key = KEY_ESC;
225*cf5a6c84SAndroid Build Coastguard Worker 			break;
226*cf5a6c84SAndroid Build Coastguard Worker 		case KEY_ESC:
227*cf5a6c84SAndroid Build Coastguard Worker 			key = on_key_esc(dialog);
228*cf5a6c84SAndroid Build Coastguard Worker 			break;
229*cf5a6c84SAndroid Build Coastguard Worker 		case KEY_RESIZE:
230*cf5a6c84SAndroid Build Coastguard Worker 			delwin(dialog);
231*cf5a6c84SAndroid Build Coastguard Worker 			on_key_resize();
232*cf5a6c84SAndroid Build Coastguard Worker 			goto do_resize;
233*cf5a6c84SAndroid Build Coastguard Worker 		}
234*cf5a6c84SAndroid Build Coastguard Worker 	}
235*cf5a6c84SAndroid Build Coastguard Worker 
236*cf5a6c84SAndroid Build Coastguard Worker 	delwin(dialog);
237*cf5a6c84SAndroid Build Coastguard Worker 	return KEY_ESC;		/* ESC pressed */
238*cf5a6c84SAndroid Build Coastguard Worker }
239