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