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