C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
Form Engine

Parses Form Descriptions, Handles User Input, and Integrates with External Commands for Calculations and Data Processing. More...

Functions

int init_form (Init *init, int argc, char **argv, int begy, int begx)
 Initialize form data structure and parse description file.
int form_engine (Init *init)
 Form main processing loop.
int form_post (Init *init)
 Handle post-processing after field entry, allowing user to edit data, execute a provider command, or write data to an output file.
int form_process (Init *init)
 Handle integration with a getter program which will provide field data.
int field_navigator (Form *form)
 Handle user input for field entry, allowing navigation between fields and looping until an exit action is selected.
unsigned int form_display_screen (Init *init)
 Display the form on the screen, including text elements and fields, and set up the form window based on the form configuration.
void form_display_fields (Form *form)
 Display form fields on the screen, populating field values and formatting them according to the form configuration.
int form_parse_desc (Form *form)
 Parse the form description file to populate the Form data structure with field definitions, text elements, and other configuration specified in the description file.
int form_read_data (Form *form)
 Read initial data for form fields from a specified input source, such as a file or standard input, and populate the form fields with the data.
int form_exec_cmd (Form *form)
 Execute a provider command specified in the form description file, passing form field values as arguments, and optionally redirecting output to a file.
int form_write (Form *form)
 Write form field values to a specified output destination, such as a file or standard output, based on the form configuration and user input.
int form_desc_error (int in_line_num, char *in_buf, char *em)
 Handle errors encountered while parsing the form description file, providing detailed error messages that include the file name, line number, and the specific error encountered.

Detailed Description

Parses Form Descriptions, Handles User Input, and Integrates with External Commands for Calculations and Data Processing.

Function Documentation

◆ field_navigator()

int field_navigator ( Form * form)

Handle user input for field entry, allowing navigation between fields and looping until an exit action is selected.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
An integer status code indicating the next action for the form processing loop (e.g., P_ACCEPT, P_HELP, P_CALC, P_CANCEL).
Note
This function manages user input for field entry, including navigation between fields and handling of special keys for accepting, canceling, requesting help, or performing calculations. The function loops until the user selects an exit action (e.g., accept or cancel).

Definition at line 400 of file form_engine.c.

400 {
401
402 if (form->fidx < 0)
403 return (-1);
404 while (1) {
406
407 switch (cmd_key) {
408 case KEY_F(10):
409 return (P_ACCEPT);
410 case KEY_F(1):
411 return (P_HELP);
412 case KEY_F(5):
413 if (form->f_process)
414 return (P_CALC);
415 break;
416 case KEY_F(9):
417 return (P_CANCEL);
418 case 'k':
419 case KEY_UP:
420 if (form->fidx != 0)
421 form->fidx--;
422 break;
423 case '\r':
424 case KEY_ENTER:
425 if (form->fidx < form->fcnt - 1)
426 form->fidx++;
427 else if (form->fidx == form->fcnt - 1)
428 return (P_ACCEPT);
429 break;
430 case 'j':
431 case KEY_DOWN:
432 if (form->fidx < form->fcnt - 1)
433 form->fidx++;
434 else if (form->fidx == form->fcnt - 1)
435 return (P_ACCEPT);
436 break;
437 case KEY_MOUSE:
438 break;
439 default:
440 break;
441 }
442 }
443}
@ P_HELP
Definition form.h:32
@ P_CALC
Definition form.h:38
@ P_ACCEPT
Definition form.h:30
@ P_CANCEL
Definition form.h:34
Form * form
Definition mem.c:47
unsigned int cmd_key
Definition dwin.c:117
int field_editor(Form *)
Accept input for a field.
Definition fields.c:59

References cmd_key, Form::f_process, Form::fcnt, Form::fidx, field_editor(), P_ACCEPT, P_CALC, P_CANCEL, and P_HELP.

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_desc_error()

int form_desc_error ( int in_line_num,
char * in_buf,
char * em )

Handle errors encountered while parsing the form description file, providing detailed error messages that include the file name, line number, and the specific error encountered.

Parameters
in_line_numThe line number in the description file where the error occurred.
in_bufThe content of the line that caused the error, for context.
emA specific error message describing the nature of the error.
Returns
An integer status code indicating how the user responded to the error message (e.g., which key they pressed to acknowledge the error).

Definition at line 876 of file form_engine.c.

876 {
877 int cmd_key;
878
879 ssnprintf(em0, MAXLEN - 1, "%s: %s", __FILE__, em);
880 ssnprintf(em1, MAXLEN - 1, "Desc file: %s, line: %d", form->mapp_spec,
881 in_line_num);
882 strnz__cpy(em2, in_buf, MAXLEN - 1);
883 cmd_key = display_error(em0, em1, em2, nullptr);
884 return cmd_key;
885}
#define MAXLEN
Definition curskeys.c:15
char em1[MAXLEN]
Definition dwin.c:133
char em0[MAXLEN]
Definition dwin.c:132
char em2[MAXLEN]
Definition dwin.c:134
int display_error(char *em0, char *em1, char *em2, char *em3)
Display an error message window or print to stderr.
Definition dwin.c:1054
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:269
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:147

References display_error(), em0, em1, em2, form, Form::mapp_spec, ssnprintf(), and strnz__cpy().

Referenced by form_parse_desc().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_display_fields()

void form_display_fields ( Form * form)

Display form fields on the screen, populating field values and formatting them according to the form configuration.

