xref: /freebsd/contrib/dialog/inputbox.c (revision 4c8945a06b01a5c8122cdeb402af36bb46a06acc)
1*4c8945a0SNathan Whitehorn /*
2*4c8945a0SNathan Whitehorn  *  $Id: inputbox.c,v 1.64 2010/01/19 01:03:39 tom Exp $
3*4c8945a0SNathan Whitehorn  *
4*4c8945a0SNathan Whitehorn  * inputbox.c -- implements the input box
5*4c8945a0SNathan Whitehorn  *
6*4c8945a0SNathan Whitehorn  * Copyright 2000-2009,2010 Thomas E. Dickey
7*4c8945a0SNathan Whitehorn  *
8*4c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
9*4c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
10*4c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
11*4c8945a0SNathan Whitehorn  *
12*4c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
13*4c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
14*4c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*4c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
16*4c8945a0SNathan Whitehorn  *
17*4c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
18*4c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
19*4c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
20*4c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
21*4c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
22*4c8945a0SNathan Whitehorn  *
23*4c8945a0SNathan Whitehorn  *  An earlier version of this program lists as authors:
24*4c8945a0SNathan Whitehorn  *	Savio Lam (lam836@cs.cuhk.hk)
25*4c8945a0SNathan Whitehorn  */
26*4c8945a0SNathan Whitehorn 
27*4c8945a0SNathan Whitehorn #include <dialog.h>
28*4c8945a0SNathan Whitehorn #include <dlg_keys.h>
29*4c8945a0SNathan Whitehorn 
30*4c8945a0SNathan Whitehorn #define sTEXT -1
31*4c8945a0SNathan Whitehorn 
32*4c8945a0SNathan Whitehorn #define NAVIGATE_BINDINGS \
33*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	KEY_DOWN ), \
34*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	KEY_RIGHT ), \
35*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_NEXT,	TAB ), \
36*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_BTAB ), \
37*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_LEFT ), \
38*4c8945a0SNathan Whitehorn 	DLG_KEYS_DATA( DLGK_FIELD_PREV,	KEY_UP )
39*4c8945a0SNathan Whitehorn 
40*4c8945a0SNathan Whitehorn /*
41*4c8945a0SNathan Whitehorn  * Display a dialog box for entering a string
42*4c8945a0SNathan Whitehorn  */
43*4c8945a0SNathan Whitehorn int
44*4c8945a0SNathan Whitehorn dialog_inputbox(const char *title, const char *cprompt, int height, int width,
45*4c8945a0SNathan Whitehorn 		const char *init, const int password)
46*4c8945a0SNathan Whitehorn {
47*4c8945a0SNathan Whitehorn     /* *INDENT-OFF* */
48*4c8945a0SNathan Whitehorn     static DLG_KEYS_BINDING binding[] = {
49*4c8945a0SNathan Whitehorn 	ENTERKEY_BINDINGS,
50*4c8945a0SNathan Whitehorn 	NAVIGATE_BINDINGS,
51*4c8945a0SNathan Whitehorn 	END_KEYS_BINDING
52*4c8945a0SNathan Whitehorn     };
53*4c8945a0SNathan Whitehorn     static DLG_KEYS_BINDING binding2[] = {
54*4c8945a0SNathan Whitehorn 	INPUTSTR_BINDINGS,
55*4c8945a0SNathan Whitehorn 	ENTERKEY_BINDINGS,
56*4c8945a0SNathan Whitehorn 	NAVIGATE_BINDINGS,
57*4c8945a0SNathan Whitehorn 	END_KEYS_BINDING
58*4c8945a0SNathan Whitehorn     };
59*4c8945a0SNathan Whitehorn     /* *INDENT-ON* */
60*4c8945a0SNathan Whitehorn 
61*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
62*4c8945a0SNathan Whitehorn     int old_height = height;
63*4c8945a0SNathan Whitehorn     int old_width = width;
64*4c8945a0SNathan Whitehorn #endif
65*4c8945a0SNathan Whitehorn     int xorg, yorg;
66*4c8945a0SNathan Whitehorn     int x, y, box_y, box_x, box_width;
67*4c8945a0SNathan Whitehorn     int show_buttons;
68*4c8945a0SNathan Whitehorn     int col_offset = 0;
69*4c8945a0SNathan Whitehorn     int chr_offset = 0;
70*4c8945a0SNathan Whitehorn     int key, fkey, code;
71*4c8945a0SNathan Whitehorn     int result = DLG_EXIT_UNKNOWN;
72*4c8945a0SNathan Whitehorn     int state;
73*4c8945a0SNathan Whitehorn     int first;
74*4c8945a0SNathan Whitehorn     char *input;
75*4c8945a0SNathan Whitehorn     WINDOW *dialog;
76*4c8945a0SNathan Whitehorn     WINDOW *editor;
77*4c8945a0SNathan Whitehorn     char *prompt = dlg_strclone(cprompt);
78*4c8945a0SNathan Whitehorn     const char **buttons = dlg_ok_labels();
79*4c8945a0SNathan Whitehorn 
80*4c8945a0SNathan Whitehorn     dlg_does_output();
81*4c8945a0SNathan Whitehorn 
82*4c8945a0SNathan Whitehorn     dlg_tab_correct_str(prompt);
83*4c8945a0SNathan Whitehorn 
84*4c8945a0SNathan Whitehorn     /* Set up the initial value */
85*4c8945a0SNathan Whitehorn     input = dlg_set_result(init);
86*4c8945a0SNathan Whitehorn 
87*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
88*4c8945a0SNathan Whitehorn   retry:
89*4c8945a0SNathan Whitehorn #endif
90*4c8945a0SNathan Whitehorn     show_buttons = TRUE;
91*4c8945a0SNathan Whitehorn     state = dialog_vars.defaultno ? dlg_defaultno_button() : sTEXT;
92*4c8945a0SNathan Whitehorn     first = (state == sTEXT);
93*4c8945a0SNathan Whitehorn     key = fkey = 0;
94*4c8945a0SNathan Whitehorn 
95*4c8945a0SNathan Whitehorn     if (init != NULL) {
96*4c8945a0SNathan Whitehorn 	dlg_auto_size(title, prompt, &height, &width, 5,
97*4c8945a0SNathan Whitehorn 		      MIN(MAX(dlg_count_columns(init) + 7, 26),
98*4c8945a0SNathan Whitehorn 			  SCOLS - (dialog_vars.begin_set ?
99*4c8945a0SNathan Whitehorn 				   dialog_vars.begin_x : 0)));
100*4c8945a0SNathan Whitehorn 	chr_offset = (int) strlen(init);
101*4c8945a0SNathan Whitehorn     } else {
102*4c8945a0SNathan Whitehorn 	dlg_auto_size(title, prompt, &height, &width, 5, 26);
103*4c8945a0SNathan Whitehorn     }
104*4c8945a0SNathan Whitehorn     dlg_button_layout(buttons, &width);
105*4c8945a0SNathan Whitehorn     dlg_print_size(height, width);
106*4c8945a0SNathan Whitehorn     dlg_ctl_size(height, width);
107*4c8945a0SNathan Whitehorn 
108*4c8945a0SNathan Whitehorn     xorg = dlg_box_x_ordinate(width);
109*4c8945a0SNathan Whitehorn     yorg = dlg_box_y_ordinate(height);
110*4c8945a0SNathan Whitehorn 
111*4c8945a0SNathan Whitehorn     dialog = dlg_new_window(height, width, yorg, xorg);
112*4c8945a0SNathan Whitehorn     dlg_register_window(dialog, "inputbox", binding);
113*4c8945a0SNathan Whitehorn     dlg_register_buttons(dialog, "inputbox", buttons);
114*4c8945a0SNathan Whitehorn 
115*4c8945a0SNathan Whitehorn     dlg_mouse_setbase(xorg, yorg);
116*4c8945a0SNathan Whitehorn 
117*4c8945a0SNathan Whitehorn     dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
118*4c8945a0SNathan Whitehorn     dlg_draw_bottom_box(dialog);
119*4c8945a0SNathan Whitehorn     dlg_draw_title(dialog, title);
120*4c8945a0SNathan Whitehorn 
121*4c8945a0SNathan Whitehorn     wattrset(dialog, dialog_attr);
122*4c8945a0SNathan Whitehorn     dlg_print_autowrap(dialog, prompt, height, width);
123*4c8945a0SNathan Whitehorn 
124*4c8945a0SNathan Whitehorn     /* Draw the input field box */
125*4c8945a0SNathan Whitehorn     box_width = width - 6;
126*4c8945a0SNathan Whitehorn     getyx(dialog, y, x);
127*4c8945a0SNathan Whitehorn     box_y = y + 2;
128*4c8945a0SNathan Whitehorn     box_x = (width - box_width) / 2;
129*4c8945a0SNathan Whitehorn     dlg_mouse_mkregion(y + 1, box_x - 1, 3, box_width + 2, 'i');
130*4c8945a0SNathan Whitehorn     dlg_draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
131*4c8945a0SNathan Whitehorn 		 border_attr, dialog_attr);
132*4c8945a0SNathan Whitehorn 
133*4c8945a0SNathan Whitehorn     /* Make a window for the input-field, to associate bindings */
134*4c8945a0SNathan Whitehorn     editor = dlg_sub_window(dialog, 1, box_width, yorg + box_y, xorg + box_x);
135*4c8945a0SNathan Whitehorn     dlg_register_window(editor, "inputbox", binding2);
136*4c8945a0SNathan Whitehorn 
137*4c8945a0SNathan Whitehorn     while (result == DLG_EXIT_UNKNOWN) {
138*4c8945a0SNathan Whitehorn 	int edit = 0;
139*4c8945a0SNathan Whitehorn 
140*4c8945a0SNathan Whitehorn 	/*
141*4c8945a0SNathan Whitehorn 	 * The last field drawn determines where the cursor is shown:
142*4c8945a0SNathan Whitehorn 	 */
143*4c8945a0SNathan Whitehorn 	if (show_buttons) {
144*4c8945a0SNathan Whitehorn 	    show_buttons = FALSE;
145*4c8945a0SNathan Whitehorn 	    col_offset = dlg_edit_offset(input, chr_offset, box_width);
146*4c8945a0SNathan Whitehorn 	    (void) wmove(dialog, box_y, box_x + col_offset);
147*4c8945a0SNathan Whitehorn 	    dlg_draw_buttons(dialog, height - 2, 0, buttons, state, FALSE, width);
148*4c8945a0SNathan Whitehorn 	}
149*4c8945a0SNathan Whitehorn 
150*4c8945a0SNathan Whitehorn 	if (!first) {
151*4c8945a0SNathan Whitehorn 	    key = dlg_mouse_wgetch((state == sTEXT) ? editor : dialog, &fkey);
152*4c8945a0SNathan Whitehorn 	    if (dlg_result_key(key, fkey, &result))
153*4c8945a0SNathan Whitehorn 		break;
154*4c8945a0SNathan Whitehorn 	}
155*4c8945a0SNathan Whitehorn 
156*4c8945a0SNathan Whitehorn 	/*
157*4c8945a0SNathan Whitehorn 	 * Handle mouse clicks first, since we want to know if this is a button,
158*4c8945a0SNathan Whitehorn 	 * or something that dlg_edit_string() should handle.
159*4c8945a0SNathan Whitehorn 	 */
160*4c8945a0SNathan Whitehorn 	if (fkey
161*4c8945a0SNathan Whitehorn 	    && is_DLGK_MOUSE(key)
162*4c8945a0SNathan Whitehorn 	    && (code = dlg_ok_buttoncode(key - M_EVENT)) >= 0) {
163*4c8945a0SNathan Whitehorn 	    result = code;
164*4c8945a0SNathan Whitehorn 	    continue;
165*4c8945a0SNathan Whitehorn 	}
166*4c8945a0SNathan Whitehorn 
167*4c8945a0SNathan Whitehorn 	if (state == sTEXT) {	/* Input box selected */
168*4c8945a0SNathan Whitehorn 	    edit = dlg_edit_string(input, &chr_offset, key, fkey, first);
169*4c8945a0SNathan Whitehorn 
170*4c8945a0SNathan Whitehorn 	    if (edit) {
171*4c8945a0SNathan Whitehorn 		dlg_show_string(dialog, input, chr_offset, inputbox_attr,
172*4c8945a0SNathan Whitehorn 				box_y, box_x, box_width, password, first);
173*4c8945a0SNathan Whitehorn 		first = FALSE;
174*4c8945a0SNathan Whitehorn 		continue;
175*4c8945a0SNathan Whitehorn 	    } else if (first) {
176*4c8945a0SNathan Whitehorn 		first = FALSE;
177*4c8945a0SNathan Whitehorn 		continue;
178*4c8945a0SNathan Whitehorn 	    }
179*4c8945a0SNathan Whitehorn 	}
180*4c8945a0SNathan Whitehorn 
181*4c8945a0SNathan Whitehorn 	/* handle non-functionkeys */
182*4c8945a0SNathan Whitehorn 	if (!fkey && (code = dlg_char_to_button(key, buttons)) >= 0) {
183*4c8945a0SNathan Whitehorn 	    dlg_del_window(dialog);
184*4c8945a0SNathan Whitehorn 	    result = dlg_ok_buttoncode(code);
185*4c8945a0SNathan Whitehorn 	    continue;
186*4c8945a0SNathan Whitehorn 	}
187*4c8945a0SNathan Whitehorn 
188*4c8945a0SNathan Whitehorn 	/* handle functionkeys */
189*4c8945a0SNathan Whitehorn 	if (fkey) {
190*4c8945a0SNathan Whitehorn 	    switch (key) {
191*4c8945a0SNathan Whitehorn 	    case DLGK_MOUSE('i'):	/* mouse enter events */
192*4c8945a0SNathan Whitehorn 		state = 0;
193*4c8945a0SNathan Whitehorn 		/* FALLTHRU */
194*4c8945a0SNathan Whitehorn 	    case DLGK_FIELD_PREV:
195*4c8945a0SNathan Whitehorn 		show_buttons = TRUE;
196*4c8945a0SNathan Whitehorn 		state = dlg_prev_ok_buttonindex(state, sTEXT);
197*4c8945a0SNathan Whitehorn 		break;
198*4c8945a0SNathan Whitehorn 	    case DLGK_FIELD_NEXT:
199*4c8945a0SNathan Whitehorn 		show_buttons = TRUE;
200*4c8945a0SNathan Whitehorn 		state = dlg_next_ok_buttonindex(state, sTEXT);
201*4c8945a0SNathan Whitehorn 		break;
202*4c8945a0SNathan Whitehorn 	    case ' ':		/* FIXME: conflict with inputstr.c */
203*4c8945a0SNathan Whitehorn 	    case DLGK_ENTER:
204*4c8945a0SNathan Whitehorn 		dlg_del_window(dialog);
205*4c8945a0SNathan Whitehorn 		result = (state >= 0) ? dlg_ok_buttoncode(state) : DLG_EXIT_OK;
206*4c8945a0SNathan Whitehorn 		break;
207*4c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
208*4c8945a0SNathan Whitehorn 	    case KEY_RESIZE:
209*4c8945a0SNathan Whitehorn 		/* reset data */
210*4c8945a0SNathan Whitehorn 		height = old_height;
211*4c8945a0SNathan Whitehorn 		width = old_width;
212*4c8945a0SNathan Whitehorn 		/* repaint */
213*4c8945a0SNathan Whitehorn 		dlg_clear();
214*4c8945a0SNathan Whitehorn 		dlg_del_window(dialog);
215*4c8945a0SNathan Whitehorn 		refresh();
216*4c8945a0SNathan Whitehorn 		dlg_mouse_free_regions();
217*4c8945a0SNathan Whitehorn 		goto retry;
218*4c8945a0SNathan Whitehorn #endif
219*4c8945a0SNathan Whitehorn 	    default:
220*4c8945a0SNathan Whitehorn 		beep();
221*4c8945a0SNathan Whitehorn 		break;
222*4c8945a0SNathan Whitehorn 	    }
223*4c8945a0SNathan Whitehorn 	} else {
224*4c8945a0SNathan Whitehorn 	    beep();
225*4c8945a0SNathan Whitehorn 	}
226*4c8945a0SNathan Whitehorn     }
227*4c8945a0SNathan Whitehorn 
228*4c8945a0SNathan Whitehorn     dlg_unregister_window(editor);
229*4c8945a0SNathan Whitehorn     dlg_del_window(dialog);
230*4c8945a0SNathan Whitehorn     dlg_mouse_free_regions();
231*4c8945a0SNathan Whitehorn     free(prompt);
232*4c8945a0SNathan Whitehorn     return result;
233*4c8945a0SNathan Whitehorn }
234