Added Debianization stuff.
[cboard.git] / src / input.c
blob1f2406c48a3b4d08cd30d070019aa3a86e29fbad
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2002-2006 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdarg.h>
22 #include <ctype.h>
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #ifdef HAVE_FORM_H
29 #include <form.h>
30 #endif
32 #ifdef HAVE_PANEL_H
33 #include <panel.h>
34 #endif
36 #include "chess.h"
37 #include "conf.h"
38 #include "colors.h"
39 #include "window.h"
40 #include "strings.h"
41 #include "misc.h"
42 #include "input.h"
44 #ifdef WITH_DMALLOC
45 #include <dmalloc.h>
46 #endif
48 const char *inputhelp[] = {
49 "UP/DOWN/LEFT/RIGHT - position cursor",
50 " CTRL-A - move cursor to the beginning of line",
51 " CTRL-E - move cursor to the end of line",
52 " CTRL-B - move cursor to previous word",
53 " CTRL-W - move cursor to next word",
54 " CTRL-X - delete word under cursor",
55 " CTRL-K - delete from cursor to end of line",
56 " CTRL-U - clear entire input field",
57 " BACKSPACE - delete previous character",
58 " ESCAPE - quit without changes",
59 " ENTER - quit with changes",
60 NULL
63 static bool validate_pgn_tag_name(int c, const void *arg)
65 if (!isalnum(c) && c != '_')
66 return FALSE;
68 return TRUE;
71 static bool validate_pgn_date(int c, const void *arg)
73 if (!isdigit(c) && c != '.' && c != '?')
74 return FALSE;
76 return TRUE;
79 static bool validate_pgn_round(int c, const void *arg)
81 if (!isdigit(c) && c != '.' && c != '-' && c != '?')
82 return FALSE;
84 return TRUE;
88 * This function prompts for input. The init argument is the initial value.
89 * The lines argument is how many lines the field is. If zero, then it is
90 * dynamically determined based on the init argument or INPUT_WIDTH if init is
91 * NULL.
93 * The reset argument is whether pressing ESC returns the initial value or
94 * NULL.
96 * The extra_help argument is an extra line of help prompt normally used with
97 * the custom_func argument. The custom_func argument is a pointer to a
98 * function of type void which takes one pointer-to-void argument. This
99 * function is called when the ckey argument is pressed.
101 * The type argument is the type of validation for the input defined in
102 * common.h. Remaining arguments are values for the type argument. See
103 * field_type(3X) for validation types.
105 * FIXME form validation is buggy (integers).
107 char *get_input(const char *title, const char *init, int lines, int reset,
108 const char *extra_help, char *(*custom_func)(void *), void *arg,
109 chtype ckey, int type, ...)
111 WINDOW *win, *swin;
112 PANEL *panel;
113 FIELD *fields[2];
114 FORM *form;
115 int width, len;
116 int y, x;
117 int i, n;
118 static char dst[MAX_PGN_LINE_LEN];
119 char *tmp;
120 va_list ap;
121 FIELDTYPE *TYPE_PGN_TAG_NAME;
122 FIELDTYPE *TYPE_PGN_DATE;
123 FIELDTYPE *TYPE_PGN_ROUND;
124 int quit = 0;
126 bzero(dst, sizeof(dst));
128 len = strlen(title);
129 width = (len + 4 > INPUT_WIDTH && len + 4 < COLS - 2) ?
130 len + 4 : INPUT_WIDTH;
132 fields[0] = new_field((lines) ? lines : sizeof(dst) / width + 1,
133 width - 2, 0, 0, 0, 0);
135 if (lines == 1)
136 field_opts_off(fields[0], O_STATIC);
138 TYPE_PGN_TAG_NAME = new_fieldtype(NULL, validate_pgn_tag_name);
139 TYPE_PGN_DATE = new_fieldtype(NULL, validate_pgn_date);
140 TYPE_PGN_ROUND = new_fieldtype(NULL, validate_pgn_round);
142 va_start(ap, type);
144 switch (type) {
145 case FIELD_TYPE_PGN_ROUND:
146 set_field_type(fields[0], TYPE_PGN_ROUND);
147 break;
148 case FIELD_TYPE_PGN_DATE:
149 set_field_type(fields[0], TYPE_PGN_DATE);
150 break;
151 case FIELD_TYPE_PGN_TAG_NAME:
152 set_field_type(fields[0], TYPE_PGN_TAG_NAME);
153 break;
154 case FIELD_TYPE_ALNUM:
155 set_field_type(fields[0], TYPE_ALNUM, va_arg(ap, int));
156 break;
157 case FIELD_TYPE_ALPHA:
158 set_field_type(fields[0], TYPE_ALPHA, va_arg(ap, int));
159 break;
160 case FIELD_TYPE_ENUM:
161 set_field_type(fields[0], TYPE_ENUM, va_arg(ap, char **),
162 va_arg(ap, int), va_arg(ap, int));
163 break;
164 case FIELD_TYPE_INTEGER:
165 set_field_type(fields[0], TYPE_INTEGER, va_arg(ap, int),
166 va_arg(ap, long), va_arg(ap, long));
167 break;
168 case FIELD_TYPE_NUMERIC:
169 set_field_type(fields[0], TYPE_NUMERIC, va_arg(ap, int),
170 va_arg(ap, double), va_arg(ap, double));
171 break;
172 case FIELD_TYPE_REGEXP:
173 set_field_type(fields[0], TYPE_REGEXP, va_arg(ap, char *));
174 break;
175 case FIELD_TYPE_IPV4:
176 set_field_type(fields[0], TYPE_IPV4);
177 break;
178 default:
179 break;
182 va_end(ap);
184 if (init)
185 set_field_buffer(fields[0], 0, init);
187 field_opts_off(fields[0], O_BLANK|O_AUTOSKIP);
188 fields[1] = NULL;
189 form = new_form(fields);
190 form_opts_off(form, O_BS_OVERLOAD);
192 scale_form(form, &y, &x);
194 win = newwin((extra_help) ? y + 5 : y + 4, x + 2,
195 CALCPOSY(((extra_help) ? y + 5 : y + 4)), CALCPOSX(x));
196 set_form_win(form, win);
197 swin = derwin(win, y, x, 2, 1);
198 set_form_sub(form, swin);
199 post_form(form);
200 nl();
201 noecho();
202 cbreak();
203 keypad(win, TRUE);
204 curs_set(1);
205 panel = new_panel(win);
206 wbkgd(win, CP_INPUT_WINDOW);
207 draw_window_title(win, title, width, CP_INPUT_TITLE, CP_INPUT_BORDER);
209 if (extra_help)
210 draw_prompt(win, y + 2, width, extra_help, CP_INPUT_PROMPT);
212 draw_prompt(win, (extra_help) ? y + 3 : y + 2, width, INPUT_HELP_PROMPT,
213 CP_INPUT_PROMPT);
215 form_driver(form, REQ_END_FIELD);
217 while (1) {
218 chtype c;
220 update_panels();
221 doupdate();
223 c = wgetch(win);
225 if (c == ckey && custom_func) {
226 form_driver(form, REQ_VALIDATION);
228 if ((tmp = custom_func(arg)) != NULL) {
229 set_field_buffer(fields[0], 0, tmp);
230 form_driver(form, REQ_END_LINE);
233 continue;
236 switch (c) {
237 case CTRL('X'):
238 form_driver(form, REQ_DEL_WORD);
239 break;
240 case CTRL('B'):
241 form_driver(form, REQ_PREV_WORD);
242 break;
243 case CTRL('W'):
244 form_driver(form, REQ_NEXT_WORD);
245 break;
246 case CTRL('A'):
247 form_driver(form, REQ_BEG_LINE);
248 break;
249 case CTRL('E'):
250 form_driver(form, REQ_END_LINE);
251 break;
252 case CTRL('K'):
253 form_driver(form, REQ_CLR_EOL);
254 break;
255 case CTRL('U'):
256 form_driver(form, REQ_CLR_FIELD);
257 break;
258 case KEY_F(1):
259 help(INPUT_HELP_TITLE, ANYKEY, inputhelp);
260 break;
261 case KEY_LEFT:
262 form_driver(form, REQ_LEFT_CHAR);
263 break;
264 case KEY_RIGHT:
265 form_driver(form, REQ_RIGHT_CHAR);
266 break;
267 case KEY_UP:
268 form_driver(form, REQ_UP_CHAR);
269 break;
270 case KEY_DOWN:
271 form_driver(form, REQ_DOWN_CHAR);
272 break;
273 case '\010':
274 case KEY_BACKSPACE:
275 form_driver(form, REQ_DEL_PREV);
276 break;
277 case '\n':
278 goto done;
279 break;
280 case KEY_ESCAPE:
281 quit = 1;
282 goto done;
283 break;
284 default:
285 form_driver(form, (c & A_CHARTEXT));
286 form_driver(form, REQ_VALIDATION);
287 break;
291 done:
292 if (quit) {
293 if (reset) {
294 dst[0] = 0;
295 goto cleanup;
297 else
298 set_field_buffer(fields[0], 0, init);
301 form_driver(form, REQ_VALIDATION);
302 tmp = trim(field_buffer(fields[0], 0));
304 /* Remove multiple whitespace. Happens on a multiline field. */
305 if (tmp) {
306 for (i = 0, n = 0; i < strlen(tmp); i++) {
307 if (isspace(tmp[i]) && isspace(tmp[i + 1]))
308 continue;
310 dst[n++] = tmp[i];
313 dst[n] = 0;
315 else
316 dst[0] = 0;
318 dst[sizeof(dst) - 1] = 0;
320 cleanup:
321 unpost_form(form);
322 free_form(form);
324 for (i = 0; fields[i]; i++)
325 free_field(fields[i]);
327 del_panel(panel);
328 delwin(swin);
329 delwin(win);
330 free_fieldtype(TYPE_PGN_TAG_NAME);
331 free_fieldtype(TYPE_PGN_DATE);
332 free_fieldtype(TYPE_PGN_ROUND);
333 noecho();
334 nonl();
335 curs_set(0);
336 tmp = dst;
337 return (dst[0]) ? dst : NULL;