Parameters
formA pointer to the Form structure containing form data and state.
Note
This function iterates through the defined form fields, formats their display values based on the specified fill character and field length, and renders them on the form window. It also updates the chyron with available commands for user interaction.

Definition at line 510 of file form_engine.c.

510 {
511 int n;
512 char fill_char = form->fill_char[0];
513 for (n = 0; n < form->fcnt; n++) {
514 if (form->field[n]->col + form->field[n]->len + 2 > form->cols)
515 form->field[n]->len = form->cols - (form->field[n]->col + 2);
516 strnfill(form->field[n]->filler_s, fill_char, form->field[n]->len);
517 strnz(form->field[n]->display_s, form->field[n]->len);
519 }
520 form->chyron = new_chyron();
521 set_chyron_key(form->chyron, 1, "F1 Help", KEY_F(1));
522 set_chyron_key(form->chyron, 9, "F9 Cancel", KEY_F(9));
523 set_chyron_key(form->chyron, 10, "F10 Continue", KEY_F(10));
524 compile_chyron(form->chyron);
525 display_chyron(form->win, form->chyron, form->lines - 1, form->chyron->l);
526 return;
527}
void display_chyron(WINDOW *win, Chyron *chyron, int line, int col)
Definition dwin.c:297
void set_chyron_key(Chyron *, int, char *, int)
Definition dwin.c:245
void compile_chyron(Chyron *)
construct the chyron string from the chyron structure
Definition dwin.c:268
Chyron * new_chyron()
Create and initialize Chyron structure.
Definition dwin.c:183
int form_display_field_n(Form *, int)
Display field n.
Definition fields.c:351
bool strnfill(char *, char, int)
Fills string s with character c n.
Definition futil.c:440
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:340

References Form::chyron, Field::col, Form::cols, compile_chyron(), display_chyron(), Field::display_s, Form::fcnt, Form::field, Form::fill_char, Field::filler_s, form_display_field_n(), Chyron::l, Field::len, Form::lines, new_chyron(), set_chyron_key(), strnfill(), strnz(), and Form::win.

Referenced by form_display_screen(), and form_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_display_screen()

unsigned int form_display_screen ( Init * init)

Display the form on the screen, including text elements and fields, and set up the form window based on the form configuration.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while creating the form window or rendering the form elements.

Definition at line 460 of file form_engine.c.

460 {
461 int n;
462 char tmp_str[MAXLEN];
463
464 form = init->form;
465 form->lines = 0;
466 for (n = 0; n < form->dcnt; n++)
467 if (form->text[n]->line > form->lines)
468 form->lines = form->text[n]->line;
469 for (n = 0; n < form->fcnt; n++)
470 if (form->field[n]->line > form->lines)
471 form->lines = form->field[n]->line;
472 form->lines += 3;
473 if (form->lines > (LINES - form->begy))
474 form->lines = LINES - form->begy;
475 for (n = 0; n < form->fcnt; n++) {
476 if (form->field[n]->line >= (form->lines - 2))
477 form->fcnt = n;
478 }
479 form->cols += 2;
480 if (form->cols > (COLS - form->begx - 3))
481 form->cols = COLS - form->begx - 3;
482 if (win_new(form->lines, form->cols, form->begy, form->begx, form->title,
483 0)) {
484 strnz__cpy(tmp_str, "kwin_new failed: ", MAXLEN - 1);
485 strnz__cat(tmp_str, form->title, MAXLEN - 1);
486 Perror(tmp_str);
487 return (1);
488 }
489#ifdef NCDEBUG
490 immedok(form->win, TRUE);
491#endif
492 form->win = win_win[win_ptr];
493 form->box = win_box[win_ptr];
494 for (n = 0; n < form->dcnt; n++) {
495 strnz(form->text[n]->str, form->cols - 3);
496 mvwaddstr(form->win, form->text[n]->line, form->text[n]->col,
497 form->text[n]->str);
498 }
500 return 0;
501}
Init * init
Definition common.h:186
#define TRUE
Definition iloan.c:19
WINDOW * win_win[MAXWIN]
Definition dwin.c:114
int win_ptr
Definition dwin.c:121
WINDOW * win_box[MAXWIN]
Definition dwin.c:115
int win_new(int, int, int, int, char *, int)
Create a new window with optional box and title.
Definition dwin.c:783
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1110
void form_display_fields(Form *)
Display form fields on the screen, populating field values and formatting them according to the form ...
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:298

References Form::begx, Form::begy, Form::box, Text::col, Form::cols, Form::dcnt, Form::fcnt, Form::field, form, Init::form, form_display_fields(), Field::line, Text::line, Form::lines, Perror(), Text::str, strnz(), strnz__cat(), strnz__cpy(), Form::text, Form::title, Form::win, win_box, win_new(), win_ptr, and win_win.

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_engine()

int form_engine ( Init * init)

Form main processing loop.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
0 on successful completion, or a non-zero value if the user cancels the form or if an error occurs during processing.
  1. Parse the form description file to populate the form data structure.
  2. Read any initial data for the form fields from a specified input source.
  3. Display the form on the screen with the initial field values.
  4. Enter a loop to handle user input for field entry, calculation, help, and cancellation: a. If the user selects the accept action, perform any necessary calculations or post-processing, and then either return to field entry or exit the loop if the form is accepted. b. If the user selects the help action, display the help screen and return to the form after the user exits the help screen. c. If the user selects the cancel action, exit the loop and return a cancel status.

Definition at line 114 of file form_engine.c.

114 {
115 char tmp_str[MAXLEN];
116 int form_action;
117 int rc = 0;
118 char *eargv[MAXARGS];
119
120 form = init->form;
121 if (form == nullptr) {
122 Perror("FORM: form data structure is nullptr");
123 }
124 if (form_parse_desc(form)) {
125 return 0;
126 }
127
130 form->fidx = 0;
131 form_action = 0;
132 while (1) {
133 if (form_action == 0 || form_action == P_CONTINUE)
134 form_action = field_navigator(form);
135 switch (form_action) {
136 case P_ACCEPT:
137 if (form->f_process || form->f_calculate || form->f_query)
138 form_action = form_process(init);
139 else
140 form_action = form_post(init);
141 if (form_action == P_HELP || form_action == P_CANCEL ||
142 form_action == P_CONTINUE || form_action == P_END)
143 continue;
144 if (form_action == P_ACCEPT) {
145 form_action = P_END;
146 continue;
147 }
148 break;
149 case P_END:
150 if (form->f_out_spec || form->out_spec[0] != '\0')
151 rc = form_write(form);
152 if (form->f_receiver_cmd || form->receiver_cmd[0] != '\0')
153 rc = form_exec_cmd(form);
154 return rc;
155 case P_HELP:
156 if (form->f_help_spec && form->help_spec[0] != '\0')
157 strnz__cpy(tmp_str, form->help_spec, MAXLEN - 1);
158 else {
159 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
160 strnz__cat(tmp_str, "/", MAXLEN - 1);
161 strnz__cat(tmp_str, FORM_HELP_FILE, MAXLEN - 1);
162 }
163 eargc = 0;
164 eargv[eargc++] = strdup("view");
165 eargv[eargc++] = strdup("-N");
166 eargv[eargc++] = strdup("f");
167 eargv[eargc++] = strdup(tmp_str);
168 eargv[eargc] = nullptr;
169 init->lines = 30;
170 init->cols = 66;
171 init->begy = form->begy + 1;
172 init->begx = form->begx + 1;
173 strnz__cpy(init->title, "Form Help", MAXLEN - 1);
174 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
175 init->begx);
177 form_action = P_CONTINUE;
178 break;
179 case P_CANCEL:
180 return P_CANCEL;
181 default:
182 form_action = P_CONTINUE;
183 break;
184 }
185 }
186 return 0;
187}
@ P_CONTINUE
Definition form.h:28
@ P_END
Definition form.h:43
#define FORM_HELP_FILE
Definition common.h:37
int popup_view(Init *, int, char **, int, int, int, int)
Definition popups.c:47
int eargc
Definition futil.c:41
#define MAXARGS
Definition cm.h:30
char * eargv[MAXARGS]
Definition futil.c:42
int form_read_data(Form *)
Read initial data for form fields from a specified input source, such as a file or standard input,...
int form_parse_desc(Form *)
Parse the form description file to populate the Form data structure with field definitions,...
int form_write(Form *)
Write form field values to a specified output destination, such as a file or standard output,...
int form_process(Init *)
Handle integration with a getter program which will provide field data.
int form_exec_cmd(Form *)
Execute a provider command specified in the form description file, passing form field values as argum...
int form_post(Init *)
Handle post-processing after field entry, allowing user to edit data, execute a provider command,...
int field_navigator(Form *)
Handle user input for field entry, allowing navigation between fields and looping until an exit actio...
unsigned int form_display_screen(Init *)
Display the form on the screen, including text elements and fields, and set up the form window based ...
void destroy_argv(int argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:221

References Form::begx, Init::begx, Form::begy, Init::begy, Init::cols, destroy_argv(), eargc, Form::f_calculate, Form::f_help_spec, Form::f_out_spec, Form::f_process, Form::f_query, Form::f_receiver_cmd, Form::fidx, field_navigator(), form, Init::form, form_display_screen(), form_exec_cmd(), form_parse_desc(), form_post(), form_process(), form_read_data(), form_write(), Form::help_spec, Init::lines, Init::mapp_help, Form::out_spec, P_ACCEPT, P_CANCEL, P_CONTINUE, P_END, P_HELP, Perror(), popup_view(), Form::receiver_cmd, strnz__cat(), strnz__cpy(), and Init::title.

Referenced by init_form().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_exec_cmd()

int form_exec_cmd ( Form * form)

Execute a provider command specified in the form description file, passing form field values as arguments, and optionally redirecting output to a file.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while constructing or executing the command.

Definition at line 804 of file form_engine.c.

804 {
805 char earg_str[MAXLEN + 1];
806 int i;
807 strnz__cpy(earg_str, form->receiver_cmd, MAXLEN - 1);
808 for (i = 0; i < form->fcnt; i++) {
809 strnz__cat(earg_str, " ", MAXLEN - 1);
810 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
811 }
812 if (form->f_out_spec && form->f_process) {
813 strnz__cat(earg_str, " >", MAXLEN - 1);
814 strnz__cat(earg_str, form->out_spec, MAXLEN - 1);
815 }
817 return 0;
818}
char earg_str[MAXLEN]
Definition futil.c:40
int shell(char *)
Execute a shell command.
Definition exec.c:80

References Field::accept_s, Form::f_out_spec, Form::f_process, Form::fcnt, Form::field, Form::out_spec, Form::receiver_cmd, shell(), strnz__cat(), and strnz__cpy().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_parse_desc()

int form_parse_desc ( Form * form)

Parse the form description file to populate the Form data structure with field definitions, text elements, and other configuration specified in the description file.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while parsing the description file (e.g., file not found, invalid format, missing directives).

Definition at line 536 of file form_engine.c.

536 {
537 FILE *form_desc_fp;
538 char *token;
539 char *s;
540 int cols = 0;
541 int i, l;
542 int in_line_num = 0;
543 char in_buf[BUFSIZ];
544 char tmp_buf[BUFSIZ];
545 char *tmp_buf_p;
546 char tmp_str[BUFSIZ];
547 char delim[5];
548 char directive;
549
550 form_desc_fp = fopen(form->mapp_spec, "r");
551 if (form_desc_fp == nullptr) {
552 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
553 strnz__cpy(em1, "fopen ", MAXLEN - 1);
554 strnz__cat(em1, form->mapp_spec, MAXLEN - 1);
555 strerror_r(errno, em2, MAXLEN);
556 display_error(em0, em1, em2, nullptr);
557 return (1);
558 }
559 for (i = 0; i < FIELD_MAXCNT; i++) {
560 form->field[i] = calloc(1, sizeof(Field));
561 if (!form->field[i]) {
562 sprintf(tmp_str, "FORM: calloc failed for fields");
563 abend(EXIT_FAILURE, tmp_str);
564 }
565 }
566 for (i = 0; i < FIELD_MAXCNT; i++) {
567 form->text[i] = calloc(1, sizeof(Text));
568 if (!form->field[i]) {
569 sprintf(tmp_str, "FORM: calloc failed for text");
570 abend(EXIT_FAILURE, tmp_str);
571 }
572 }
573 form->didx = 0;
574 form->fidx = 0;
575 form->fcnt = 0;
576 form->cols = 34;
577 while ((fgets(in_buf, MAXLEN, form_desc_fp)) != nullptr) {
578 s = in_buf;
579 in_line_num++;
580 l = trim(in_buf);
581 if (l == 0)
582 continue;
583 if (*s == D_COMMENT)
584 continue;
585 delim[0] = '\n';
586 delim[1] = in_buf[1];
587 delim[2] = '\0';
588 strnz__cpy(tmp_buf, in_buf, MAXLEN - 1);
589 tmp_buf_p = tmp_buf;
590 if (!(token = strtok(tmp_buf_p, delim))) {
591 continue;
592 }
593 directive = *token;
594 switch ((int)directive) {
595 case D_COMMENT:
596 break;
597 case D_CALC:
598 form->f_calculate = true;
599 break;
600 case D_QUERY:
601 form->f_query = true;
602 break;
603 case D_GETTER:
604 form->f_process = true;
605 break;
606 case D_CMD:
607 if (!(token = strtok(nullptr, delim))) {
608 form_desc_error(in_line_num, in_buf,
609 "FORM: receiver_cmd delimiter");
610 continue;
611 }
612 strnz__cpy(form->receiver_cmd, token, MAXLEN - 1);
613 break;
614 case D_HELP:
615 if (!(token = strtok(nullptr, delim))) {
616 form_desc_error(in_line_num, in_buf,
617 "FORM: help_spec delimiter");
618 }
619 strnz__cpy(form->help_spec, token, MAXLEN - 1);
620 break;
621 case D_FIELD:
622 if (form->field[form->fidx] == nullptr) {
623 sprintf(tmp_str, "FORM: calloc failed for fields");
624 abend(EXIT_FAILURE, tmp_str);
625 }
626 if (!(token = strtok(nullptr, delim))) {
627 form_desc_error(in_line_num, in_buf,
628 "FORM: line number delimiter");
629 return 1;
630 }
631 form->field[form->fidx]->line = atoi(token);
632 if (form->field[form->fidx]->line < 0 ||
633 form->field[form->fidx]->line >= FIELD_MAXCNT) {
634 form_desc_error(in_line_num, in_buf,
635 "FORM: invalid line number");
636 return 1;
637 }
638 if (!(token = strtok(nullptr, delim))) {
639 form_desc_error(in_line_num, in_buf,
640 "FORM: column number delimiter");
641 return 1;
642 }
643 form->field[form->fidx]->col = atoi(token);
644 if (form->field[form->fidx]->col < 0 ||
645 form->field[form->fidx]->col >= FIELD_MAXLEN) {
646 form_desc_error(in_line_num, in_buf,
647 "FORM: invalid column number");
648 break;
649 }
650 if (!(token = strtok(nullptr, delim))) {
651 strnz__cpy(tmp_str, in_buf, MAXLEN - 1);
652 form_desc_error(in_line_num, tmp_str, "FORM: length delimiter");
653 break;
654 }
655 form->field[form->fidx]->len = atoi(token);
656 if (form->field[form->fidx]->len < 0 ||
657 form->field[form->fidx]->len > FIELD_MAXLEN) {
658 form_desc_error(in_line_num, in_buf, "FORM: invalid length");
659 break;
660 }
661 if (!(token = strtok(nullptr, delim))) {
662 form_desc_error(in_line_num, in_buf,
663 "FORM: validation code delimiter");
664 break;
665 }
666 form->field[form->fidx]->ff = -1;
667 for (i = 0; i < FF_INVALID; i++) {
668 str_to_lower(token);
670 if (!strcmp(token, ff_tbl[i])) {
671 form->field[form->fidx]->ff = i;
672 break;
673 }
674 }
675 if (form->field[form->fidx]->ff < 0 ||
676 form->field[form->fidx]->ff >= FF_INVALID) {
677 form_desc_error(in_line_num, in_buf,
678 "FORM: invalid format code");
679 break;
680 }
681 cols =
682 form->field[form->fidx]->col + form->field[form->fidx]->len + 1;
683 if (cols > form->cols)
684 form->cols = cols;
685 form->fidx++;
686 form->fcnt = form->fidx;
687 break;
688 case D_TEXT:
689 if (form->text[form->didx] == nullptr) {
690 sprintf(tmp_str, "FORM: calloc failed for text");
691 abend(EXIT_FAILURE, tmp_str);
692 }
693 if (!(token = strtok(nullptr, delim))) {
694 form_desc_error(in_line_num, in_buf,
695 "FORM: line number delimiter");
696 break;
697 }
698 form->text[form->didx]->line = atoi(token);
699 if (form->text[form->didx]->line < 0 ||
700 form->text[form->didx]->line >= FIELD_MAXCNT) {
701 form_desc_error(in_line_num, in_buf,
702 "FORM: invalid line number");
703 break;
704 }
705 if (!(token = strtok(nullptr, delim))) {
706 form_desc_error(in_line_num, in_buf,
707 "FORM: column number delimiter");
708 break;
709 }
710 form->text[form->didx]->col = atoi(token);
711 if (form->text[form->didx]->col < 0 ||
712 form->text[form->didx]->col >= FIELD_MAXLEN) {
713 form_desc_error(in_line_num, in_buf,
714 "FORM: invalid column number");
715 break;
716 }
717 if (!(token = strtok(nullptr, delim))) {
718 form_desc_error(in_line_num, in_buf, "FORM: text delimiter");
719 break;
720 }
721 strnz__cpy(form->text[form->didx]->str, token, MAXLEN - 1);
722 form->text[form->didx]->len = strlen(form->text[form->didx]->str);
723 if (form->text[form->didx]->len < 0 ||
724 form->text[form->didx]->len > FIELD_MAXLEN) {
725 form_desc_error(in_line_num, in_buf, "FORM: invalid length");
726 break;
727 }
728 cols =
729 form->text[form->didx]->col + form->text[form->didx]->len + 1;
730 if (cols > form->cols)
731 form->cols = cols;
732 form->didx++;
733 form->dcnt = form->didx;
734 break;
735 case D_HEADER:
736 if ((token = strtok(nullptr, delim))) {
737 strnz__cpy(form->title, token, MAXLEN - 1);
738 }
739 break;
740 default:
741 form_desc_error(in_line_num, in_buf, "invalid directive");
742 break;
743 }
744 }
745 fclose(form_desc_fp);
746 if (form->didx < 1 && form->fidx < 1) {
747 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__);
748 ssnprintf(em1, MAXLEN - 1, "%s", "Error in description file:");
749 ssnprintf(em2, MAXLEN - 1, "%s", form->mapp_spec);
750 display_error(em0, em1, em2, nullptr);
751 return (1);
752 }
753 return (0);
754}
#define FIELD_MAXLEN
Definition form.h:18
@ FF_INVALID
Definition form.h:69
#define FIELD_MAXCNT
Definition form.h:19
int cols
#define BUFSIZ
Definition view.h:29
#define D_CMD
Definition form_engine.c:26
#define D_FIELD
Definition form_engine.c:27
#define D_CALC
Definition form_engine.c:31
#define D_TEXT
Definition form_engine.c:28
#define D_HELP
Definition form_engine.c:29
#define D_QUERY
Definition form_engine.c:32
#define D_COMMENT
Definition form_engine.c:25
#define D_HEADER
Definition form_engine.c:30
#define D_GETTER
Definition form_engine.c:33
char ff_tbl[][26]
Definition fields.c:40
void abend(int, char *)
Abnormal program termination.
Definition dwin.c:1331
int form_desc_error(int, char *, char *)
Handle errors encountered while parsing the form description file, providing detailed error messages ...
size_t trim(char *)
Trims leading and trailing spaces from string s in place.
Definition futil.c:118
bool str_to_lower(char *)
Converts a string to lowercase.
Definition futil.c:233
structure for form fields
Definition form.h:101
structure for form fields
Definition form.h:114

References abend(), Field::col, Text::col, Form::cols, Form::dcnt, Form::didx, display_error(), em0, em1, em2, Form::f_calculate, Form::f_process, Form::f_query, Form::fcnt, Field::ff, FF_INVALID, ff_tbl, Form::fidx, Form::field, form_desc_error(), Form::help_spec, Field::len, Text::len, Field::line, Text::line, Form::mapp_spec, Form::receiver_cmd, ssnprintf(), Text::str, str_to_lower(), strnz__cat(), strnz__cpy(), Form::text, Form::title, and trim().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_post()

int form_post ( Init * init)

Handle post-processing after field entry, allowing user to edit data, execute a provider command, or write data to an output file.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
An integer status code indicating the next action for the form processing loop (e.g., P_CONTINUE, P_CANCEL, P_ACCEPT, P_HELP).

Definition at line 194 of file form_engine.c.

194 {
195 bool loop = true;
196 int c, rc;
197 click_y = click_x = -1;
198 form = init->form;
199 wmove(form->win, form->lines - 1, 0);
200 wclrtoeol(form->win);
201 unset_chyron_key(form->chyron, 18);
202 set_chyron_key(form->chyron, 8, "F8 Edit", KEY_F(8));
203 set_chyron_key(form->chyron, 10, "F10 Commit", KEY_F(10));
204 compile_chyron(form->chyron);
205 rc = -1;
206 while (loop) {
207 if (rc == -1) {
208 display_chyron(form->win, form->chyron, form->lines - 1,
209 form->chyron->l);
210 tcflush(2, TCIFLUSH);
211 c = xwgetch(form->win, form->chyron, -1);
212 }
213 switch (c) {
214 case KEY_F(1):
215 return P_HELP;
216 case KEY_F(8):
217 if (is_set_chyron_key(form->chyron, 8)) {
218 loop = false;
219 rc = P_CONTINUE;
220 break;
221 }
222 continue;
223 case KEY_F(9):
224 loop = false;
225 rc = P_CANCEL;
226 break;
227 case KEY_F(10):
228 loop = false;
229 rc = P_ACCEPT;
230 break;
231 case KEY_MOUSE:
232 continue;
233 default:
234 break;
235 }
236 }
237 unset_chyron_key(form->chyron, 8);
238 return rc;
239}
int click_x
Definition dwin.c:45
int click_y
Definition dwin.c:44
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:1359
bool is_set_chyron_key(Chyron *, int)
Check if function key label is set.
Definition dwin.c:217
void unset_chyron_key(Chyron *, int)
Unset chyron key.
Definition dwin.c:258

References Form::chyron, click_x, click_y, compile_chyron(), display_chyron(), form, Init::form, is_set_chyron_key(), Chyron::l, Form::lines, P_ACCEPT, P_CANCEL, P_CONTINUE, P_HELP, set_chyron_key(), unset_chyron_key(), Form::win, and xwgetch().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_process()

int form_process ( Init * init)

Handle integration with a getter program which will provide field data.

Parameters
initA pointer to the Init structure containing form data and state.
Returns
An integer status code indicating the next action for the form processing loop (e.g., P_CONTINUE, P_CANCEL, P_ACCEPT, P_HELP).

This function provides integration with getter programs. The requirements are:

  1. The form description file must have a line containing only 'C' (calculate), 'Q' (query), org 'G' (getter) to indicate that the form supports a getter.
  2. The form description file must specify the provider command using a line starting with '!' followed by the command and its arguments.
  3. The getter program must be able to accept field data from a file, from standard input, or as command line parameters.
  4. The getter program must output field values in a format that can be read by the form (e.g., one value per line), either to a file or to standard output.
     The sequence of operations is as follows:
    
     1. The 'C', 'Q', or 'G' option causes Form to pause and display an
    
    KEY_F(5) Calculate, Query, or Getter. option on the chyron.
  1. The user can then cancel the operation by pressing KEY_F(9) or activate the getter option by pressing KEY_F(5).
  2. Form outputs its data to file, standard output, or as command line parameters.
  3. Form executes the getter program.
  4. The getter program processes the data and outputs the results.
  5. Form reads the results and populates the appropriate form fields.
  6. Form presents the user with an option to edit the data, and the sequence restarts at 1.

This function forks and executes the getter executable as a child process, creates a pipe to read the output from the provider command, reads the output, and updates the Form fields.

Definition at line 278 of file form_engine.c.

278 {
279 int i, c, rc;
280 char tmp_str[MAXLEN];
281 char earg_str[MAXLEN + 1];
282 char *eargv[MAXARGS];
283 char file_spec[MAXLEN];
284 bool loop = true;
285 pid_t pid;
286 int pipe_fd[2];
287
288 form = init->form;
289 wmove(form->win, form->lines - 1, 0);
290 wclrtoeol(form->win);
291 unset_chyron_key(form->chyron, 18);
292 unset_chyron_key(form->chyron, 10);
293 strnz__cpy(tmp_str, "F5 ", MAXLEN - 1);
294
295 if (form->f_process)
296 strnz__cat(tmp_str, "Process", MAXLEN - 1);
297 else if (form->f_calculate)
298 strnz__cat(tmp_str, "Calculate", MAXLEN - 1);
299 else if (form->f_query)
300 strnz__cat(tmp_str, "Query", MAXLEN - 1);
301 set_chyron_key_cp(form->chyron, 5, tmp_str, KEY_F(5), cp_reverse_highlight);
302
303 while (loop) {
304 compile_chyron(form->chyron);
305 display_chyron(form->win, form->chyron, form->lines - 1,
306 form->chyron->l);
307 click_y = click_x = -1;
308 tcflush(2, TCIFLUSH);
309 c = xwgetch(form->win, form->chyron, -1);
310 switch (c) {
311 case KEY_F(1):
312 return P_HELP;
313 case KEY_F(5):
314 if (form->f_out_spec)
316 if (form->f_provider_cmd) {
317 strnz__cpy(earg_str, form->provider_cmd, MAXLEN - 1);
318 for (i = 0; i < form->fcnt; i++) {
319 strnz__cat(earg_str, " ", MAXLEN - 1);
320 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
321 }
323 strnz__cpy(file_spec, eargv[0], MAXLEN - 1);
324 base_name(eargv[0], file_spec);
325 if (pipe(pipe_fd) == -1) {
327 Perror("pipe(pipe_fd) failed in init_form");
328 return (1);
329 }
330 if ((pid = fork()) == -1) {
332 Perror("fork() failed in init_form");
333 return (1);
334 }
335 if (pid == 0) { // Child
336 close(pipe_fd[P_READ]);
337 dup2(pipe_fd[P_WRITE], STDOUT_FILENO);
338 close(pipe_fd[P_WRITE]);
339 execvp(eargv[0], eargv);
340 ssnprintf(em0, MAXLEN, "%s, line: %d", __FILE__,
341 __LINE__ - 2);
342 strnz__cpy(em1, "execvp(", MAXLEN - 1);
343 strnz__cat(em1, eargv[0], MAXLEN - 1);
344 strnz__cat(em1, ", ", MAXLEN - 1);
346 strnz__cat(em1, ")", MAXLEN - 1);
347 strerror_r(errno, em2, MAXLEN);
348 display_error(em0, em1, em2, nullptr);
349 exit(EXIT_FAILURE);
350 } // Back to parent
351 close(pipe_fd[P_WRITE]);
352 form->in_fp = fdopen(pipe_fd[P_READ], "rb");
353 form->f_in_pipe = true;
355 close(pipe_fd[P_READ]);
359 set_chyron_key(form->chyron, 8, "F5 Edit", KEY_F(5));
360 set_chyron_key(form->chyron, 10, "F10 Commit", KEY_F(10));
361 compile_chyron(form->chyron);
362 continue;
363 }
364 break;
365 case KEY_F(8):
366 if (is_set_chyron_key(form->chyron, 8)) {
367 loop = false;
368 rc = P_CONTINUE;
369 break;
370 }
371 continue;
372 case KEY_F(9):
373 loop = false;
374 rc = P_CANCEL;
375 break;
376 case KEY_F(10):
377 loop = false;
378 rc = P_ACCEPT;
379 break;
380 case KEY_MOUSE:
381 break;
382 default:
383 break;
384 }
385 }
386 unset_chyron_key(form->chyron, 8);
387 unset_chyron_key(form->chyron, 5);
388 return rc;
389}
#define P_READ
Definition common.h:50
#define P_WRITE
Definition common.h:51
int wait_timeout
Definition futil.c:98
int pipe_fd[2]
Definition pick_engine.c:39
bool waitpid_with_timeout(pid_t pid, int timeout)
Definition dwin.c:1431
int cp_reverse_highlight
Definition dwin.c:140
void set_chyron_key_cp(Chyron *, int, char *, int, int)
Set chyron key.
Definition dwin.c:237
bool base_name(char *, char *)
Returns the base name of a file specification.
Definition futil.c:775
int str_to_args(char **, char *, int)
Converts a string into an array of argument strings.
Definition futil.c:167

References Field::accept_s, base_name(), Form::chyron, click_x, click_y, compile_chyron(), cp_reverse_highlight, destroy_argv(), display_chyron(), display_error(), eargc, em0, em1, em2, Form::f_calculate, Form::f_in_pipe, Form::f_out_spec, Form::f_process, Form::f_provider_cmd, Form::f_query, Form::fcnt, Form::field, form, Init::form, form_display_fields(), form_read_data(), form_write(), Form::in_fp, is_set_chyron_key(), Chyron::l, Form::lines, P_ACCEPT, P_CANCEL, P_CONTINUE, P_HELP, Perror(), Form::provider_cmd, set_chyron_key(), set_chyron_key_cp(), ssnprintf(), str_to_args(), strnz__cat(), strnz__cpy(), unset_chyron_key(), wait_timeout, waitpid_with_timeout(), Form::win, and xwgetch().

Referenced by form_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_read_data()

int form_read_data ( Form * form)

Read initial data for form fields from a specified input source, such as a file or standard input, and populate the form fields with the data.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while reading the data or if the specified input source is invalid or empty.

Definition at line 761 of file form_engine.c.

761 {
762 struct stat sb;
763 char in_buf[MAXLEN];
764 char field[MAXLEN];
765
766 if (!form->f_in_pipe) {
767 if (form->f_in_spec && form->in_spec[0] != '\0') {
768 if ((lstat(form->in_spec, &sb) == -1) || (sb.st_size == 0) ||
769 ((form->in_fp = fopen(form->in_spec, "rb")) == nullptr)) {
770 strnz__cat(em0, form->in_spec, MAXLEN - 1);
771 if (sb.st_size == 0)
772 strnz__cpy(em1, "File is empty", MAXLEN - 1);
773 else
774 strnz__cpy(em1, "File does not exist", MAXLEN - 1);
775 strnz__cpy(em2, "Fields will be blank or zero", MAXLEN - 1);
776 cmd_key = display_error(em0, em1, em2, nullptr);
777 if (cmd_key == KEY_F(9))
778 return (1);
779 }
780 if (form->in_fp == nullptr)
781 return (1);
782 } else
783 return (0);
784 }
785 form->fidx = 0;
786 if (form->in_fp != nullptr) {
787 while ((fgets(in_buf, MAXLEN, form->in_fp)) != nullptr) {
788 if (form->fidx < FIELD_MAXCNT)
789 strnz__cpy(field, in_buf, MAXLEN - 1);
790 form_fmt_field(form, field);
791 form->fidx++;
792 }
793 fclose(form->in_fp);
794 }
795 return (0);
796}
int form_fmt_field(Form *, char *)
Format field according to its format type.
Definition fields.c:421

References cmd_key, display_error(), em0, em1, em2, Form::f_in_pipe, Form::f_in_spec, Form::fidx, form_fmt_field(), Form::in_fp, Form::in_spec, strnz__cat(), and strnz__cpy().

Referenced by form_engine(), and form_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ form_write()

int form_write ( Form * form)

Write form field values to a specified output destination, such as a file or standard output, based on the form configuration and user input.

Parameters
formA pointer to the Form structure containing form data and state.
Returns
0 on success, or a non-zero value if an error occurs while writing the data or if the specified output destination is invalid.

Definition at line 825 of file form_engine.c.

825 {
826 int n;
827 if (form->out_spec[0] == '\0' || strcmp(form->out_spec, "-") == 0 ||
828 strcmp(form->out_spec, "/dev/stdout") == 0) {
829 strnz__cpy(form->out_spec, "/dev/stdout", MAXLEN - 1);
830 close(form->out_fd);
831 form->out_fd = open(form->out_spec, O_CREAT | O_RDWR | O_TRUNC, 0644);
832 if (form->out_fd == -1) {
833 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
834 strnz__cpy(em1, "open ", MAXLEN - 1);
835 strnz__cat(em1, form->out_spec, MAXLEN - 1);
836 strerror_r(errno, em2, MAXLEN);
837 display_error(em0, em1, em2, nullptr);
838 return (1);
839 }
840 dup2(form->out_fd, STDOUT_FILENO);
841 form->out_fp = fdopen(STDOUT_FILENO, "w");
842 form->f_out_spec = true;
843 form->f_out_pipe = true;
844 } else {
845 if ((form->out_fp = fopen(form->out_spec, "w")) == nullptr) {
846 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
847 strerror_r(errno, em2, MAXLEN);
848 display_error(em0, em1, em2, nullptr);
849 return (1);
850 }
851 }
852 if (form->out_fp == nullptr) {
853 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
854 strnz__cpy(em1, "fopen ", MAXLEN - 1);
855 strnz__cat(em1, form->out_spec, MAXLEN - 1);
856 strerror_r(errno, em2, MAXLEN);
857 display_error(em0, em1, em2, nullptr);
858 return (1);
859 }
860 for (n = 0; n < form->fcnt; n++)
861 fprintf(form->out_fp, "%s\n", form->field[n]->accept_s);
862 if (form->out_fp != nullptr)
863 fclose(form->out_fp);
864 return (0);
865}

References Field::accept_s, display_error(), em0, em1, em2, Form::f_out_pipe, Form::f_out_spec, Form::fcnt, Form::field, Form::out_fd, Form::out_fp, Form::out_spec, ssnprintf(), strnz__cat(), and strnz__cpy().

Referenced by form_engine(), and form_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_form()

int init_form ( Init * init,
int argc,
char ** argv,
int begy,
int begx )

Initialize form data structure and parse description file.

Parameters
initA pointer to the Init structure containing form data and state.
argcThe number of command line arguments passed to the form.
argvThe array of command line arguments passed to the form.
begyThe y-coordinate for the top-left corner of the form window.
begxThe x-coordinate for the top-left corner of the form window.
Returns
0 on success, or a non-zero value if an error occurs during

Definition at line 59 of file form_engine.c.

59 {
60 int rc;
61 char tmp_str[MAXLEN];
62 if (init->form != nullptr)
64 init->form = new_form(init, argc, argv, begy, begx);
65 form = init->form;
66 if (!form->f_mapp_spec) {
67 if (form->mapp_spec[0] == '\0') {
68 rc = Perror("Error: No form specification file given");
69 } else {
70 strnz__cpy(tmp_str, "form->mapp_spec: ", MAXLEN - 1);
71 strnz__cat(tmp_str, form->mapp_spec, MAXLEN - 1);
72 strnz__cat(tmp_str, " not found", MAXLEN - 1);
73 rc = Perror(tmp_str);
74 }
76 return rc;
77 }
78 if (begy != 0)
79 form->begy = begy;
80 if (begx != 0)
81 form->begx = begx;
82 if ((form->f_in_spec && (form->in_spec[0] == '\0')) ||
83 (strcmp(form->in_spec, "-") == 0) ||
84 strcmp(form->in_spec, "/dev/stdin") == 0) {
85 strnz__cpy(form->in_spec, "/dev/stdin", MAXLEN - 1);
86 form->f_in_pipe = true;
87 }
88 if (form->title[0] == '\0')
89 strnz__cpy(form->title, form->in_spec, MAXLEN - 1);
90 rc = form_engine(init);
91 if (form->win)
92 win_del();
93 destroy_chyron(form->chyron);
94 return rc;
95}
int begx
int begy
WINDOW * win_del()
Delete the current window and its associated box window.
Definition dwin.c:902
Chyron * destroy_chyron(Chyron *chyron)
Destroy Chyron structure.
Definition dwin.c:198
int form_engine(Init *)
Form main processing loop.
Form * new_form(Init *, int, char **, int, int)
Create and initialize Form structure.
Definition mem.c:253
Form * destroy_form(Init *init)
Destroy Form structure.
Definition mem.c:276

References Form::begx, Form::begy, Form::chyron, destroy_chyron(), destroy_form(), Form::f_in_pipe, Form::f_in_spec, Form::f_mapp_spec, form, Init::form, form_engine(), Form::in_spec, Form::mapp_spec, new_form(), Perror(), strnz__cat(), strnz__cpy(), Form::title, Form::win, and win_del().

Referenced by main(), and popup_form().

Here is the call graph for this function:
Here is the caller graph for this function: