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

unsigned int display_form (Init *init)
 Display the form on the screen, including text elements and fields, and set up the form window based on the form configuration.
int field_navigator (Form *form)
 Handle user input for field entry, allowing navigation between fields and looping until an exit action is selected.
int form_desc_error (Form *form, 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.
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_engine (Init *init)
 Form main processing loop.
int form_exec_cmd (Form *form)
 Execute a command specified in the form description file, passing form field values as arguments, and optionally redirecting output to a file.
int form_exec_receiver (Init *init)
 Execute a command specified by the -R option on the form command line.
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_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 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_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 init_form (Init *init, int argc, char **argv, int begy, int begx)
 Initialize form data structure and parse description file.

Detailed Description

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

Function Documentation

◆ display_form()

unsigned int display_form ( 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 525 of file form_engine.c.

525 {
526 int n, flin, fcol;
527 char tmp_str[MAXLEN];
528
529 Form *form = init->form;
530 form->lines = 0;
531 for (n = 0; n < form->dcnt; n++)
532 if (form->text[n]->line > form->lines)
533 form->lines = form->text[n]->line;
534 for (n = 0; n < form->fcnt; n++)
535 if (form->field[n]->line > form->lines)
536 form->lines = form->field[n]->line;
537 form->lines += 3;
538 if (form->lines > (LINES - form->begy))
539 form->lines = LINES - form->begy;
540 for (n = 0; n < form->fcnt; n++) {
541 if (form->field[n]->line >= (form->lines - 2))
542 form->fcnt = n;
543 }
544 form->cols += 2;
545 if (form->cols > (COLS - form->begx - 3))
546 form->cols = COLS - form->begx - 3;
547 if (box_new(form->lines, form->cols, form->begy, form->begx, form->title)) {
548 strnz__cpy(tmp_str, "box_new failed: ", MAXLEN - 1);
549 strnz__cat(tmp_str, form->title, MAXLEN - 1);
550 Perror(tmp_str);
551 return (1);
552 }
553 form->box = win_box[win_ptr];
554 form->win = win_win[win_ptr];
555#ifdef DEBUG_IMMEDOK
556 immedok(form->win, true);
557 immedok(form->box, true);
558#endif
559 // wnoutrefresh(form->win);
560 // display field brackets if specified in the form description
561 for (form->fidx = 0; form->fidx < form->fcnt; form->fidx++) {
562 if (form->brackets[0] != '\0' && form->brackets[1] != '\0') {
563 flin = form->field[form->fidx]->line + 1;
564 fcol = form->field[form->fidx]->col;
565 mvwadd_wch(form->box, flin, fcol, &form->brktl);
566 fcol += form->field[form->fidx]->len + 1;
567 mvwadd_wch(form->box, flin, fcol, &form->brktr);
568 // wnoutrefresh(form->box);
569 }
570 }
571 for (n = 0; n < form->dcnt; n++) {
572 strnz(form->text[n]->str, form->cols - 3);
573 mvwaddstr(form->win, form->text[n]->line, form->text[n]->col,
574 form->text[n]->str);
575 // wnoutrefresh(form->win);
576 }
577 update_panels();
579 return 0;
580}
WINDOW * win_win[MAXWIN]
Definition dwin.c:52
int win_ptr
Definition dwin.c:164
WINDOW * win_box[MAXWIN]
Definition dwin.c:53
Form * form
Definition mem.c:48
#define MAXLEN
Definition curskeys.c:15
int box_new(int, int, int, int, char *)
Create a new window with optional box and title.
Definition dwin.c:967
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1526
void form_display_fields(Form *)
Display form fields on the screen, populating field values and formatting them according to the form ...
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:544
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:615
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:573
Form * form
Definition common.h:184
Definition form.h:145

References Form::begx, Form::begy, Form::box, box_new(), Form::brackets, Form::brktl, Form::brktr, Field::col, Text::col, Form::cols, Form::dcnt, Form::fcnt, Form::fidx, Form::field, Init::form, form_display_fields(), Field::len, Field::line, Text::line, Form::lines, Perror(), Text::str, strnz(), strnz__cat(), strnz__cpy(), Form::text, Form::title, Form::win, win_box, 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:

◆ 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., FA_ACCEPT, FA_HELP, FA_CALC, FA_CANCEL).

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 464 of file form_engine.c.

464 {
465
466 if (form->fidx < 0 || form->fidx >= form->fcnt)
467 form->fidx = 0;
468 while (1) {
470 switch (cmd_key) {
471 case KEY_F(1): // F1 Help
472 return (FA_HELP);
473 case KEY_F(2): // F2 Process
474 case KEY_F(3): // F3 Calculate
475 case KEY_F(4): // F4 Query
476 if (form->f_process)
477 return (FA_CALC);
478 break;
479 case KEY_F(9): // F9 Cancel
480 return (FA_CANCEL);
481 case KEY_F(10): // F10 Accept
482 return (FA_ACCEPT);
483 case 'k':
484 case KEY_UP:
485 if (form->fidx != 0)
486 form->fidx--;
487 break;
488 case '\r':
489 case KEY_ENTER:
490 if (form->fidx < form->fcnt - 1)
491 form->fidx++;
492 else if (form->fidx == form->fcnt - 1)
493 return (FA_ACCEPT);
494 break;
495 case 'j':
496 case KEY_DOWN:
497 if (form->fidx < form->fcnt - 1)
498 form->fidx++;
499 else if (form->fidx == form->fcnt - 1)
500 return (FA_ACCEPT);
501 break;
502 case KEY_MOUSE:
503 break;
504 default:
505 break;
506 }
507 }
508}
@ FA_ACCEPT
Definition form.h:29
@ FA_CALC
Definition form.h:37
@ FA_HELP
Definition form.h:31
@ FA_CANCEL
Definition form.h:33
unsigned int cmd_key
Definition dwin.c:160
int field_editor(Form *)
Accept input for a field.
Definition fields.c:55

References Form::f_process, FA_ACCEPT, FA_CALC, FA_CANCEL, FA_HELP, Form::fcnt, Form::fidx, and field_editor().

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 ( Form * form,
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
formA pointer to the Form structure containing form data and state.
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 1152 of file form_engine.c.

1152 {
1153 int cmd_key;
1154 ssnprintf(em0, MAXLEN - 1, "%s: %s", __FILE__, em);
1155 ssnprintf(em1, MAXLEN - 1, "Desc file: %s, line: %d", form->mapp_spec,
1156 in_line_num);
1157 strnz__cpy(em2, in_buf, MAXLEN - 1);
1158 cmd_key = display_error(em0, em1, em2, nullptr);
1159 return cmd_key;
1160}
char em1[MAXLEN]
Definition dwin.c:176
char em0[MAXLEN]
Definition dwin.c:175
char em2[MAXLEN]
Definition dwin.c:177
int display_error(char *, char *, char *, char *)
Display an error message window or print to stderr.
Definition dwin.c:1467
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:420

References display_error(), em0, em1, em2, 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.

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 590 of file form_engine.c.

590 {
591 int y, x;
592 for (form->fidx = 0; form->fidx < form->fcnt; form->fidx++) {
593 if (form->field[form->fidx]->col + form->field[form->fidx]->len + 2 >
594 form->cols)
595 form->field[form->fidx]->len =
596 form->cols - (form->field[form->fidx]->col + 2);
597 // Make filler_cc
598 size_t fl = form->field[form->fidx]->len;
599 char *d = form->field[form->fidx]->filler_s;
600 size_t char_bytes = strlen(form->fill_char);
601 for (size_t i = 0; i < fl; i++) {
602 memcpy(d, form->fill_char, char_bytes);
603 d += char_bytes;
604 }
605 d = nullptr;
606
607 if (form->field[form->fidx]->accept_s[0] != '\0') {
608 strnz(form->field[form->fidx]->accept_s, form->field[form->fidx]->len);
609 // d = form->field[form->fidx]->accept_s;
610 } else {
611 memset(form->field[form->fidx]->accept_s, 0, MAXLEN);
612 // d = form->field[form->fidx]->accept_s;
613 }
614 strnz(form->field[form->fidx]->display_s, form->field[form->fidx]->len);
615
616 y = form->field[form->fidx]->line;
617 x = form->field[form->fidx]->col;
618
619 str_to_cc(form->field[form->fidx]->filler_cc, form->field[form->fidx]->filler_s, WA_NORMAL, cp_fill_char, form->field[form->fidx]->len);
620
621 mvwadd_wchstr(form->win, y, x, form->field[form->fidx]->filler_cc);
622
623 str_to_cc(form->field[form->fidx]->display_cc, form->field[form->fidx]->display_s, WA_NORMAL, cp_nt, form->field[form->fidx]->len);
624
625 mvwadd_wchnstr(form->win, y, x, form->field[form->fidx]->display_cc, form->field[form->fidx]->len);
626 update_panels();
627 doupdate();
628 }
629 return;
630}
int cp_nt
Definition dwin.c:183
int cp_fill_char
Definition dwin.c:189
size_t str_to_cc(cchar_t *, const char *, attr_t, int, size_t)
Convert a multibyte string to an array of cchar_t complex characters.
Definition dwin.c:786

References Field::accept_s, Field::col, Form::cols, cp_fill_char, cp_nt, Field::display_cc, Field::display_s, Form::fcnt, Form::fidx, Form::field, Form::fill_char, Field::filler_cc, Field::filler_s, Field::len, Field::line, str_to_cc(), strnz(), and Form::win.

Referenced by display_form(), and form_process().

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 120 of file form_engine.c.

120 {
121 char tmp_str[MAXLEN];
122 int form_action;
123 char *eargv[MAXARGS];
124 int eargc;
125
126 Form *form = init->form;
127 if (form == nullptr) {
128 Perror("FORM: form data structure is nullptr");
129 }
130 if (form_parse_desc(form)) {
131 return 0;
132 }
133
135 display_form(init);
136 form->chyron = new_chyron();
137 set_chyron_key(form->chyron, 1, "F1 Help", KEY_F(1));
138 set_chyron_key_cp(form->chyron, 2, "F2 Process", KEY_F(2), cp_nt_hl_rev);
139 set_chyron_key_cp(form->chyron, 3, "F3 Calculate", KEY_F(3), cp_nt_hl_rev);
140 set_chyron_key_cp(form->chyron, 4, "F4 Query", KEY_F(4), cp_nt_hl_rev);
141 set_chyron_key_cp(form->chyron, 5, "F5 Edit", KEY_F(5), cp_nt_hl_rev);
142 set_chyron_key(form->chyron, 9, "F9 Cancel", KEY_F(9));
143 set_chyron_key(form->chyron, 10, "F10 Accept", KEY_F(10));
144 set_chyron_key(form->chyron, 18, "INS", KEY_IC);
145 form->chyron->key[2]->active = false; // F2 Process
146 form->chyron->key[3]->active = false; // F3 Calculate
147 form->chyron->key[4]->active = false; // F4 Query
148 form->chyron->key[5]->active = false; // F5 Edit
149 form->chyron->key[18]->active = false; // Insert
150 compile_chyron(form->chyron);
151 display_chyron(form->win, form->chyron, form->lines - 1, form->chyron->l);
152 // 1 F1 Help
153 // 2 F2 Process
154 // 3 F3 Calculate
155 // 4 F4 Query
156 // 5 F5 Edit
157 // 9 F9 Cancel
158 // 10 F10 Accept
159 form->fidx = 0;
160 form_action = 0;
161 while (1) {
162 if (form_action == 0 || form_action == FA_CONTINUE)
163 form_action = field_navigator(form);
164 form->chyron->key[18]->active = false; // Insert
165 switch (form_action) {
166 case FA_ACCEPT:
167 if (form->f_process || form->f_calculate || form->f_query)
168 form_action = form_process(init);
169 else
170 form_action = form_post(init);
171 if (form_action == FA_HELP || form_action == FA_CANCEL ||
172 form_action == FA_CONTINUE || form_action == FA_END)
173 continue;
174 if (form_action == FA_ACCEPT) {
175 form_action = FA_END;
176 continue;
177 }
178 break;
179 case FA_END:
180 if (form->f_out_spec || form->out_spec[0] != '\0')
182 if (form->f_receiver_cmd || form->receiver_cmd[0] != '\0')
183 form_exec_receiver(init);
184 break;
185 case FA_HELP:
186 if (form->f_help_spec && form->help_spec[0] != '\0')
187 strnz__cpy(tmp_str, form->help_spec, MAXLEN - 1);
188 else {
189 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
190 strnz__cat(tmp_str, "/", MAXLEN - 1);
191 strnz__cat(tmp_str, FORM_HELP_FILE, MAXLEN - 1);
192 }
193 eargc = 0;
194 eargv[eargc++] = strdup("view");
195 eargv[eargc++] = strdup("-Nf");
196 eargv[eargc++] = strdup(tmp_str);
197 eargv[eargc] = nullptr;
198 init->lines = 30;
199 init->cols = 66;
200 init->begy = form->begy + 1;
201 init->begx = form->begx + 1;
202 strnz__cpy(init->title, "Form Help", MAXLEN - 1);
203 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
204 init->begx);
206 form_action = FA_CONTINUE;
207 break;
208 case FA_CANCEL:
209 return FA_CANCEL;
210 default:
211 form_action = FA_CONTINUE;
212 break;
213 }
214 if (form_action == FA_END)
215 break;
216 }
217 return 0;
218}
@ FA_END
Definition form.h:42
@ FA_CONTINUE
Definition form.h:27
#define FORM_HELP_FILE
Definition common.h:33
int popup_view(Init *, int, char **, int, int, int, int)
instantiate a view popup window
Definition popups.c:144
#define MAXARGS
Definition cm.h:48
int cp_nt_hl_rev
Definition dwin.c:186
int eargc
Definition futil.c:57
char * eargv[MAXARGS]
Definition futil.c:58
void set_chyron_key(Chyron *, int, char *, int)
Set chyron key with default color pair (cp_nt_rev).
Definition dwin.c:1783
void display_chyron(WINDOW *, Chyron *, int, int)
Display chyron on window.
Definition dwin.c:1892
void set_chyron_key_cp(Chyron *, int, char *, int, int)
Set chyron key with color pair (cp).
Definition dwin.c:1759
void compile_chyron(Chyron *)
construct the chyron string from the chyron structure
Definition dwin.c:1848
Chyron * new_chyron()
Create and initialize Chyron structure.
Definition dwin.c:1701
int form_exec_receiver(Init *)
Execute a command specified by the -R option on the form command line.
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_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 display_form(Init *)
Display the form on the screen, including text elements and fields, and set up the form window based ...
int destroy_argv(int argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:494
char title[MAXLEN]
Definition common.h:129
char mapp_help[MAXLEN]
Definition common.h:148
int begx
Definition common.h:118
int cols
Definition common.h:116
int begy
Definition common.h:117
int lines
Definition common.h:115

References ChyronKey::active, Form::begx, Init::begx, Form::begy, Init::begy, Form::chyron, Init::cols, compile_chyron(), cp_nt_hl_rev, destroy_argv(), display_chyron(), display_form(), Form::f_calculate, Form::f_help_spec, Form::f_out_spec, Form::f_process, Form::f_query, Form::f_receiver_cmd, FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_END, FA_HELP, Form::fidx, field_navigator(), Init::form, form_exec_receiver(), form_parse_desc(), form_post(), form_process(), form_read_data(), form_write(), Form::help_spec, Chyron::key, Chyron::l, Form::lines, Init::lines, Init::mapp_help, new_chyron(), Form::out_spec, Perror(), popup_view(), Form::receiver_cmd, set_chyron_key(), set_chyron_key_cp(), strnz__cat(), strnz__cpy(), Init::title, and Form::win.

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 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 910 of file form_engine.c.

910 {
911 char earg_str[MAXLEN + 1];
912 int i;
913 strnz__cpy(earg_str, form->receiver_cmd, MAXLEN - 1);
914 for (i = 0; i < form->fcnt; i++) {
915 strnz__cat(earg_str, " ", MAXLEN - 1);
916 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
917 }
918 if (form->f_out_spec && form->f_process) {
919 strnz__cat(earg_str, " >", MAXLEN - 1);
920 strnz__cat(earg_str, form->out_spec, MAXLEN - 1);
921 }
923 return 0;
924}
char earg_str[MAXLEN]
Definition futil.c:56
int shell(char *)
Execute a shell command.
Definition exec.c:78

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().

Here is the call graph for this function:

◆ form_exec_receiver()

int form_exec_receiver ( Init * init)

Execute a command specified by the -R option on the form command line.

Parameters
initA pointer to the Init structure
Returns
0 on success, or a non-zero value if an error occurs while constructing or executing the command.

This function constructs a command by taking the receiver_cmd appending field values as arguments, and handling special cases such as multiple command arguments or placeholder substitution. It then executes the command, either displaying the output in a popup view if the command is "view", or executing it directly in a child process for other commands. The function also handles error cases and ensures that resources are properly freed.

This is the line that gets the selected objects

initialize popup_view arguments and execute popup_view to display command output within form interface

fork failed, free eargv and return error

Prevent child process from writing to terminal

Child process to execute command

If execvp returns, it means execution failed, so free eargv and print error message before exiting

Definition at line 937 of file form_engine.c.

937 {
938 int rc = -1;
939 int eargc;
940 char *eargv[MAXARGS];
941 char tmp_str[MAXLEN] = {'\0'};
942 char title[MAXLEN];
943 char sav_arg[MAXLEN];
944 char *out_s;
945 int eargx = 0;
946 int i = 0;
947 pid_t pid = 0;
948 bool f_append_values = false;
949
950 title[0] = '\0';
951 Form *form = init->form;
952 if (form->receiver_cmd[0] == '\0')
953 return -1;
954 // Eliminate leading and trailing quotes
955 if (form->receiver_cmd[0] == '\\' || form->receiver_cmd[0] == '\"') {
956 size_t len = strlen(form->receiver_cmd);
957 if (len > 1 && form->receiver_cmd[len - 1] == '\"') {
958 memmove(form->receiver_cmd, form->receiver_cmd + 1, len - 2);
959 form->receiver_cmd[len - 2] = '\0';
960 }
961 }
962 eargc = str_to_args(eargv, form->receiver_cmd, MAXARGS - 1);
963 tmp_str[0] = '\0';
964 if (form->f_multiple_cmd_args) {
965 // concatenate fields into a single argument
966 for (i = 0; i < form->fcnt; i++) {
967 if (form->field[i]->accept_s[0] && eargc < MAXARGS) {
968 if (tmp_str[0] != '\0')
969 strnz__cat(tmp_str, " ", MAXLEN - 1);
970 strnz__cat(tmp_str, form->field[i]->accept_s, MAXLEN - 1);
971 }
972 }
973 eargv[eargc++] = strdup(tmp_str);
974 } else {
975 f_append_values = false;
976 // find lines with "%%" to determine where to insert field values
977 i = 0;
978 while (i < eargc) {
980 if (strstr(eargv[i], "%%") != nullptr) {
981 tmp_str[0] = '\0';
982 f_append_values = true;
983 strnz__cpy(sav_arg, eargv[i], MAXLEN - 1);
984 eargx = i;
985 break;
986 }
987 i++;
988 }
989 for (i = 0; i < form->fcnt; i++) {
990 // concatenate field values onto tmp_str
991 if (form->field[i]->accept_s[0] && eargc < MAXARGS - 1) {
992 if (f_append_values == true) {
993 if (tmp_str[0] != '\0')
994 strnz__cat(tmp_str, " ", MAXLEN - 1);
995 strnz__cat(tmp_str, form->field[i]->accept_s, MAXLEN - 1);
996 continue;
997 }
998 eargv[eargc++] = strdup(form->field[i]->accept_s);
999 }
1000 }
1001 // replace "%%" with concatenated field values
1002 if (f_append_values == true) {
1003 if (eargv[eargx] != nullptr) {
1004 free(eargv[eargx]);
1005 eargv[eargx] = nullptr;
1006 }
1007 out_s = rep_substring(sav_arg, "%%", tmp_str);
1008 if (out_s == nullptr || out_s[0] == '\0') {
1009 i = 0;
1010 while (i < eargc) {
1011 if (eargv[i] != nullptr)
1012 free(eargv[i]);
1013 i++;
1014 }
1015 Perror("rep_substring() failed in form_exec_objects");
1016 return 1;
1017 }
1018 strnz__cpy(title, out_s, MAXLEN - 1);
1019 eargv[eargx] = strdup(out_s);
1020 if (out_s != nullptr) {
1021 free(out_s);
1022 out_s = nullptr;
1023 }
1024 }
1025 }
1026 if (eargc > 0)
1027 eargv[eargc] = nullptr;
1028 base_name(tmp_str, eargv[0]);
1029 if (tmp_str[0] != '\0' && (strcmp(tmp_str, "view") == 0)) {
1032 init->lines = 60;
1033 init->cols = 80;
1034 init->begy = form->begy + 1;
1035 init->begx = form->begx + 1;
1036 if (title[0] != '\0')
1037 strnz__cpy(init->title, title, MAXLEN - 1);
1038 else
1039 strnz__cpy(init->title, eargv[eargc], MAXLEN - 1);
1040 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
1041 init->begx);
1042 i = 0;
1043 while (i < eargc) {
1044 if (eargv[i] != nullptr)
1045 free(eargv[i]);
1046 i++;
1047 }
1048 return 0;
1049 } else {
1050 endwin();
1051 if ((pid = fork()) == -1) {
1053 i = 0;
1054 while (i < eargc) {
1055 if (eargv[i] != nullptr)
1056 free(eargv[i]);
1057 i++;
1058 }
1059 Perror("fork() failed in form_exec_objects");
1060 return (1);
1061 }
1062 if (pid == 0) {
1064 int dev_null = open("/dev/null", O_WRONLY);
1065 if (dev_null == -1) {
1066 Perror("open(/dev/null) failed in init_form child process");
1067 exit(EXIT_FAILURE);
1068 }
1069 dup2(dev_null, STDERR_FILENO);
1070 close(dev_null);
1072 execvp(eargv[0], eargv);
1075 strnz__cpy(tmp_str, "Can't exec form cmd: ", MAXLEN - 1);
1076 strnz__cat(tmp_str, eargv[0], MAXLEN - 1);
1077 Perror(tmp_str);
1078 exit(EXIT_FAILURE);
1079 }
1080 }
1081 waitpid(pid, nullptr, 0);
1082 reset_prog_mode();
1084 sig_prog_mode();
1085 // werase(stdscr);
1086 // wrefresh(stdscr);
1087 restore_wins();
1088 return rc;
1089}
void restore_wins()
Restore all windows after a screen resize.
Definition dwin.c:1225
char * rep_substring(const char *, const char *, const char *)
Replace all occurrences of "tgt_s" in "org_s" with "rep_s".
Definition futil.c:1440
bool base_name(char *, char *)
Returns the base name of a file specification.
Definition futil.c:1123
int str_to_args(char **, char *, int)
Converts a string into an array of argument strings.
Definition futil.c:440
void sig_prog_mode()
Set up signal handlers for interrupt signals.
Definition sig.c:62

References Field::accept_s, base_name(), Form::begx, Init::begx, Form::begy, Init::begy, Init::cols, destroy_argv(), Form::f_multiple_cmd_args, Form::fcnt, Form::field, Init::form, Init::lines, Perror(), popup_view(), Form::receiver_cmd, rep_substring(), restore_wins(), sig_prog_mode(), str_to_args(), strnz__cat(), strnz__cpy(), and Init::title.

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 640 of file form_engine.c.

640 {
641 FILE *form_desc_fp;
642 char *token;
643 char *s;
644 int cols = 0;
645 int i, l;
646 int in_line_num = 0;
647 char in_buf[BUFSIZ];
648 char tmp_buf[BUFSIZ];
649 char *tmp_buf_p;
650 char tmp_str[BUFSIZ];
651 char delim[5];
652 char directive;
653
654 form_desc_fp = fopen(form->mapp_spec, "r");
655 if (form_desc_fp == nullptr) {
656 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 2);
657 strnz__cpy(em1, "fopen ", MAXLEN - 1);
658 strnz__cat(em1, form->mapp_spec, MAXLEN - 1);
659 strerror_r(errno, em2, MAXLEN);
660 display_error(em0, em1, em2, nullptr);
661 return (1);
662 }
663 for (i = 0; i < FIELD_MAXCNT; i++) {
664 form->field[i] = calloc(1, sizeof(Field));
665 if (!form->field[i]) {
666 sprintf(tmp_str, "FORM: calloc failed for fields");
667 abend(EXIT_FAILURE, tmp_str);
668 }
669 }
670 for (i = 0; i < FIELD_MAXCNT; i++) {
671 form->text[i] = calloc(1, sizeof(Text));
672 if (!form->text[i]) {
673 sprintf(tmp_str, "FORM: calloc failed for text");
674 abend(EXIT_FAILURE, tmp_str);
675 }
676 }
677 form->didx = 0;
678 form->fidx = 0;
679 form->fcnt = 0;
680 form->cols = 34;
681 while ((fgets(in_buf, MAXLEN, form_desc_fp)) != nullptr) {
682 s = in_buf;
683 in_line_num++;
684 l = trim(in_buf);
685 if (l == 0)
686 continue;
687 if (*s == D_COMMENT)
688 continue;
689 delim[0] = '\n';
690 delim[1] = in_buf[1];
691 delim[2] = '\0';
692 strnz__cpy(tmp_buf, in_buf, MAXLEN - 1);
693 tmp_buf_p = tmp_buf;
694 if (!(token = strtok(tmp_buf_p, delim))) {
695 continue;
696 }
697 directive = *token;
698 switch ((int)directive) {
699 case D_COMMENT:
700 break;
701 case D_CALC:
702 form->f_calculate = true;
703 break;
704 case D_QUERY:
705 form->f_query = true;
706 break;
707 case D_GETTER:
708 form->f_process = true;
709 break;
710 case D_CMD:
711 if (!(token = strtok(nullptr, delim))) {
712 form_desc_error(form, in_line_num, in_buf,
713 "FORM: receiver_cmd delimiter");
714 continue;
715 }
716 strnz__cpy(form->receiver_cmd, token, MAXLEN - 1);
717 break;
718 case D_HELP:
719 if (!(token = strtok(nullptr, delim))) {
720 form_desc_error(form, in_line_num, in_buf,
721 "FORM: help_spec delimiter");
722 }
723 strnz__cpy(form->help_spec, token, MAXLEN - 1);
724 break;
725 case D_FIELD:
726 if (form->field[form->fidx] == nullptr) {
727 sprintf(tmp_str, "FORM: calloc failed for fields");
728 abend(EXIT_FAILURE, tmp_str);
729 }
730 if (!(token = strtok(nullptr, delim))) {
731 form_desc_error(form, in_line_num, in_buf,
732 "FORM: line number delimiter");
733 return 1;
734 }
735 form->field[form->fidx]->line = atoi(token);
736 if (form->field[form->fidx]->line < 0 ||
737 form->field[form->fidx]->line >= FIELD_MAXCNT) {
738 form_desc_error(form, in_line_num, in_buf,
739 "FORM: invalid line number");
740 return 1;
741 }
742 if (!(token = strtok(nullptr, delim))) {
743 form_desc_error(form, in_line_num, in_buf,
744 "FORM: column number delimiter");
745 return 1;
746 }
747 form->field[form->fidx]->col = atoi(token);
748 if (form->field[form->fidx]->col < 0 ||
749 form->field[form->fidx]->col >= FIELD_MAXLEN) {
750 form_desc_error(form, in_line_num, in_buf,
751 "FORM: invalid column number");
752 break;
753 }
754 if (!(token = strtok(nullptr, delim))) {
755 strnz__cpy(tmp_str, in_buf, MAXLEN - 1);
756 form_desc_error(form, in_line_num, tmp_str, "FORM: length delimiter");
757 break;
758 }
759 form->field[form->fidx]->len = atoi(token);
760 if (form->field[form->fidx]->len < 0 ||
761 form->field[form->fidx]->len > FIELD_MAXLEN) {
762 form_desc_error(form, in_line_num, in_buf, "FORM: invalid length");
763 break;
764 }
765 if (!(token = strtok(nullptr, delim))) {
766 form_desc_error(form, in_line_num, in_buf,
767 "FORM: validation code delimiter");
768 break;
769 }
770 form->field[form->fidx]->ff = -1;
771 for (i = 0; i < FF_INVALID; i++) {
772 str_to_lower(token);
774 if (!strcmp(token, ff_tbl[i])) {
775 form->field[form->fidx]->ff = i;
776 break;
777 }
778 }
779 if (form->field[form->fidx]->ff < 0 ||
780 form->field[form->fidx]->ff >= FF_INVALID) {
781 form_desc_error(form, in_line_num, in_buf,
782 "FORM: invalid format code");
783 break;
784 }
785 cols =
786 form->field[form->fidx]->col + form->field[form->fidx]->len + 1;
787 if (cols > form->cols)
788 form->cols = cols;
789 form->fidx++;
790 form->fcnt = form->fidx;
791 break;
792 case D_TEXT:
793 if (form->text[form->didx] == nullptr) {
794 sprintf(tmp_str, "FORM: calloc failed for text");
795 abend(EXIT_FAILURE, tmp_str);
796 }
797 if (!(token = strtok(nullptr, delim))) {
798 form_desc_error(form, in_line_num, in_buf,
799 "FORM: line number delimiter");
800 break;
801 }
802 form->text[form->didx]->line = atoi(token);
803 if (form->text[form->didx]->line < 0 ||
804 form->text[form->didx]->line >= FIELD_MAXCNT) {
805 form_desc_error(form, in_line_num, in_buf,
806 "FORM: invalid line number");
807 break;
808 }
809 if (!(token = strtok(nullptr, delim))) {
810 form_desc_error(form, in_line_num, in_buf,
811 "FORM: column number delimiter");
812 break;
813 }
814 form->text[form->didx]->col = atoi(token);
815 if (form->text[form->didx]->col < 0 ||
816 form->text[form->didx]->col >= FIELD_MAXLEN) {
817 form_desc_error(form, in_line_num, in_buf,
818 "FORM: invalid column number");
819 break;
820 }
821 if (!(token = strtok(nullptr, delim))) {
822 form_desc_error(form, in_line_num, in_buf, "FORM: text delimiter");
823 break;
824 }
825 strnz__cpy(form->text[form->didx]->str, token, MAXLEN - 1);
826 form->text[form->didx]->len = strlen(form->text[form->didx]->str);
827 if (form->text[form->didx]->len < 0 ||
828 form->text[form->didx]->len > FIELD_MAXLEN) {
829 form_desc_error(form, in_line_num, in_buf, "FORM: invalid length");
830 break;
831 }
832 cols =
833 form->text[form->didx]->col + form->text[form->didx]->len + 1;
834 if (cols > form->cols)
835 form->cols = cols;
836 form->didx++;
837 form->dcnt = form->didx;
838 break;
839 case D_HEADER:
840 if ((token = strtok(nullptr, delim))) {
841 strnz__cpy(form->title, token, MAXLEN - 1);
842 }
843 break;
844 default:
845 form_desc_error(form, in_line_num, in_buf, "invalid directive");
846 break;
847 }
848 }
849 fclose(form_desc_fp);
850 if (form->didx < 1 && form->fidx < 1) {
851 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__);
852 ssnprintf(em1, MAXLEN - 1, "%s", "Error in description file:");
853 ssnprintf(em2, MAXLEN - 1, "%s", form->mapp_spec);
854 display_error(em0, em1, em2, nullptr);
855 return (1);
856 }
857 return (0);
858}
#define FIELD_MAXLEN
Definition form.h:18
@ FF_INVALID
Definition form.h:68
char ff_tbl[][26]
Definition fields.c:26
#define FIELD_MAXCNT
Definition form.h:19
#define BUFSIZ
Definition view.h:31
#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
void abend(int, char *)
Abnormal program termination.
Definition dwin.c:2018
int form_desc_error(Form *form, 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:391
bool str_to_lower(char *)
Converts a string to lowercase.
Definition futil.c:508
structure for form fields
Definition form.h:99
structure for form fields
Definition form.h:112

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., FA_CONTINUE, FA_CANCEL, FA_ACCEPT, FA_HELP).

Definition at line 225 of file form_engine.c.

225 {
226 bool loop = true;
227 int c, rc;
228 click_y = click_x = -1;
229 Form *form = init->form;
230 wmove(form->win, form->lines - 1, 0);
231 wclrtoeol(form->win);
232 // 1 F1 Help
233 // 2 F2 Process
234 // 3 F3 Calculate
235 // 4 F4 Query
236 // 5 F5 Edit
237 // 9 F9 Cancel
238 // 10 F10 Continue
239 // 11 F10 Commit
240 // 18 INS Insert
241 form->chyron->key[5]->active = true; // F5 Edit
242 form->chyron->key[10]->active = false; // F10 Continue
243 form->chyron->key[18]->active = false; // INS Insert
244 compile_chyron(form->chyron);
245 rc = -1;
246 while (loop) {
247 if (rc == -1) {
248 display_chyron(form->win, form->chyron, form->lines - 1,
249 form->chyron->l);
250 tcflush(2, TCIFLUSH);
251 update_panels();
252 doupdate();
253 c = xwgetch(form->win, form->chyron, -1);
254 }
255 switch (c) {
256 case KEY_F(1):
257 return FA_HELP;
258 case KEY_F(5): // F5 Edit
259 if (is_set_chyron_key(form->chyron, 5)) {
260 loop = false;
261 rc = FA_CONTINUE;
262 break;
263 }
264 continue;
265 case KEY_F(9):
266 loop = false;
267 rc = FA_CANCEL;
268 break;
269 case KEY_F(10):
270 loop = false;
271 rc = FA_ACCEPT;
272 break;
273 case KEY_MOUSE:
274 continue;
275 default:
276 break;
277 }
278 }
279 form->chyron->key[5]->active = false; // F5 Edit
280 return rc;
281}
int click_x
Definition dwin.c:81
int click_y
Definition dwin.c:80
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:2094
bool is_set_chyron_key(Chyron *, int)
Check if function key label is set.
Definition dwin.c:1743

References ChyronKey::active, Form::chyron, click_x, click_y, compile_chyron(), display_chyron(), FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_HELP, Init::form, is_set_chyron_key(), Chyron::key, Chyron::l, Form::lines, 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., FA_CONTINUE, FA_CANCEL, FA_ACCEPT, FA_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.

Prevent child process from writing to terminal

Definition at line 320 of file form_engine.c.

320 {
321 int i, c, rc;
322 char earg_str[MAXLEN + 1];
323 char *eargv[MAXARGS];
324 int eargc;
325 char file_spec[MAXLEN];
326 bool loop = true;
327 pid_t pid;
328 int pipe_fd[2];
329
330 Form *form = init->form;
331 wmove(form->win, form->lines - 1, 0);
332 //
333 // 1 F1 Help
334 // 2 F2 Process
335 // 3 F3 Calculate
336 // 4 F4 Query
337 // 5 F5 Edit
338 // 9 F9 Cancel
339 // 10 F10 Continue
340 // 11 F10 Commit
341 form->chyron->key[2]->active = form->f_process > 0 ? true : false;
342 form->chyron->key[3]->active = form->f_calculate > 0 ? true : false;
343 form->chyron->key[4]->active = form->f_query > 0 ? true : false; // PgUp
344 form->chyron->key[10]->active = false; // F10 Continue
345 form->chyron->key[18]->active = false; // INS Insert
346
347 while (loop) {
348 compile_chyron(form->chyron);
349 display_chyron(form->win, form->chyron, form->lines - 1,
350 form->chyron->l);
351 click_y = click_x = -1;
352 tcflush(2, TCIFLUSH);
353 update_panels();
354 doupdate();
355 c = xwgetch(form->win, form->chyron, -1);
356 switch (c) {
357 case KEY_F(1):
358 return FA_HELP;
359 case KEY_F(2): // F2 Process
360 case KEY_F(3): // F3 Calculate
361 case KEY_F(4): // F4 Query
362 if (form->f_out_spec)
364 if (form->f_provider_cmd) {
365 strnz__cpy(earg_str, form->provider_cmd, MAXLEN - 1);
366 for (i = 0; i < form->fcnt; i++) {
367 strnz__cat(earg_str, " ", MAXLEN - 1);
368 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
369 }
371 strnz__cpy(file_spec, eargv[0], MAXLEN - 1);
372 base_name(eargv[0], file_spec);
373 if (pipe(pipe_fd) == -1) {
375 Perror("pipe(pipe_fd) failed in init_form");
376 return (1);
377 }
378 if ((pid = fork()) == -1) {
380 Perror("fork() failed in init_form");
381 return (1);
382 }
383 if (pid == 0) { // Child
385 int dev_null = open("/dev/null", O_WRONLY);
386 if (dev_null == -1) {
387 Perror("open(/dev/null) failed in init_pick child "
388 "process");
389 exit(EXIT_FAILURE);
390 }
391 dup2(dev_null, STDERR_FILENO);
392 close(dev_null);
393 close(pipe_fd[P_READ]);
394 dup2(pipe_fd[P_WRITE], STDOUT_FILENO);
395 stdio_fdnames(stdio_names_str, "form_engine.c:367");
396 close(pipe_fd[P_WRITE]);
397 execvp(eargv[0], eargv);
398 ssnprintf(em0, MAXLEN, "%s, line: %d", __FILE__,
399 __LINE__ - 2);
400 strnz__cpy(em1, "execvp(", MAXLEN - 1);
401 strnz__cat(em1, eargv[0], MAXLEN - 1);
402 strnz__cat(em1, ", ", MAXLEN - 1);
404 strnz__cat(em1, ")", MAXLEN - 1);
405 strerror_r(errno, em2, MAXLEN);
406 display_error(em0, em1, em2, nullptr);
407 exit(EXIT_FAILURE);
408 } // Back to parent
409 close(pipe_fd[P_WRITE]);
410 form->in_fp = fdopen(pipe_fd[P_READ], "rb");
411 form->f_in_pipe = true;
413 close(pipe_fd[P_READ]);
415 stdio_fdnames(stdio_names_str, "form_engine.c:387");
418 form->chyron->key[2]->active = false; // F2 Process
419 form->chyron->key[3]->active = false; // F3 Calculate
420 form->chyron->key[4]->active = false; // F4 Query
421 form->chyron->key[5]->active = true; // F5 Edit
422 form->chyron->key[10]->active = true; // F10 Accept
423 compile_chyron(form->chyron);
424 continue;
425 }
426 break;
427 case KEY_F(5):
428 if (is_set_chyron_key(form->chyron, 5)) {
429 loop = false;
430 rc = FA_CONTINUE;
431 break;
432 }
433 continue;
434 case KEY_F(9):
435 loop = false;
436 rc = FA_CANCEL;
437 break;
438 case KEY_F(10):
439 loop = false;
440 rc = FA_ACCEPT;
441 break;
442 case KEY_MOUSE:
443 break;
444 default:
445 break;
446 }
447 }
448 form->chyron->key[2]->active = false; // F2 Process
449 form->chyron->key[3]->active = false; // F3 Calculate
450 form->chyron->key[4]->active = false; // F4 Query
451 form->chyron->key[5]->active = false; // F5 Edit
452 return rc;
453}
#define P_READ
Definition common.h:50
#define P_WRITE
Definition common.h:51
int wait_timeout
Definition futil.c:152
char stdio_names_str[MAXLEN]
Definition futil.c:134
char * stdio_fdnames(char *, char *)
Definition futil.c:1089
int pipe_fd[2]
Definition pick_engine.c:46
bool waitpid_with_timeout(pid_t, int)
Wait for a process to finish with a timeout and optional user cancellation.
Definition dwin.c:2033

