1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2015 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
42 static struct input_history_s
{
44 struct input_history_s
*next
;
45 struct input_history_s
*prev
;
46 struct input_history_s
*head
;
47 } *input_history
[INPUT_HIST_MAX
];
49 static void add_input_history(int which
, const char *str
)
51 struct input_history_s
*new;
52 struct input_history_s
*p
= NULL
;
54 if (!str
|| !*str
|| which
< 0)
57 if (input_history
[which
])
58 for (p
= input_history
[which
]->head
; p
->next
; p
= p
->next
);
60 new = calloc(1, sizeof(struct input_history_s
));
62 fprintf(stderr
, "Out of core!\n");
66 new->str
= strdup(str
);
76 input_history
[which
] = p
? p
->next
: new;
79 static bool validate_pgn_tag_name(int c
, const void *arg
)
81 if (!isalnum(c
) && c
!= '_')
87 static bool validate_pgn_date(int c
, const void *arg
)
89 if (!isdigit(c
) && c
!= '.' && c
!= '?')
95 static bool validate_pgn_round(int c
, const void *arg
)
97 if (!isdigit(c
) && c
!= '.' && c
!= '-' && c
!= '?')
103 static bool validate_pgn_result(int c
, const void *arg
)
105 if (c
!= '1' && c
!= '0' && c
!= '2' && c
!= '*' && c
!= '/' && c
!= '-')
111 static int get_input(WIN
*win
)
113 struct input_s
*in
= win
->data
;
115 struct input_data_s
*data
= in
->data
;
117 char *prompt
= _("Type F1 for help");
118 char str
[MB_CUR_MAX
];
121 window_draw_title(win
->w
, win
->title
, in
->w
, CP_INPUT_TITLE
,
125 for (i
= 0; in
->extra
[i
]; i
++)
126 window_draw_prompt(win
->w
, in
->lines
+ 2 + i
, in
->w
, in
->extra
[i
],
129 window_draw_prompt(win
->w
, in
->lines
+ 2 + i
, in
->w
, prompt
,
133 window_draw_prompt(win
->w
, in
->lines
+ 2, in
->w
, prompt
,
136 if (in
->func
&& in
->c
&& win
->c
== in
->c
) {
143 form_driver(in
->f
, REQ_DEL_WORD
);
146 form_driver(in
->f
, REQ_PREV_WORD
);
149 form_driver(in
->f
, REQ_NEXT_WORD
);
153 form_driver(in
->f
, REQ_BEG_LINE
);
157 form_driver(in
->f
, REQ_END_LINE
);
160 form_driver(in
->f
, REQ_CLR_EOL
);
163 form_driver(in
->f
, REQ_CLR_FIELD
);
166 message(_("Line Editing Keys"), ANY_KEY_STR
,
169 "UP/DOWN/LEFT/RIGHT - position cursor (multiline)\n"
170 " UP/CTRL-P - previous input history\n"
171 " DOWN/CTRL-N - next input history\n"
172 " HOME/CTRL-A - move cursor to the beginning of line\n"
173 " END/CTRL-E - move cursor to the end of line\n"
174 " CTRL-B/W - move cursor to previous/next word\n"
175 " CTRL-X - delete word under cursor\n"
176 " CTRL-K - delete from cursor to end of line\n"
177 " CTRL-U - clear entire input field\n"
178 " BACKSPACE - delete previous character\n"
179 " ESCAPE - quit without changes\n"
180 " ENTER - quit with changes"));
183 form_driver(in
->f
, REQ_LEFT_CHAR
);
186 form_driver(in
->f
, REQ_RIGHT_CHAR
);
190 if (in
->hist
>= 0 && input_history
[in
->hist
] && in
->lines
== 1) {
191 set_field_buffer(in
->fields
[0], 0, input_history
[in
->hist
]->str
);
192 form_driver(in
->f
, REQ_END_LINE
);
194 if (!input_history
[in
->hist
]->prev
)
195 input_history
[in
->hist
] = input_history
[in
->hist
]->head
;
197 input_history
[in
->hist
] = input_history
[in
->hist
]->prev
;
202 form_driver(in
->f
, REQ_UP_CHAR
);
206 if (in
->hist
>= 0 && input_history
[in
->hist
] && in
->lines
== 1) {
207 if (!input_history
[in
->hist
]->next
) {
208 set_field_buffer(in
->fields
[0], 0, NULL
);
209 form_driver(in
->f
, REQ_CLR_FIELD
);
213 input_history
[in
->hist
] = input_history
[in
->hist
]->next
;
214 set_field_buffer(in
->fields
[0], 0, input_history
[in
->hist
]->str
);
215 form_driver(in
->f
, REQ_END_LINE
);
219 form_driver(in
->f
, REQ_DOWN_CHAR
);
223 form_driver(in
->f
, REQ_DEL_PREV
);
226 tmp
= field_buffer(in
->fields
[0], 0);
232 tmp
= (in
->buf
[0]) ? in
->buf
: NULL
;
235 n
= wctomb (str
, win
->c
);
236 for (i
= 0; n
!= -1 && i
< n
; i
++)
237 form_driver(in
->f
, (unsigned char )str
[i
]);
241 form_driver(in
->f
, REQ_VALIDATION
);
249 strncpy(in
->buf
, tmp
, sizeof(in
->buf
)-1);
250 in
->buf
[sizeof(in
->buf
)-1] = 0;
260 free_field(in
->fields
[0]);
263 for (i
= 0; in
->extra
[i
]; i
++)
269 data
->str
= (in
->buf
[0]) ? strdup(in
->buf
) : NULL
;
272 add_input_history(in
->hist
, in
->buf
);
275 free_fieldtype(in
->ft
);
282 * This function prompts for input. The init argument is the initial value.
283 * The lines argument is how many lines the field is. If zero, then it is
284 * dynamically determined based on the init argument or INPUT_WIDTH if init is
287 * The reset argument is whether pressing ESC returns the initial value or
290 * The extra_help argument is an extra line of help prompt normally used with
291 * the custom_func argument. The custom_func argument is a pointer to a
292 * function of type void which takes one pointer-to-void argument. This
293 * function is called when the ckey argument is pressed.
295 * The efunc parameter is the function that is ran when the window is done
296 * getting input or NULL. This function is ran just before the window is
299 * The type argument is the type of validation for the input defined in
300 * common.h. Remaining arguments are values for the type argument. See
301 * field_type(3X) for validation types.
303 * FIXME form validation is buggy (integers).
305 WIN
*construct_input(const char *title
, const char *init
, int lines
, int reset
,
306 const char *extra_help
, input_func
*func
, void *arg
, wint_t key
,
307 struct input_data_s
*id
, int history
, int type
, ...)
311 int l
= (lines
> 0) ? lines
: 1;
313 FIELDTYPE
*ft
= NULL
;
317 in
= Calloc(1, sizeof(struct input_s
));
321 char *tmp
= strdup(extra_help
);
323 in
->extra
= split_str(tmp
, "\n", &eh
, &in
->w
, 0);
335 in
->lines
= (lines
) ? lines
: 1;
336 win
= window_create(title
, in
->h
, in
->w
, CALCPOSY(in
->h
), CALCPOSX(in
->w
),
337 get_input
, in
, id
->efunc
);
342 in
->fields
[0] = new_field(in
->lines
, in
->w
- 2, 0, 0, 0, 0);
346 case FIELD_TYPE_PGN_ROUND
:
347 ft
= new_fieldtype(NULL
, validate_pgn_round
);
348 set_field_type(in
->fields
[0], ft
);
350 case FIELD_TYPE_PGN_RESULT
:
351 ft
= new_fieldtype(NULL
, validate_pgn_result
);
352 set_field_type(in
->fields
[0], ft
);
354 case FIELD_TYPE_PGN_DATE
:
355 ft
= new_fieldtype(NULL
, validate_pgn_date
);
356 set_field_type(in
->fields
[0], ft
);
358 case FIELD_TYPE_PGN_TAG_NAME
:
359 ft
= new_fieldtype(NULL
, validate_pgn_tag_name
);
360 set_field_type(in
->fields
[0], ft
);
362 case FIELD_TYPE_ALNUM
:
363 set_field_type(in
->fields
[0], TYPE_ALNUM
, va_arg(ap
, int));
365 case FIELD_TYPE_ALPHA
:
366 set_field_type(in
->fields
[0], TYPE_ALPHA
, va_arg(ap
, int));
368 case FIELD_TYPE_ENUM
:
369 set_field_type(in
->fields
[0], TYPE_ENUM
, va_arg(ap
, char **),
370 va_arg(ap
, int), va_arg(ap
, int));
372 case FIELD_TYPE_INTEGER
:
373 set_field_type(in
->fields
[0], TYPE_INTEGER
, va_arg(ap
, int),
374 va_arg(ap
, long), va_arg(ap
, long));
376 case FIELD_TYPE_NUMERIC
:
377 set_field_type(in
->fields
[0], TYPE_NUMERIC
, va_arg(ap
, int),
378 va_arg(ap
, double), va_arg(ap
, double));
380 case FIELD_TYPE_REGEXP
:
381 set_field_type(in
->fields
[0], TYPE_REGEXP
, va_arg(ap
, char *));
384 #ifdef HAVE_TYPE_IPV4
385 case FIELD_TYPE_IPV4
:
386 set_field_type(in
->fields
[0], TYPE_IPV4
);
390 set_field_type(in
->fields
[0], NULL
);
397 strncpy(in
->buf
, init
, sizeof(in
->buf
)-1);
398 in
->buf
[sizeof(in
->buf
)-1] = 0;
399 set_field_buffer(in
->fields
[0], 0, init
);
405 field_opts_off(in
->fields
[0], O_STATIC
);
408 set_field_buffer(in
->fields
[0], 0, in
->buf
);
410 field_opts_off(in
->fields
[0], O_BLANK
|O_AUTOSKIP
);
411 in
->fields
[1] = NULL
;
412 in
->f
= new_form(in
->fields
);
413 form_opts_off(in
->f
, O_BS_OVERLOAD
);
414 set_form_win(in
->f
, win
->w
);
415 in
->sw
= derwin(win
->w
, in
->lines
, in
->w
- 2, 2, 1);
416 set_form_sub(in
->f
, in
->sw
);
418 form_driver(in
->f
, REQ_END_FIELD
);
419 keypad(win
->w
, TRUE
);
421 wbkgd(win
->w
, CP_INPUT_WINDOW
);