1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2024 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
44 static struct input_history_s
47 struct input_history_s
*next
;
48 struct input_history_s
*prev
;
49 struct input_history_s
*head
;
50 } *input_history
[INPUT_HIST_MAX
];
53 add_input_history (int which
, const char *str
)
55 struct input_history_s
*new;
56 struct input_history_s
*p
= NULL
;
58 if (!str
|| !*str
|| which
< 0)
61 if (input_history
[which
])
62 for (p
= input_history
[which
]->head
; p
->next
; p
= p
->next
);
64 new = Calloc (1, sizeof (struct input_history_s
));
67 fprintf (stderr
, "Out of core!\n");
71 new->str
= strdup (str
);
82 input_history
[which
] = p
? p
->next
: new;
86 validate_pgn_tag_name (int c
, const void *arg
)
88 if (!isalnum (c
) && c
!= '_')
95 validate_pgn_date (int c
, const void *arg
)
97 if (!isdigit (c
) && c
!= '.' && c
!= '?')
104 validate_pgn_round (int c
, const void *arg
)
106 if (!isdigit (c
) && c
!= '.' && c
!= '-' && c
!= '?')
113 validate_pgn_result (int c
, const void *arg
)
115 if (c
!= '1' && c
!= '0' && c
!= '2' && c
!= '*' && c
!= '/' && c
!= '-')
122 get_input (WIN
* win
)
124 struct input_s
*in
= win
->data
;
126 struct input_data_s
*data
= in
->data
;
128 char *prompt
= _("Type %ls for help");
130 char str
[MB_CUR_MAX
];
132 snprintf (buf
, sizeof (buf
), prompt
, key_lookup (global_keys
, do_global_help
));
134 window_draw_title (win
->w
, win
->title
, in
->w
, CP_INPUT_TITLE
,
139 for (i
= 0; in
->extra
[i
]; i
++)
140 window_draw_prompt (win
->w
, in
->lines
+ 2 + i
, in
->w
, in
->extra
[i
],
143 window_draw_prompt (win
->w
, in
->lines
+ 2 + i
, in
->w
, buf
,
147 window_draw_prompt (win
->w
, in
->lines
+ 2, in
->w
, buf
, CP_INPUT_PROMPT
);
149 if (in
->func
&& in
->c
&& win
->c
== in
->c
)
155 if (win
->c
== keycode_lookup (global_keys
, do_global_help
))
157 message (_("Line Editing Keys"), ANY_KEY_STR
,
159 _("UP/DOWN/LEFT/RIGHT - position cursor (multiline)\n"
160 " UP/CTRL-P - previous input history\n"
161 " DOWN/CTRL-N - next input history\n"
162 " HOME/CTRL-A - move cursor to the beginning of line\n"
163 " END/CTRL-E - move cursor to the end of line\n"
164 " CTRL-B/W - move cursor to previous/next word\n"
165 " CTRL-X - delete word under cursor\n"
166 " CTRL-K - delete from cursor to end of line\n"
167 " CTRL-U - clear entire input field\n"
168 " BACKSPACE - delete previous character\n"
169 " ESCAPE - quit without changes\n"
170 " ENTER - quit with changes"));
177 form_driver (in
->f
, REQ_DEL_WORD
);
180 form_driver (in
->f
, REQ_PREV_WORD
);
183 form_driver (in
->f
, REQ_NEXT_WORD
);
187 form_driver (in
->f
, REQ_BEG_LINE
);
191 form_driver (in
->f
, REQ_END_LINE
);
194 form_driver (in
->f
, REQ_CLR_EOL
);
197 form_driver (in
->f
, REQ_CLR_FIELD
);
200 form_driver (in
->f
, REQ_LEFT_CHAR
);
203 form_driver (in
->f
, REQ_RIGHT_CHAR
);
207 if (in
->hist
>= 0 && input_history
[in
->hist
] && in
->lines
== 1)
209 set_field_buffer (in
->fields
[0], 0, input_history
[in
->hist
]->str
);
210 form_driver (in
->f
, REQ_END_LINE
);
212 if (!input_history
[in
->hist
]->prev
)
213 input_history
[in
->hist
] = input_history
[in
->hist
]->head
;
215 input_history
[in
->hist
] = input_history
[in
->hist
]->prev
;
220 form_driver (in
->f
, REQ_UP_CHAR
);
224 if (in
->hist
>= 0 && input_history
[in
->hist
] && in
->lines
== 1)
226 if (!input_history
[in
->hist
]->next
)
228 set_field_buffer (in
->fields
[0], 0, NULL
);
229 form_driver (in
->f
, REQ_CLR_FIELD
);
233 input_history
[in
->hist
] = input_history
[in
->hist
]->next
;
234 set_field_buffer (in
->fields
[0], 0, input_history
[in
->hist
]->str
);
235 form_driver (in
->f
, REQ_END_LINE
);
239 form_driver (in
->f
, REQ_DOWN_CHAR
);
243 form_driver (in
->f
, REQ_DEL_PREV
);
246 tmp
= field_buffer (in
->fields
[0], 0);
252 tmp
= (in
->buf
[0]) ? in
->buf
: NULL
;
255 n
= wctomb (str
, win
->c
);
256 for (i
= 0; n
!= -1 && i
< n
; i
++)
257 form_driver (in
->f
, (unsigned char) str
[i
]);
262 form_driver (in
->f
, REQ_VALIDATION
);
272 strncpy (in
->buf
, tmp
, sizeof (in
->buf
) - 1);
273 in
->buf
[sizeof (in
->buf
) - 1] = 0;
283 free_field (in
->fields
[0]);
287 for (i
= 0; in
->extra
[i
]; i
++)
293 data
->str
= (in
->buf
[0]) ? strdup (in
->buf
) : NULL
;
296 add_input_history (in
->hist
, in
->buf
);
299 free_fieldtype (in
->ft
);
306 input_resize_func (WIN
*w
)
308 move_panel (w
->p
, CALCPOSY (w
->rows
), CALCPOSX (w
->cols
));
312 * This function prompts for input. The init argument is the initial value.
313 * The lines argument is how many lines the field is. If zero, then it is
314 * dynamically determined based on the init argument or INPUT_WIDTH if init is
317 * The reset argument is whether pressing ESC returns the initial value or
320 * The extra_help argument is an extra line of help prompt normally used with
321 * the custom_func argument. The custom_func argument is a pointer to a
322 * function of type void which takes one pointer-to-void argument. This
323 * function is called when the ckey argument is pressed.
325 * The efunc parameter is the function that is ran when the window is done
326 * getting input or NULL. This function is ran just before the window is
329 * The type argument is the type of validation for the input defined in
330 * common.h. Remaining arguments are values for the type argument. See
331 * field_type(3X) for validation types.
333 * FIXME form validation is buggy (integers).
336 construct_input (const char *title
, const char *init
, int lines
, int reset
,
337 const char *extra_help
, input_func
* func
, void *arg
,
338 wint_t key
, struct input_data_s
* id
, int history
,
339 window_resize_func rfunc
, int type
, ...)
343 int l
= (lines
> 0) ? lines
: 1;
345 FIELDTYPE
*ft
= NULL
;
349 in
= Calloc (1, sizeof (struct input_s
));
354 char *tmp
= strdup (extra_help
);
356 in
->extra
= split_str (tmp
, "\n", &eh
, &in
->w
, 0);
368 in
->lines
= (lines
) ? lines
: 1;
369 win
= window_create (title
, in
->h
, in
->w
, CALCPOSY (in
->h
), CALCPOSX (in
->w
),
370 get_input
, in
, id
->efunc
,
371 rfunc
? rfunc
: input_resize_func
);
376 in
->fields
[0] = new_field (in
->lines
, in
->w
- 2, 0, 0, 0, 0);
381 case FIELD_TYPE_PGN_ROUND
:
382 ft
= new_fieldtype (NULL
, validate_pgn_round
);
383 set_field_type (in
->fields
[0], ft
);
385 case FIELD_TYPE_PGN_RESULT
:
386 ft
= new_fieldtype (NULL
, validate_pgn_result
);
387 set_field_type (in
->fields
[0], ft
);
389 case FIELD_TYPE_PGN_DATE
:
390 ft
= new_fieldtype (NULL
, validate_pgn_date
);
391 set_field_type (in
->fields
[0], ft
);
393 case FIELD_TYPE_PGN_TAG_NAME
:
394 ft
= new_fieldtype (NULL
, validate_pgn_tag_name
);
395 set_field_type (in
->fields
[0], ft
);
397 case FIELD_TYPE_ALNUM
:
398 set_field_type (in
->fields
[0], TYPE_ALNUM
, va_arg (ap
, int));
400 case FIELD_TYPE_ALPHA
:
401 set_field_type (in
->fields
[0], TYPE_ALPHA
, va_arg (ap
, int));
403 case FIELD_TYPE_ENUM
:
404 set_field_type (in
->fields
[0], TYPE_ENUM
, va_arg (ap
, char **),
405 va_arg (ap
, int), va_arg (ap
, int));
407 case FIELD_TYPE_INTEGER
:
408 set_field_type (in
->fields
[0], TYPE_INTEGER
, va_arg (ap
, int),
409 va_arg (ap
, long), va_arg (ap
, long));
411 case FIELD_TYPE_NUMERIC
:
412 set_field_type (in
->fields
[0], TYPE_NUMERIC
, va_arg (ap
, int),
413 va_arg (ap
, double), va_arg (ap
, double));
415 case FIELD_TYPE_REGEXP
:
416 set_field_type (in
->fields
[0], TYPE_REGEXP
, va_arg (ap
, char *));
419 #ifdef HAVE_TYPE_IPV4
420 case FIELD_TYPE_IPV4
:
421 set_field_type (in
->fields
[0], TYPE_IPV4
);
425 set_field_type (in
->fields
[0], NULL
);
433 strncpy (in
->buf
, init
, sizeof (in
->buf
) - 1);
434 in
->buf
[sizeof (in
->buf
) - 1] = 0;
435 set_field_buffer (in
->fields
[0], 0, init
);
441 field_opts_off (in
->fields
[0], O_STATIC
);
444 set_field_buffer (in
->fields
[0], 0, in
->buf
);
446 field_opts_off (in
->fields
[0], O_BLANK
| O_AUTOSKIP
);
447 in
->fields
[1] = NULL
;
448 in
->f
= new_form (in
->fields
);
449 form_opts_off (in
->f
, O_BS_OVERLOAD
);
450 set_form_win (in
->f
, win
->w
);
451 in
->sw
= derwin (win
->w
, in
->lines
, in
->w
- 2, 2, 1);
452 set_form_sub (in
->f
, in
->sw
);
454 form_driver (in
->f
, REQ_END_FIELD
);
455 keypad (win
->w
, TRUE
);
457 wbkgd (win
->w
, CP_INPUT_WINDOW
);