C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
fields.c
Go to the documentation of this file.
1/** @file fields.c
2 @brief Field Edit and Entry for C-Menu Form
3 @author Bill Waller
4 Copyright (c) 2025
5 MIT License
6 billxwaller@gmail.com
7 @date 2026-02-09
8 */
9
10#include <common.h>
11#include <monetary.h>
12#include <stdbool.h>
13#include <stddef.h>
14#include <stdio.h>
15#include <string.h>
16#include <termios.h>
17#include <unistd.h>
18
19bool is_valid_date(int, int, int);
20bool is_valid_time(int, int, int);
21int form_fmt_field(Form *, char *);
22void numeric(char *, char *);
23void right_justify(char *, int);
24void left_justify(char *);
25
26char ff_tbl[][26] = {"string", "decimal_int", "hex_int", "float", "double",
27 "currency", "yyyymmdd", "hhmmss", "apr", ""};
28
29int field_editor(Form *);
30int form_display_field(Form *);
31int form_display_field_n(Form *, int);
32int form_validate_field(Form *);
33void mk_filler(char *, int);
34
35/** @defgroup field_editor Field Editor
36 @brief File mapping, user input, command processing, and display logic
37 @brief Main loop for field editing and entry
38 @details This function handles the main loop for field editing and entry.
39 It processes user input, including character input, navigation keys, and
40 mouse events, to allow the user to edit the content of a field. The function
41 validates input based on the field's specified format and updates the display
42 accordingly. It returns the key code of the action taken, such as accepting
43 the field, tabbing to the next field, or breaking out of the input loop.
44 */
45
46/** @brief Accept input for a field
47 @ingroup field_editor
48 @param form Pointer to Form structure
49 @return int Key code of action taken
50 @details Handles character input, navigation keys, and mouse events for
51 field editing. Validates input based on field format and updates display.
52 Returns key code of action taken (e.g., accept field, tab to next field,
53 break out of input loop).
54 */
55int field_editor(Form *form) {
56 bool f_insert = FALSE;
57 int in_key;
58 char *s, *d;
59 WINDOW *win = form->win;
60
61 int flin = form->field[form->fidx]->line;
62 int fcol = form->field[form->fidx]->col;
63 int flen = form->field[form->fidx]->len;
64 int ff = form->field[form->fidx]->ff;
65 char *accept_s = form->field[form->fidx]->accept_s;
66 char *filler_s = form->field[form->fidx]->filler_s;
67 form_fmt_field(form, accept_s);
68 click_x = click_y = -1;
69 char *fstart = accept_s;
70 char *fend = fstart + flen;
71 int x = fcol;
72 char *p = fstart = accept_s;
73 char *str_end = p + strlen(p);
74 in_key = 0;
75 if (f_insert)
77 else
81
82 while (1) {
83 if (in_key == 0) {
84 mvwaddstr(win, flin, fcol, filler_s);
85 mvwaddstr(win, flin, fcol, accept_s);
86 wmove(win, flin, x);
87 tcflush(0, TCIFLUSH);
88 wrefresh(form->box);
89 in_key = xwgetch(win, form->chyron, -1);
90 }
91 switch (in_key) {
92 /** KEY_F(10) is the default key for accepting the field and moving
93 to the next field */
94 case KEY_F(10):
95 form_fmt_field(form, accept_s);
97 if (form_validate_field(form) != 0)
98 continue;
99 return (in_key);
100 /** KEY_F(9) Cancels the current operation */
101 case KEY_BREAK:
102 case KEY_F(9):
104 in_key = KEY_F(9);
105 return (in_key);
106 /** KEY_UP, KEY_BTAB moves to the previous field */
107 case 'H':
108 case KEY_F(1):
109 return (in_key);
110 case KEY_BTAB:
111 case KEY_UP:
112 form_fmt_field(form, accept_s);
114 in_key = KEY_UP;
115 return (in_key);
116 /** KEY_DOWN, TAB moves to the next field */
117 case '\t':
118 case KEY_DOWN:
119 form_fmt_field(form, accept_s);
121 in_key = KEY_DOWN;
122 return (in_key);
123 /** KEY_END moves cursor to end of field */
124 case KEY_END:
125 case Ctrl('e'):
126 while (*p != '\0')
127 p++;
128 x = fcol + (p - fstart);
129 in_key = 0;
130 continue;
131 /**< Enter accepts the field and moves to the next field if
132 * form->f_erase_remainder is set, it will clear the remaining
133 * characters above and after the current cursor location */
134 case '\n':
135 case KEY_ENTER:
136 if (form->f_erase_remainder)
137 *p = '\0';
138 form_fmt_field(form, accept_s);
140 in_key = KEY_ENTER;
141 return (in_key);
142 /** KEY_IC toggles insert mode */
143 case KEY_IC:
144 if (f_insert) {
145 f_insert = FALSE;
146 set_chyron_key_cp(form->chyron, 18, "INS", KEY_IC, cp_nt_rev);
147 } else {
148 f_insert = TRUE;
149 set_chyron_key_cp(form->chyron, 18, "INS", KEY_IC,
151 }
154 form->chyron->l);
155 in_key = 0;
156 continue;
157 /** KEY_DC deletes character at cursor */
158 case KEY_DC:
159 s = p + 1;
160 d = p;
161 while (*s != '\0')
162 *d++ = *s++;
163 *d = '\0';
164 str_end = d;
165 f_insert = FALSE;
166 in_key = 0;
167 continue;
168 /** KEY_HOME moves cursor to start of field */
169 case KEY_HOME:
170 case Ctrl('a'):
171 p = fstart;
172 x = fcol;
173 in_key = 0;
174 continue;
175 /** KEY_BACKSPACE deletes character before cursor */
176 case KEY_BACKSPACE:
177 if (p > fstart) {
178 p--;
179 x--;
180 }
181 s = p + 1;
182 d = p;
183 while (*s != '\0')
184 *d++ = *s++;
185 *d = '\0';
186 str_end = d;
187 in_key = 0;
188 continue;
189 /** KEY_LEFT moves cursor left one character */
190 case KEY_LEFT:
191 if (p > fstart) {
192 p--;
193 x--;
194 }
195 in_key = 0;
196 continue;
197 /** KEY_RIGHT moves cursor right one character */
198 case KEY_RIGHT:
199 if (p < fend && p < str_end) {
200 p++;
201 x++;
202 }
203 in_key = 0;
204 continue;
205 /** Handles mouse events for field editing */
206 case KEY_MOUSE:
208 x = click_x;
209 flin = click_y;
210 flen = form->field[form->fidx]->len;
211 ff = form->field[form->fidx]->ff; /* ff - field forat */
212 accept_s = form->field[form->fidx]->accept_s;
213 filler_s = form->field[form->fidx]->filler_s;
214 form_fmt_field(form, accept_s);
215 fstart = accept_s;
216 fend = fstart + flen;
217 str_end = fstart + strlen(fstart);
218 p = fstart + (x - form->field[form->fidx]->col);
219 if (p > str_end)
220 x -= p - str_end;
221 p = min(p, str_end);
222 in_key = 0;
223 continue;
224 default:
225 if (p >= fend) {
226 in_key = 0;
227 continue;
228 }
229 /** Validates fields based on format */
230 switch (ff) {
231 /** FF_STRING accepts all printable characters and spaces */
232 case FF_STRING:
233 break;
234 /** FF_DECIMAL_INT accepts digits 0 through 9 and decimal point
235 * ('.') */
236 case FF_DECIMAL_INT:
237 if ((in_key >= '0' && in_key <= '9') || in_key == '.')
238 break;
239 beep();
240 in_key = 0;
241 continue;
242 /** FF_HEX_INT accepts digits 0 through 9 and letters A through
243 * F (case-insensitive) */
244 case FF_HEX_INT:
245 if ((in_key >= '0' && in_key <= '9') ||
246 (in_key >= 'A' && in_key <= 'F') ||
247 (in_key >= 'a' && in_key <= 'f'))
248 break;
249 beep();
250 in_key = 0;
251 continue;
252 /** FF_FLOAT accepts digits 0 through 9 and decimal point ('.')
253 * and negative operator ('-') at the start of the field */
254 case FF_FLOAT:
255 if ((in_key >= '0' && in_key <= '9') || in_key == '.' ||
256 (in_key == '-' && p == fstart))
257 break;
258 beep();
259 in_key = 0;
260 continue;
261 /** FF_DOUBLE accepts digits 0 through 9 and decimal point ('.')
262 * and negative operator ('-') at the start of the field */
263 case FF_DOUBLE:
264 if ((in_key >= '0' && in_key <= '9') || in_key == '.' ||
265 (in_key == '-' && p == fstart))
266 break;
267 beep();
268 in_key = 0;
269 continue;
270 /** FF_CURRENCY accepts digits 0 through 9 and decimal point
271 * ('.') and negative operator ('-') at the start of the field
272 */
273 case FF_CURRENCY:
274 if ((in_key >= '0' && in_key <= '9') || in_key == '.' ||
275 (in_key == '-' && p == fstart))
276 break;
277 beep();
278 in_key = 0;
279 continue;
280 /** FF_YYYYMMDD accepts digits 0 through 9 */
281 case FF_YYYYMMDD:
282 if (in_key >= '0' && in_key <= '9')
283 break;
284 beep();
285 in_key = 0;
286 continue;
287 /** FF_HHMMSS accepts digits 0 through 9 */
288 case FF_HHMMSS:
289 if (in_key >= '0' && in_key <= '9')
290 break;
291 beep();
292 in_key = 0;
293 continue;
294 /** FF_APR accepts digits 0 through 9 and decimal point ('.') */
295 case FF_APR:
296 if ((in_key >= '0' && in_key <= '9') || in_key == '.')
297 break;
298 beep();
299 in_key = 0;
300 continue;
301 default:
302 Perror("field_editor() invalid format");
303 break;
304 }
305 if (in_key < ' ' || in_key > '~') {
306 in_key = 0;
307 continue;
308 }
309 if (f_insert) {
310 if (str_end < fend) {
311 s = str_end - 1;
312 d = str_end;
313 while (s >= p)
314 *d-- = *s--;
315 *p++ = in_key;
316 str_end++;
317 x++;
318 }
319 } else {
320 if (p < fend) {
321 if (p < str_end) {
322 *p++ = in_key;
323 x++;
324 } else if (p == str_end) {
325 *p++ = in_key;
326 *p = '\0';
327 str_end = p;
328 x++;
329 }
330 }
331 }
332 in_key = 0;
333 continue;
334 }
335 }
336}
337
338/** @brief Display field n
339 @ingroup field_editor
340 @param form Pointer to Form structure
341 @param n Field index to display
342 @return 0 on success, non-zero on error
343 @details This function temporarily sets the form's current field index
344 (fidx) to n, calls form_display_field() to display that field, and then
345 restores the original fidx value. This allows for displaying a specific field
346 without permanently changing the form's current field index.
347 */
348int form_display_field_n(Form *form, int n) {
349 int fidx = form->fidx;
350 form->fidx = n;
352 form->fidx = fidx;
353 return 0;
354}
355/** @brief Display current field
356 @ingroup field_editor
357 @param form Pointer to Form structure
358 @return 0 on success, non-zero on error
359 @details This function displays the current field based on the form's
360 current field index (fidx). It retrieves the line and column information for
361 the current field, displays any brackets if set, and then displays the
362 field's content using the display_s string. The function ensures that the
363 field is displayed correctly within the form's window and refreshes the
364 display to show the updated field content.
365 */
366int form_display_field(Form *form) {
367 int flin = form->field[form->fidx]->line;
368 int fcol = form->field[form->fidx]->col;
369 mvwaddstr(form->win, flin, fcol, form->field[form->fidx]->filler_s);
370 mvwaddstr(form->win, flin, fcol, form->field[form->fidx]->display_s);
371 return 0;
372}
373/** @brief Format field according to its format type
374 @ingroup field_editor
375 @param form Pointer to Form structure
376 @param s Input string to format
377 @return 0 on success, non-zero on error
378 @details takes the input string for the current field and formats it
379 according to the field's specified format type (ff). It updates the
380 accept_s and display_s strings for the field based on the formatted
381 value.
382 Handles various format types, including strings, decimal integers,
383 hexadecimal integers, floating-point numbers, currency, dates, and times.
384 Uses helper functions for validation and formatting, such as
385 is_valid_date(), is_valid_time(), numeric(), right_justify(),
386 left_justify(), and strnzcpy(). The function ensures that the formatted
387 output fits within the field's length and creates a filler string for the
388 field as needed. The function also handles error cases, such as invalid
389 formats, and provides feedback through error messages. It is designed to
390 be extensible, allowing for additional format types to be added in the
391 future as needed.
392 Assumes that the input string is well-formed and does not contain
393 malicious content. Input validation and sanitization should be performed
394 at a higher level in the application to ensure security and robustness.
395 The function currently does not handle localization or
396 internationalization of number formats, such as different decimal
397 separators or currency symbols. Future enhancements may include support
398 for locale-specific formatting.
399 Error handling is basic; future
400 versions may include more detailed error reporting and logging
401 mechanisms.
402 Performance optimizations may be considered for
403 handling large volumes of data or high-frequency updates in real-time
404 applications. The following variables and structures are used in
405 this function:
406 @code
407 char field_s[FIELD_MAXLEN];
408 int decimal_int_n = 0;
409 int hex_int_n = 0;
410 float float_n = 0.0;
411 double double_n = 0.0;
412 double currency_n = 0.0;
413 struct Date { int yyyy; int mm; int dd; };
414 struct Time { int hh; int mm; int ss; };
415 @endcode
416 */
417int form_fmt_field(Form *form, char *s) {
419 char *input_s = form->field[form->fidx]->input_s;
420 char *accept_s = form->field[form->fidx]->accept_s;
421 char *display_s = form->field[form->fidx]->display_s;
422 char *filler_s = form->field[form->fidx]->filler_s;
423 int ff = form->field[form->fidx]->ff;
424 int fl = form->field[form->fidx]->len;
425
426 char field_s[FIELD_MAXLEN];
427 int decimal_int_n = 0;
428 int hex_int_n = 0;
429 float float_n = 0.0;
430 double double_n = 0.0;
431 double currency_n = 0.0;
432
433 struct {
434 int yyyy;
435 int mm;
436 int dd;
437 } Date;
438 Date.yyyy = Date.mm = Date.dd = 0;
439 struct {
440 int hh;
441 int mm;
442 int ss;
443 } Time;
444 Time.hh = Time.mm = Time.ss = 0;
445 strnz(accept_s, fl);
446 switch (ff) {
447 case FF_STRING:
449 trim(s);
450 strnz__cpy(input_s, s, FIELD_MAXLEN - 1);
451 strnz__cpy(accept_s, s, FIELD_MAXLEN - 1);
452 strnz__cpy(display_s, s, FIELD_MAXLEN - 1);
453 break;
454 case FF_DECIMAL_INT:
455 sscanf(input_s, "%d", &decimal_int_n);
456 sprintf(accept_s, "%d", decimal_int_n);
457 sprintf(display_s, "%d", decimal_int_n);
458 right_justify(display_s, fl);
459 break;
460 case FF_HEX_INT:
461 sscanf(input_s, "%x", &hex_int_n);
462 sprintf(accept_s, "%d", hex_int_n);
463 sprintf(display_s, "%x", hex_int_n);
464 right_justify(display_s, fl);
465 break;
466 case FF_FLOAT:
467 sscanf(input_s, "%f", &float_n);
468 sprintf(accept_s, "%f", float_n);
469 sprintf(display_s, "%f", float_n);
470 right_justify(display_s, fl);
471 break;
472 case FF_DOUBLE:
473 sscanf(input_s, "%lf", &double_n);
474 sprintf(accept_s, "%lf", double_n);
475 sprintf(display_s, "%lf", double_n);
476 right_justify(display_s, fl);
477 break;
478 case FF_CURRENCY:
479 numeric(field_s, input_s);
480 sscanf(field_s, "%lf", &currency_n);
481 sprintf(accept_s, "%.2lf", currency_n);
482 sprintf(display_s, "%'.2lf", currency_n);
483 right_justify(display_s, fl);
484 break;
485 case FF_YYYYMMDD:
486 Date.yyyy = Date.mm = Date.dd = 0;
487 strnz__cpy(field_s, input_s, FIELD_MAXLEN - 1);
488 sscanf(field_s, "%4d%2d%2d", &Date.yyyy, &Date.mm, &Date.dd);
489 sprintf(accept_s, "%04d%02d%02d", Date.yyyy, Date.mm, Date.dd);
490 if (is_valid_date(Date.yyyy, Date.mm, Date.dd))
491 sprintf(display_s, "%04d-%02d-%02d", Date.yyyy, Date.mm, Date.dd);
492 break;
493 case FF_HHMMSS:
494 Time.hh = Time.mm = Time.ss = 0;
495 strnz__cpy(field_s, input_s, FIELD_MAXLEN - 1);
496 sscanf(field_s, "%2d%2d%2d", &Time.hh, &Time.mm, &Time.ss);
497 sprintf(accept_s, "%02d%02d%02d", Time.hh, Time.mm, Time.ss);
498 if (is_valid_time(Time.hh, Time.mm, Time.ss))
499 sprintf(display_s, "%02d:%02d:%02d", Time.hh, Time.mm, Time.ss);
500 break;
501 case FF_APR:
502 sscanf(input_s, "%lf", &double_n);
503 sprintf(accept_s, "%lf", double_n);
504 sprintf(display_s, "%0.3lf", double_n);
505 right_justify(display_s, fl);
506 break;
507 default:
508 Perror("form_fmt_field() invalid format");
509 break;
510 }
511 strnz(accept_s, fl);
512 left_justify(accept_s);
513 mk_filler(filler_s, fl);
514 return 0;
515}
516/** @brief Validate current field based on flags
517 @ingroup field_editor
518 @param form Pointer to Form structure
519 @return 0 if valid, 1 if invalid
520 @details Very underdeveloped - only checks F_NOTBLANK and F_NOMETAS
521 */
522int form_validate_field(Form *form) {
523 int n = form->fidx;
524 char *p = form->field[n]->accept_s;
525 if (form->field[n]->ff & F_NOTBLANK) {
526 char *s = form->field[n]->accept_s;
527 while (*s++ == ' ')
528 ;
529 if (*s == '\0') {
530 Perror("blank field not allowed");
531 return (1);
532 }
533 }
534 if (form->field[n]->ff & F_NOMETAS) {
535 if (strpbrk(p, "*?[]") != 0) {
536 Perror("metacharacters not allowed");
537 return (1);
538 }
539 }
540 return (0);
541}
542/** @brief Create filler string for field
543 @ingroup field_editor
544 @param s Filler string to create
545 @param fl Field length
546 @details Fills the string s with the fill character specified in the form's
547 fill_char array, repeated for the length of the field (fl). The resulting
548 string is null-terminated. This filler string can be used to display empty
549 fields or to clear the field area before displaying new content.
550 */
551void mk_filler(char *s, int fl) {
552 char *e = s + fl;
553 unsigned char c;
554
555 c = form->fill_char[0];
556 while (s != e)
557 *s++ = c;
558 *s = '\0';
559}
560/** @brief Left justify string by removing leading spaces
561 @ingroup field_editor
562 @param s String to left justify
563 @details This function takes a string s and removes any leading spaces,
564 effectively left-justifying the text. It does this by finding the first
565 non-space character and shifting the string to the left, overwriting the
566 leading spaces. The resulting string is null-terminated.
567 */
568void left_justify(char *s) { trim(s); }
569/** @brief Right justify string by removing trailing spaces and adding leading
570 @ingroup field_editor
571 spaces
572 @param s String to right justify
573 @param fl Field length
574 @details This function takes a string s and right-justifies it within a
575 field of length fl. It first removes any trailing spaces from the string,
576 then shifts the characters to the right end of the field, filling the left
577 side with spaces. The resulting string is null-terminated and fits within the
578 specified field length.
579 */
580void right_justify(char *s, int fl) {
581 char *p = s;
582 char *d = s + fl;
583 trim(s);
584 *d = '\0';
585 while (*s != '\0') {
586 s++;
587 }
588 while (s != p) {
589 *(--d) = *(--s);
590 }
591 while (d != p) {
592 *(--d) = ' ';
593 }
594}
595/** @brief Check if a given date is valid, including leap years
596 @ingroup field_editor
597 @param yyyy Year
598 @param mm Month
599 @param dd Day
600 @return true if the date is valid, false otherwise
601 @details This function checks if the provided year, month, and day
602 constitute a valid date. It accounts for leap years when determining the
603 number of days in February. The function returns true if the date is valid
604 and false if it is not.
605 */
606bool is_valid_date(int yyyy, int mm, int dd) {
607 if (yyyy < 1 || mm < 1 || mm > 12 || dd < 1)
608 return false;
609 int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
610 if ((yyyy % 4 == 0 && yyyy % 100 != 0) || (yyyy % 400 == 0))
611 days_in_month[2] = 29;
612 if (dd > days_in_month[mm])
613 return false;
614 return true;
615}
616/** @brief Check if a given time is valid
617 @ingroup field_editor
618 @param hh Hour
619 @param mm Minute
620 @param ss Second
621 @return true if the time is valid, false otherwise
622 @details This function checks if the provided hour, minute, and second
623 constitute a valid time. It ensures that hours are between 0 and 23, minutes
624 and seconds are between 0 and 59. The function returns true if the time is
625 valid and false if it is not.
626 */
627bool is_valid_time(int hh, int mm, int ss) {
628 if (hh < 0 || hh > 23 || mm < 0 || mm > 59 || ss < 0 || ss > 59)
629 return false;
630 return true;
631}
632/** @brief Extract numeric characters from source string to destination string
633 @ingroup field_editor
634 @param d Destination string
635 @param s Source string
636 @details This function takes a source string s and extracts only the numeric
637 characters (digits 0-9), as well as dashes ('-') and periods ('.'), copying
638 them into the destination string d. The resulting string in d is
639 null-terminated. This is useful for processing input that may contain
640 non-numeric characters, allowing the application to focus on the numeric
641 content for further processing or validation.
642 */
643void numeric(char *d, char *s) {
644 while (*s != '\0') {
645 if (*s == '-' || *s == '.' || (*s >= '0' && *s <= '9'))
646 *d++ = *s++;
647 else
648 s++;
649 }
650 *d = '\0';
651}
int form_yx_to_fidx(Form *, int, int)
#define FIELD_MAXLEN
Definition form.h:18
@ FF_DECIMAL_INT
Definition form.h:51
@ FF_STRING
Definition form.h:49
@ FF_HEX_INT
Definition form.h:53
@ FF_YYYYMMDD
Definition form.h:62
@ FF_HHMMSS
Definition form.h:64
@ FF_CURRENCY
Definition form.h:59
@ FF_FLOAT
Definition form.h:55
@ FF_DOUBLE
Definition form.h:57
@ FF_APR
Definition form.h:66
#define F_NOTBLANK
Definition form.h:21
Form * form
Definition mem.c:47
#define F_NOMETAS
Definition form.h:20
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:56
#define Ctrl(c)
Definition cm.h:34
#define TRUE
Definition iloan.c:19
#define FALSE
Definition iloan.c:18
int click_x
Definition dwin.c:49
int cp_nt_hl_rev
Definition dwin.c:151
int click_y
Definition dwin.c:48
int cp_nt_rev
Definition dwin.c:149
char ff_tbl[][26]
Definition fields.c:26
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:1651
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1162
void display_chyron(WINDOW *win, Chyron *chyron, int line, int col)
Display chyron on window.
Definition dwin.c:1476
void set_chyron_key_cp(Chyron *, int, char *, int, int)
Set chyron key with color pair (cp).
Definition dwin.c:1388
void compile_chyron(Chyron *)
construct the chyron string from the chyron structure
Definition dwin.c:1436
int form_fmt_field(Form *, char *)
Format field according to its format type.
Definition fields.c:417
int field_editor(Form *)
Accept input for a field.
Definition fields.c:55
void numeric(char *, char *)
Extract numeric characters from source string to destination string.
Definition fields.c:643
void right_justify(char *, int)
Right justify string by removing trailing spaces and adding leadingspaces.
Definition fields.c:580
bool is_valid_date(int, int, int)
Check if a given date is valid, including leap years.
Definition fields.c:606
void left_justify(char *)
Left justify string by removing leading spaces.
Definition fields.c:568
bool is_valid_time(int, int, int)
Check if a given time is valid.
Definition fields.c:627
int form_display_field_n(Form *, int)
Display field n.
Definition fields.c:348
void mk_filler(char *, int)
Create filler string for field.
Definition fields.c:551
int form_display_field(Form *)
Display current field.
Definition fields.c:366
int form_validate_field(Form *)
Validate current field based on flags.
Definition fields.c:522
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:435
size_t trim(char *)
Trims leading and trailing spaces from string s in place.
Definition futil.c:282
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:506
int l
Definition cm.h:280
int line
Definition form.h:115
char display_s[FIELD_MAXLEN]
Definition form.h:132
char accept_s[FIELD_MAXLEN]
Definition form.h:128
int ff
Definition form.h:121
int col
Definition form.h:117
char input_s[FIELD_MAXLEN]
Definition form.h:125
int len
Definition form.h:119
char filler_s[FIELD_MAXLEN]
Definition form.h:137
bool f_erase_remainder
Definition form.h:235
WINDOW * box
Definition form.h:156
Field * field[FIELD_MAXCNT]
Definition form.h:351
int lines
Definition form.h:149
int fidx
Definition form.h:308
char fill_char[2]
Definition form.h:297
Chyron * chyron
Definition form.h:363
WINDOW * win
Definition form.h:155