References Field::accept_s, ChyronKey::active, base_name(), Form::chyron, click_x, click_y, compile_chyron(), destroy_argv(), display_chyron(), display_error(), em0, em1, em2, Form::f_calculate, Form::f_in_pipe, Form::f_out_spec, Form::f_process, Form::f_provider_cmd, Form::f_query, FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_HELP, Form::fcnt, Form::field, Init::form, form_display_fields(), form_read_data(), form_write(), Form::in_fp, is_set_chyron_key(), Chyron::key, Chyron::l, Form::lines, Perror(), Form::provider_cmd, ssnprintf(), stdio_fdnames(), stdio_names_str, str_to_args(), strnz__cat(), strnz__cpy(), 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 867 of file form_engine.c.

867 {
868 struct stat sb;
869 char in_buf[MAXLEN];
870 char field[MAXLEN];
871 int cmd_key;
872
873 if (!form->f_in_pipe) {
874 if (form->f_in_spec && form->in_spec[0] != '\0') {
875 if ((lstat(form->in_spec, &sb) == -1) || (sb.st_size == 0) ||
876 ((form->in_fp = fopen(form->in_spec, "rb")) == nullptr)) {
877 strnz__cat(em0, form->in_spec, MAXLEN - 1);
878 if (sb.st_size == 0)
879 strnz__cpy(em1, "File is empty", MAXLEN - 1);
880 else
881 strnz__cpy(em1, "File does not exist", MAXLEN - 1);
882 strnz__cpy(em2, "Fields will be blank or zero", MAXLEN - 1);
883 cmd_key = display_error(em0, em1, em2, nullptr);
884 if (cmd_key == KEY_F(9))
885 return (1);
886 }
887 if (form->in_fp == nullptr)
888 return (1);
889 } else
890 return (0);
891 }
892 form->fidx = 0;
893 if (form->in_fp != nullptr) {
894 while ((fgets(in_buf, MAXLEN, form->in_fp)) != nullptr) {
895 if (form->fidx < FIELD_MAXCNT)
896 strnz__cpy(field, in_buf, MAXLEN - 1);
897 form_fmt_field(form, field);
898 form->fidx++;
899 }
900 fclose(form->in_fp);
901 }
902 return (0);
903}
int form_fmt_field(Form *, char *s)
Format field according to its format type.
Definition fields.c:444

