1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2018 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
45 struct input_history_s
*next
;
46 struct input_history_s
*prev
;
47 struct input_history_s
*head
;
48 } *input_history
[INPUT_HIST_MAX
];
51 add_input_history (int which
, const char *str
)
53 struct input_history_s
*new;
54 struct input_history_s
*p
= NULL
;
56 if (!str
|| !*str
|| which
< 0)
59 if (input_history
[which
])
60 for (p
= input_history
[which
]->head
; p
->next
; p
= p
->next
);
62 new = calloc (1, sizeof (struct input_history_s
));
65 fprintf (stderr
, "Out of core!\n");
69 new->str
= strdup (str
);
80 input_history
[which
] = p
? p
->next
: new;
84 validate_pgn_tag_name (int c
, const void *arg
)
86 if (!isalnum (c
) && c
!= '_')
93 validate_pgn_date (int c
, const void *arg
)
95 if (!isdigit (c
) && c
!= '.' && c
!= '?')
102 validate_pgn_round (int c
, const void *arg
)
104 if (!isdigit (c
) && c
!= '.' && c
!= '-' && c
!= '?')
111 validate_pgn_result (int c
, const void *arg
)
113 if (c
!= '1' && c
!= '0' && c
!= '2' && c
!= '*' && c
!= '/' && c
!= '-')
120 get_input (WIN
* win
)
122 struct input_s
*in
= win
->data
;
124 struct input_data_s
*data
= in
->data
;
126 char *prompt
= _("Type F1 for help");
127 char str
[MB_CUR_MAX
];
130 window_draw_title (win
->w
, win
->title
, in
->w
, CP_INPUT_TITLE
,
135 for (i
= 0; in
->extra
[i
]; i
++)
136 window_draw_prompt (win
->w
, in
->lines
+ 2 + i
, in
->w
, in
->extra
[i
],
139 window_draw_prompt (win
->w
, in
->lines
+ 2 + i
, in
->w
, prompt
,
143 window_draw_prompt (win
->w
, in
->lines
+ 2, in
->w
, prompt
,
146 if (in
->func
&& in
->c
&& win
->c
== in
->c
)
155 form_driver (in
->f
, REQ_DEL_WORD
);
158 form_driver (in
->f
, REQ_PREV_WORD
);
161 form_driver (in
->f
, REQ_NEXT_WORD
);
165 form_driver (in
->f
, REQ_BEG_LINE
);
169 form_driver (in
->f
, REQ_END_LINE
);
172 form_driver (in
->f
, REQ_CLR_EOL
);
175 form_driver (in
->f
, REQ_CLR_FIELD
);
178 message (_("Line Editing Keys"), ANY_KEY_STR
,
180 _("UP/DOWN/LEFT/RIGHT - position cursor (multiline)\n"
181 " UP/CTRL-P - previous input history\n"
182 " DOWN/CTRL-N - next input history\n"
183 " HOME/CTRL-A - move cursor to the beginning of line\n"
184 " END/CTRL-E - move cursor to the end of line\n"
185 " CTRL-B/W - move cursor to previous/next word\n"
186 " CTRL-X - delete word under cursor\n"
187 " CTRL-K - delete from cursor to end of line\n"
188 " CTRL-U - clear entire input field\n"
189 " BACKSPACE - delete previous character\n"
190 " ESCAPE - quit without changes\n"
191 " ENTER - quit with changes"));
194 form_driver (in
->f
, REQ_LEFT_CHAR
);
197 form_driver (in
->f
, REQ_RIGHT_CHAR
);
201 if (in
->hist
>= 0 && input_history
[in
->hist
] && in
->lines
== 1)
203 set_field_buffer (in
->fields
[0], 0, input_history
[in
->hist
]->str
);
204 form_driver (in
->f
, REQ_END_LINE
);
206 if (!input_history
[in
->hist
]->prev
)
207 input_history
[in
->hist
] = input_history
[in
->hist
]->head
;
209 input_history
[in
->hist
] = input_history
[in
->hist
]->prev
;
214 form_driver (in
->f
, REQ_UP_CHAR
);
218 if (in
->hist
>= 0 && input_history
[in
->hist
] && in
->lines
== 1)
220 if (!input_history
[in
->hist
]->next
)
222 set_field_buffer (in
->fields
[0], 0, NULL
);
223 form_driver (in
->f
, REQ_CLR_FIELD
);
227 input_history
[in
->hist
] = input_history
[in
->hist
]->next
;
228 set_field_buffer (in
->fields
[0], 0, input_history
[in
->hist
]->str
);
229 form_driver (in
->f
, REQ_END_LINE
);
233 form_driver (in
->f
, REQ_DOWN_CHAR
);
237 form_driver (in
->f
, REQ_DEL_PREV
);
240 tmp
= field_buffer (in
->fields
[0], 0);
246 tmp
= (in
->buf
[0]) ? in
->buf
: NULL
;
249 n
= wctomb (str
, win
->c
);
250 for (i
= 0; n
!= -1 && i
< n
; i
++)
251 form_driver (in
->f
, (unsigned char) str
[i
]);
255 form_driver (in
->f
, REQ_VALIDATION
);
265 strncpy (in
->buf
, tmp
, sizeof (in
->buf
) - 1);
266 in
->buf
[sizeof (in
->buf
) - 1] = 0;
276 free_field (in
->fields
[0]);
280 for (i
= 0; in
->extra
[i
]; i
++)
286 data
->str
= (in
->buf
[0]) ? strdup (in
->buf
) : NULL
;
289 add_input_history (in
->hist
, in
->buf
);
292 free_fieldtype (in
->ft
);
299 input_resize_func (WIN
*w
)
301 move_panel (w
->p
, CALCPOSY (w
->rows
), CALCPOSX (w
->cols
));
305 * This function prompts for input. The init argument is the initial value.
306 * The lines argument is how many lines the field is. If zero, then it is
307 * dynamically determined based on the init argument or INPUT_WIDTH if init is
310 * The reset argument is whether pressing ESC returns the initial value or
313 * The extra_help argument is an extra line of help prompt normally used with
314 * the custom_func argument. The custom_func argument is a pointer to a
315 * function of type void which takes one pointer-to-void argument. This
316 * function is called when the ckey argument is pressed.
318 * The efunc parameter is the function that is ran when the window is done
319 * getting input or NULL. This function is ran just before the window is
322 * The type argument is the type of validation for the input defined in
323 * common.h. Remaining arguments are values for the type argument. See
324 * field_type(3X) for validation types.
326 * FIXME form validation is buggy (integers).
329 construct_input (const char *title
, const char *init
, int lines
, int reset
,
330 const char *extra_help
, input_func
* func
, void *arg
,
331 wint_t key
, struct input_data_s
* id
, int history
,
332 window_resize_func rfunc
, int type
, ...)
336 int l
= (lines
> 0) ? lines
: 1;
338 FIELDTYPE
*ft
= NULL
;
342 in
= Calloc (1, sizeof (struct input_s
));
347 char *tmp
= strdup (extra_help
);
349 in
->extra
= split_str (tmp
, "\n", &eh
, &in
->w
, 0);
361 in
->lines
= (lines
) ? lines
: 1;
362 win
= window_create (title
, in
->h
, in
->w
, CALCPOSY (in
->h
), CALCPOSX (in
->w
),
363 get_input
, in
, id
->efunc
,
364 rfunc
? rfunc
: input_resize_func
);
369 in
->fields
[0] = new_field (in
->lines
, in
->w
- 2, 0, 0, 0, 0);
374 case FIELD_TYPE_PGN_ROUND
:
375 ft
= new_fieldtype (NULL
, validate_pgn_round
);
376 set_field_type (in
->fields
[0], ft
);
378 case FIELD_TYPE_PGN_RESULT
:
379 ft
= new_fieldtype (NULL
, validate_pgn_result
);
380 set_field_type (in
->fields
[0], ft
);
382 case FIELD_TYPE_PGN_DATE
:
383 ft
= new_fieldtype (NULL
, validate_pgn_date
);
384 set_field_type (in
->fields
[0], ft
);
386 case FIELD_TYPE_PGN_TAG_NAME
:
387 ft
= new_fieldtype (NULL
, validate_pgn_tag_name
);
388 set_field_type (in
->fields
[0], ft
);
390 case FIELD_TYPE_ALNUM
:
391 set_field_type (in
->fields
[0], TYPE_ALNUM
, va_arg (ap
, int));
393 case FIELD_TYPE_ALPHA
:
394 set_field_type (in
->fields
[0], TYPE_ALPHA
, va_arg (ap
, int));
396 case FIELD_TYPE_ENUM
:
397 set_field_type (in
->fields
[0], TYPE_ENUM
, va_arg (ap
, char **),
398 va_arg (ap
, int), va_arg (ap
, int));
400 case FIELD_TYPE_INTEGER
:
401 set_field_type (in
->fields
[0], TYPE_INTEGER
, va_arg (ap
, int),
402 va_arg (ap
, long), va_arg (ap
, long));
404 case FIELD_TYPE_NUMERIC
:
405 set_field_type (in
->fields
[0], TYPE_NUMERIC
, va_arg (ap
, int),
406 va_arg (ap
, double), va_arg (ap
, double));
408 case FIELD_TYPE_REGEXP
:
409 set_field_type (in
->fields
[0], TYPE_REGEXP
, va_arg (ap
, char *));
412 #ifdef HAVE_TYPE_IPV4
413 case FIELD_TYPE_IPV4
:
414 set_field_type (in
->fields
[0], TYPE_IPV4
);
418 set_field_type (in
->fields
[0], NULL
);
426 strncpy (in
->buf
, init
, sizeof (in
->buf
) - 1);
427 in
->buf
[sizeof (in
->buf
) - 1] = 0;
428 set_field_buffer (in
->fields
[0], 0, init
);
434 field_opts_off (in
->fields
[0], O_STATIC
);
437 set_field_buffer (in
->fields
[0], 0, in
->buf
);
439 field_opts_off (in
->fields
[0], O_BLANK
| O_AUTOSKIP
);
440 in
->fields
[1] = NULL
;
441 in
->f
= new_form (in
->fields
);
442 form_opts_off (in
->f
, O_BS_OVERLOAD
);
443 set_form_win (in
->f
, win
->w
);
444 in
->sw
= derwin (win
->w
, in
->lines
, in
->w
- 2, 2, 1);
445 set_form_sub (in
->f
, in
->sw
);
447 form_driver (in
->f
, REQ_END_FIELD
);
448 keypad (win
->w
, TRUE
);
450 wbkgd (win
->w
, CP_INPUT_WINDOW
);