References 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 1098 of file form_engine.c.

1098 {
1099 int n;
1100 if (form->out_spec[0] == '\0' || strcmp(form->out_spec, "-") == 0 ||
1101 strcmp(form->out_spec, "/dev/stdout") == 0) {
1102 strnz__cpy(form->out_spec, "/dev/stdout", MAXLEN - 1);
1103 close(form->out_fd);
1104 form->out_fd = open(form->out_spec, O_CREAT | O_RDWR | O_TRUNC, 0644);
1105 if (form->out_fd == -1) {
1106 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
1107 strnz__cpy(em1, "open ", MAXLEN - 1);
1108 strnz__cat(em1, form->out_spec, MAXLEN - 1);
1109 strerror_r(errno, em2, MAXLEN);
1110 display_error(em0, em1, em2, nullptr);
1111 return (1);
1112 }
1113 dup2(form->out_fd, STDOUT_FILENO);
1114 form->out_fp = fdopen(STDOUT_FILENO, "w");
1115 form->f_out_spec = true;
1116 form->f_out_pipe = true;
1117 } else {
1118 if ((form->out_fp = fopen(form->out_spec, "w")) == nullptr) {
1119 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
1120 strerror_r(errno, em2, MAXLEN);
1121 display_error(em0, em1, em2, nullptr);
1122 return (1);
1123 }
1124 }
1125 if (form->out_fp == nullptr) {
1126 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
1127 strnz__cpy(em1, "fopen ", MAXLEN - 1);
1128 strnz__cat(em1, form->out_spec, MAXLEN - 1);
1129 strerror_r(errno, em2, MAXLEN);
1130 display_error(em0, em1, em2, nullptr);
1131 return (1);
1132 }
1133 for (n = 0; n < form->fcnt; n++)
1134 fprintf(form->out_fp, "%s\n", form->field[n]->accept_s);
1135 if (form->out_fp != nullptr)
1136 fclose(form->out_fp);
1137 return (0);
1138}

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 61 of file form_engine.c.

61 {
62 int rc;
63 char tmp_str[MAXLEN];
64 if (init->form != nullptr)
65 destroy_form(init);
66 init->form = new_form(init, argc, argv, begy, begx);
67 Form *form = init->form;
68 if (!form->f_mapp_spec) {
69 if (form->mapp_spec[0] == '\0') {
70 rc = Perror("Error: No form specification file given");
71 } else {
72 strnz__cpy(tmp_str, "form->mapp_spec: ", MAXLEN - 1);
73 strnz__cat(tmp_str, form->mapp_spec, MAXLEN - 1);
74 strnz__cat(tmp_str, " not found", MAXLEN - 1);
75 rc = Perror(tmp_str);
76 }
77 destroy_form(init);
78 return rc;
79 }
80 if (begy != 0)
81 form->begy = begy;
82 if (begx != 0)
83 form->begx = begx;
84 if ((form->f_in_spec && (form->in_spec[0] == '\0')) ||
85 (strcmp(form->in_spec, "-") == 0) ||
86 strcmp(form->in_spec, "/dev/stdin") == 0) {
87 strnz__cpy(form->in_spec, "/dev/stdin", MAXLEN - 1);
88 form->f_in_pipe = true;
89 }
90 if (form->title[0] == '\0')
91 strnz__cpy(form->title, form->in_spec, MAXLEN - 1);
92 form->brktl = mkcc(cp_brackets, WA_NORMAL, &form->brackets[0]);
93 form->brktr = mkcc(cp_brackets, WA_NORMAL, &form->brackets[1]);
94
95 rc = form_engine(init);
96 destroy_chyron(form->chyron);
97 if (form->win)
98 win_del();
99 destroy_form(init);
100 return rc;
101}
int cp_brackets
Definition dwin.c:190
void win_del()
Delete the current window and its associated box window.
Definition dwin.c:1179
cchar_t mkcc(int, attr_t, const char *)
Create a cchar_t with the specified color pair index.
Definition dwin.c:748
Chyron * destroy_chyron(Chyron *chyron)
Destroy Chyron structure.
Definition dwin.c:1722
int form_engine(Init *)
Form main processing loop.
Form * new_form(Init *, int, char **, int, int)
Create and initialize Form structure.
Definition mem.c:263
Form * destroy_form(Init *init)
Destroy Form structure.
Definition mem.c:286

References Form::begx, Form::begy, Form::brackets, Form::brktl, Form::brktr, Form::chyron, cp_brackets, destroy_chyron(), destroy_form(), Form::f_in_pipe, Form::f_in_spec, Form::f_mapp_spec, Init::form, form_engine(), Form::in_spec, Form::mapp_spec, mkcc(), 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: