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, uint begy, uint 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 532 of file form_engine.c.

532 {
533 uint n, flin, fcol;
534 char tmp_str[MAXLEN];
535
536 Form *form = init->form;
537 form->lines = 0;
538 for (n = 0; n < form->dcnt; n++)
539 if (form->text[n]->line > form->lines)
540 form->lines = form->text[n]->line;
541 for (n = 0; n < form->fcnt; n++)
542 if (form->field[n]->line > form->lines)
543 form->lines = form->field[n]->line;
544 form->lines += 3;
545 if (form->lines > (LINES - form->begy))
546 form->lines = LINES - form->begy;
547 for (n = 0; n < form->fcnt; n++) {
548 if (form->field[n]->line >= (form->lines - 2))
549 form->fcnt = n;
550 }
551 form->cols += 2;
552 if (form->cols > (COLS - form->begx - 3))
553 form->cols = COLS - form->begx - 3;
554 if (surface_box_win_new(form->lines, form->cols, form->begy, form->begx, form->title)) {
555 strnz__cpy(tmp_str, "surface_box_win_new failed: ", MAXLEN - 1);
556 strnz__cat(tmp_str, form->title, MAXLEN - 1);
557 Perror(tmp_str);
558 return (1);
559 }
561#ifdef DEBUG_IMMEDOK
562 ui_immedok(sfc, WIN, true);
563 ui_immedok(sfc, BOX, true);
564#endif
565 for (form->fidx = 0; form->fidx < form->fcnt; form->fidx++) {
566 if (form->brackets[0] != '\0' && form->brackets[1] != '\0') {
567 flin = form->field[form->fidx]->line + 1;
568 fcol = form->field[form->fidx]->col;
569 ui_mvwadd_wch(sfc, BOX, flin, fcol, &cell_brktl);
570 fcol += form->field[form->fidx]->len + 1;
571 ui_mvwadd_wch(sfc, BOX, flin, fcol, &cell_brktr);
572 }
573 }
574 for (n = 0; n < form->dcnt; n++) {
575 strnz(form->text[n]->str, form->cols - 3);
576 ui_mvwaddstr(sfc, WIN, form->text[n]->line, form->text[n]->col,
577 form->text[n]->str);
578 }
579 ui_render();
581 return 0;
582}
void ui_render()
Definition ui_ncurses.c:800
int ui_mvwaddstr(UiSurface *s, uint w, uint y, uint x, const char *text)
uint COLS
Definition ui_backend.h:266
UiSurface * ui_surface[UI_SFC_MAX]
Definition ui_ncurses.c:28
uint LINES
int sfc_ptr
Definition nckeys.c:47
int ui_mvwadd_wch(UiSurface *s, uint w, uint y, uint x, const UiCell *cell)
Form * form
Definition mem.c:37
#define MAXLEN
Definition curskeys.c:15
int surface_box_win_new(uint wlines, uint wcols, uint wbegy, uint wbegx, char *wtitle)
Definition dwin.c:521
UiCell cell_brktl
Definition dwin.c:92
UiCell cell_brktr
Definition dwin.c:93
int Perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition dwin.c:841
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:537
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:608
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:566
A drawable surface in the NotCurses backend.
Form * form
Definition common.h:185
Definition form.h:146

References Form::begx, Form::begy, BOX, Form::brackets, cell_brktl, cell_brktr, Field::col, Text::col, COLS, Form::cols, Form::dcnt, Form::fcnt, Form::fidx, Form::field, Init::form, form_display_fields(), Field::len, Field::line, Text::line, LINES, Form::lines, Perror(), sfc_ptr, Text::str, strnz(), strnz__cat(), strnz__cpy(), surface_box_win_new(), Form::text, Form::title, ui_mvwadd_wch(), ui_mvwaddstr(), ui_render(), ui_surface, and 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 471 of file form_engine.c.

471 {
472
473 if (form->fidx >= form->fcnt)
474 form->fidx = 0;
475 while (1) {
477 switch (cmd_key) {
478 case KEY_F01: // F1 Help
479 return (FA_HELP);
480 case KEY_F02: // F2 Process
481 case KEY_F03: // F3 Calculate
482 case KEY_F04: // F4 Query
483 if (form->f_process)
484 return (FA_CALC);
485 break;
486 case KEY_F09: // F9 Cancel
487 return (FA_CANCEL);
488 case KEY_F10: // F10 Accept
489 return (FA_ACCEPT);
490 case 'k':
491 case KEY_UP:
492 if (form->fidx != 0)
493 form->fidx--;
494 break;
495 case '\r':
496 case KEY_ENTER:
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 'j':
503 case KEY_DOWN:
504 if (form->fidx < form->fcnt - 1)
505 form->fidx++;
506 else if (form->fidx == form->fcnt - 1)
507 return (FA_ACCEPT);
508 break;
509 case KEY_MOUSE:
510 break;
511 default:
512 break;
513 }
514 }
515}
@ FA_ACCEPT
Definition form.h:29
@ FA_CALC
Definition form.h:37
@ FA_HELP
Definition form.h:31
@ FA_CANCEL
Definition form.h:33
#define KEY_F04
#define KEY_F01
#define KEY_F09
#define KEY_F03
#define KEY_F10
#define KEY_F02
#define KEY_DOWN
#define KEY_ENTER
#define KEY_MOUSE
#define KEY_UP
unsigned int cmd_key
Definition dwin.c:128
int field_editor(Form *)
Accept input for a field.
Definition fields.c:48

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

1148 {
1149 int cmd_key;
1150 ssnprintf(em0, MAXLEN - 1, "%s: %s", __FILE__, em);
1151 ssnprintf(em1, MAXLEN - 1, "Desc file: %s, line: %d", form->mapp_spec,
1152 in_line_num);
1153 strnz__cpy(em2, in_buf, MAXLEN - 1);
1154 cmd_key = display_error(em0, em1, em2, nullptr);
1155 return cmd_key;
1156}
char em1[MAXLEN]
Definition dwin.c:143
char em2[MAXLEN]
Definition dwin.c:144
char em0[MAXLEN]
Definition dwin.c:142
int display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition dwin.c:778
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:413

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

592 {
593 uint y, x;
594 uint pos = 0;
595 for (form->fidx = 0; form->fidx < form->fcnt; form->fidx++) {
596 if (form->field[form->fidx]->col + form->field[form->fidx]->len + 2 >
597 form->cols)
598 form->field[form->fidx]->len =
599 form->cols - (form->field[form->fidx]->col + 2);
600 // Make filler_cc
601 size_t fl = form->field[form->fidx]->len;
602 char *d = form->field[form->fidx]->filler_s;
603 size_t char_bytes = strlen(form->fill_char);
604 for (size_t i = 0; i < fl; i++) {
605 memcpy(d, form->fill_char, char_bytes);
606 d += char_bytes;
607 }
608 d = nullptr;
609
610 if (form->field[form->fidx]->accept_s[0] != '\0') {
611 strnz(form->field[form->fidx]->accept_s, form->field[form->fidx]->len);
612 // d = form->field[form->fidx]->accept_s;
613 } else {
614 memset(form->field[form->fidx]->accept_s, 0, MAXLEN);
615 // d = form->field[form->fidx]->accept_s;
616 }
617 strnz(form->field[form->fidx]->display_s, form->field[form->fidx]->len);
618
619 y = form->field[form->fidx]->line;
620 x = form->field[form->fidx]->col;
621
622 pos = 0;
623 mbstr_to_cellstr(form->field[form->fidx]->filler_cc, form->field[form->fidx]->filler_s, &cell_fill_char, &pos, form->field[form->fidx]->len + 1);
624
626 ui_mvwadd_wchstr(sfc, WIN, y, x, form->field[form->fidx]->filler_cc);
627 ui_render();
628
629 pos = 0;
630 mbstr_to_cellstr(form->field[form->fidx]->display_cc, form->field[form->fidx]->display_s, &cell_nt, &pos, form->field[form->fidx]->len + 1);
631
632 ui_mvwadd_wchnstr(sfc, WIN, y, x, form->field[form->fidx]->display_cc, form->field[form->fidx]->len);
633 ui_render();
634 }
635 return;
636}
int ui_mvwadd_wchstr(UiSurface *s, uint w, uint y, uint x, const UiCell *cell)
int ui_mvwadd_wchnstr(UiSurface *s, uint w, uint y, uint x, const UiCell *cell, uint m)
UiCell cell_nt
Definition dwin.c:94
UiCell cell_fill_char
Definition dwin.c:91
uint mbstr_to_cellstr(UiCell *cmplx_buf, const char *str, const UiCell *cell_base, uint *pos, const uint atmost)
Convert multibyte string to complex character array.
Definition dwin.c:480

References Field::accept_s, cell_fill_char, cell_nt, Field::col, Form::cols, 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, mbstr_to_cellstr(), sfc_ptr, strnz(), ui_mvwadd_wchnstr(), ui_mvwadd_wchstr(), ui_render(), ui_surface, and 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 118 of file form_engine.c.

118 {
119 char tmp_str[MAXLEN];
120 int form_action;
121 char *eargv[MAXARGS];
122 int eargc;
123
124 Form *form = init->form;
125 if (form == nullptr) {
126 Perror("FORM: form data structure is nullptr");
127 }
128 if (form_parse_desc(form)) {
129 return 0;
130 }
132 display_form(init);
133 form->chyron = new_chyron();
134 set_chyron_key(form->chyron, 1, "F1 Help", KEY_F01);
135 set_chyron_key_cb(form->chyron, 2, "F2 Process", KEY_F02, cell_nt_hl_rev);
136 set_chyron_key_cb(form->chyron, 3, "F3 Calculate", KEY_F03, cell_nt_hl_rev);
137 set_chyron_key_cb(form->chyron, 4, "F4 Query", KEY_F04, cell_nt_hl_rev);
138 set_chyron_key_cb(form->chyron, 5, "F5 Edit", KEY_F05, cell_nt_hl_rev);
139 set_chyron_key(form->chyron, 9, "F9 Cancel", KEY_F09);
140 set_chyron_key(form->chyron, 10, "F10 Accept", KEY_F10);
141 set_chyron_key(form->chyron, 18, "INS", KEY_IC);
142 form->chyron->key[2]->active = false; // F2 Process
143 form->chyron->key[3]->active = false; // F3 Calculate
144 form->chyron->key[4]->active = false; // F4 Query
145 form->chyron->key[5]->active = false; // F5 Edit
146 form->chyron->key[18]->active = false; // Insert
147 compile_chyron(form->chyron);
149 display_chyron(sfc, 1, form->chyron, form->lines - 1, form->chyron->l);
150 // 1 F1 Help
151 // 2 F2 Process
152 // 3 F3 Calculate
153 // 4 F4 Query
154 // 5 F5 Edit
155 // 9 F9 Cancel
156 // 10 F10 Accept
157 form->fidx = 0;
158 form_action = 0;
159 while (1) {
160 if (form_action == 0 || form_action == FA_CONTINUE)
161 form_action = field_navigator(form);
162 form->chyron->key[18]->active = false; // Insert
163 switch (form_action) {
164 case FA_ACCEPT:
165 if (form->f_process || form->f_calculate || form->f_query)
166 form_action = form_process(init);
167 else
168 form_action = form_post(init);
169 if (form_action == FA_HELP || form_action == FA_CANCEL ||
170 form_action == FA_CONTINUE || form_action == FA_END)
171 continue;
172 if (form_action == FA_ACCEPT) {
173 form_action = FA_END;
174 continue;
175 }
176 break;
177 case FA_END:
178 if (form->f_out_spec || form->out_spec[0] != '\0')
180 if (form->f_receiver_cmd || form->receiver_cmd[0] != '\0')
181 form_exec_receiver(init);
182 break;
183 case FA_HELP:
184 if (form->f_help_spec && form->help_spec[0] != '\0')
185 strnz__cpy(tmp_str, form->help_spec, MAXLEN - 1);
186 else {
187 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
188 strnz__cat(tmp_str, "/", MAXLEN - 1);
189 strnz__cat(tmp_str, FORM_HELP_FILE, MAXLEN - 1);
190 }
191 eargc = 0;
192 eargv[eargc++] = strdup("view");
193 eargv[eargc++] = strdup("-Nf");
194 eargv[eargc++] = strdup(tmp_str);
195 eargv[eargc] = nullptr;
196 init->lines = 30;
197 init->cols = 66;
198 init->begy = form->begy + 1;
199 init->begx = form->begx + 1;
200 strnz__cpy(init->title, "Form Help", MAXLEN - 1);
201 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
202 init->begx);
204 form_action = FA_CONTINUE;
205 break;
206 case FA_CANCEL:
207 return FA_CANCEL;
208 default:
209 form_action = FA_CONTINUE;
210 break;
211 }
212 if (form_action == FA_END)
213 break;
214 }
215 return 0;
216}
@ 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 **, uint, uint, uint, uint)
instantiate a view popup window
Definition popups.c:145
#define MAXARGS
Definition cm.h:50
#define KEY_F05
#define KEY_IC
char * eargv[MAXARGS]
Definition futil.c:51
int eargc
Definition futil.c:50
UiCell cell_nt_hl_rev
Definition dwin.c:97
void set_chyron_key_cb(Chyron *chyron, uint k, char *s, uint kc, UiCell cell_base)
Set chyron key with color pair (cp).
Definition dwin.c:1021
void compile_chyron(Chyron *chyron)
construct the chyron string from the chyron structure
Definition dwin.c:1110
Chyron * new_chyron()
Create and initialize Chyron structure.
Definition dwin.c:947
void display_chyron(UiSurface *sfc, uint w, Chyron *chyron, uint line, uint col)
Display chyron on the specified line and column of the surface.
Definition dwin.c:1163
void set_chyron_key(Chyron *chyron, uint k, char *s, uint kc)
Set chyron key with default color pair (cp_nt_rev).
Definition dwin.c:1045
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(uint argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:487
char title[MAXLEN]
Definition common.h:129
char mapp_help[MAXLEN]
Definition common.h:149
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, cell_nt_hl_rev, Form::chyron, Init::cols, compile_chyron(), 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_cb(), sfc_ptr, strnz__cat(), strnz__cpy(), Init::title, and ui_surface.

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

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

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

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

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

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

223 {
224 bool loop = true;
225 int c, rc;
226 click_y = click_x = -1;
227 Form *form = init->form;
229 UiEvent event;
230 uint maxy, maxx;
231 ui_cursor_move(sfc, WIN, form->lines - 1, 0);
232 ui_wclrtoeol(sfc, WIN);
233 // 1 F1 Help
234 // 2 F2 Process
235 // 3 F3 Calculate
236 // 4 F4 Query
237 // 5 F5 Edit
238 // 9 F9 Cancel
239 // 10 F10 Continue
240 // 11 F10 Commit
241 // 18 INS Insert
242 form->chyron->key[5]->active = true; // F5 Edit
243 form->chyron->key[10]->active = false; // F10 Continue
244 form->chyron->key[18]->active = false; // INS Insert
245 compile_chyron(form->chyron);
246 rc = -1;
247 while (loop) {
248 if (rc == -1) {
249 display_chyron(sfc, WIN, form->chyron, form->lines - 1, form->chyron->l);
250 tcflush(2, TCIFLUSH);
251 ui_render();
252 c = ui_get_event_multi(sfc, WIN, &event, -1);
253 ui_getmaxyx(sfc, WIN, &maxy, &maxx);
254 if (event.in_win == 1 && event.y == maxy - 1)
255 c = get_chyron_key(form->chyron, event.x);
256 }
257 switch (c) {
258 case KEY_F01:
259 return FA_HELP;
260 case KEY_F05: // F5 Edit
261 if (is_set_chyron_key(form->chyron, 5)) {
262 loop = false;
263 rc = FA_CONTINUE;
264 break;
265 }
266 continue;
267 case KEY_F09:
268 loop = false;
269 rc = FA_CANCEL;
270 break;
271 case KEY_F10:
272 loop = false;
273 rc = FA_ACCEPT;
274 break;
275 case KEY_MOUSE:
276 continue;
277 default:
278 break;
279 }
280 }
281 form->chyron->key[5]->active = false; // F5 Edit
282 return rc;
283}
int ui_cursor_move(UiSurface *s, uint w, uint y, uint x)
Definition ui_ncurses.c:727
int ui_wclrtoeol(UiSurface *s, uint w)
int ui_get_event_multi(UiSurface *s, uint w, UiEvent *ev, int timeout_ms)
void ui_getmaxyx(UiSurface *s, uint w, uint *lines, uint *cols)
Definition ui_ncurses.c:676
int click_x
Definition dwin.c:45
int click_y
Definition dwin.c:44
int get_chyron_key(Chyron *chyron, uint x)
Get keycode from chyron.
Definition dwin.c:1186
bool is_set_chyron_key(Chyron *chyron, uint k)
Check if function key label is set.
Definition dwin.c:1005
uint in_win
Definition ui_backend.h:110

References ChyronKey::active, Form::chyron, click_x, click_y, compile_chyron(), display_chyron(), FA_ACCEPT, FA_CANCEL, FA_CONTINUE, FA_HELP, Init::form, get_chyron_key(), UiEvent::in_win, is_set_chyron_key(), Chyron::key, Chyron::l, Form::lines, sfc_ptr, ui_cursor_move(), ui_get_event_multi(), ui_getmaxyx(), ui_render(), ui_surface, ui_wclrtoeol(), WIN, UiEvent::x, and UiEvent::y.

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_F05 Calculate, Query, or Getter. option on the chyron.
  1. The user can then cancel the operation by pressing KEY_F09 or activate the getter option by pressing KEY_F05.
  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 322 of file form_engine.c.

322 {
323 uint i, c;
324 int rc;
325 char earg_str[MAXLEN + 1];
326 char *eargv[MAXARGS];
327 int eargc;
328 char file_spec[MAXLEN];
329 bool loop = true;
330 pid_t pid;
331 int pipe_fd[2];
333 UiEvent event;
334 Form *form = init->form;
335 ui_cursor_move(sfc, WIN, form->lines - 1, 0);
336 uint maxy, maxx;
337 //
338 // 1 F1 Help
339 // 2 F2 Process
340 // 3 F3 Calculate
341 // 4 F4 Query
342 // 5 F5 Edit
343 // 9 F9 Cancel
344 // 10 F10 Continue
345 // 11 F10 Commit
346 form->chyron->key[2]->active = form->f_process > 0 ? true : false;
347 form->chyron->key[3]->active = form->f_calculate > 0 ? true : false;
348 form->chyron->key[4]->active = form->f_query > 0 ? true : false; // PgUp
349 form->chyron->key[10]->active = false; // F10 Continue
350 form->chyron->key[18]->active = false; // INS Insert
351
352 while (loop) {
353 compile_chyron(form->chyron);
354 display_chyron(sfc, 1, form->chyron, form->lines - 1, form->chyron->l);
355 click_y = click_x = -1;
356 tcflush(2, TCIFLUSH);
357 ui_render();
358 c = ui_get_event_multi(sfc, WIN, &event, -1);
359 ui_getmaxyx(sfc, WIN, &maxy, &maxx);
360 if (event.in_win == 1 && event.y == maxy - 1)
361 c = get_chyron_key(form->chyron, event.x);
362
363 switch (c) {
364 case KEY_F01:
365 return FA_HELP;
366 case KEY_F02: // F2 Process
367 case KEY_F03: // F3 Calculate
368 case KEY_F04: // F4 Query
369 if (form->f_out_spec)
371 if (form->f_provider_cmd) {
372 strnz__cpy(earg_str, form->provider_cmd, MAXLEN - 1);
373 for (i = 0; i < form->fcnt; i++) {
374 strnz__cat(earg_str, " ", MAXLEN - 1);
375 strnz__cat(earg_str, form->field[i]->accept_s, MAXLEN - 1);
376 }
378 strnz__cpy(file_spec, eargv[0], MAXLEN - 1);
379 base_name(eargv[0], file_spec);
380 if (pipe(pipe_fd) == -1) {
382 Perror("pipe(pipe_fd) failed in init_form");
383 return (1);
384 }
385 if ((pid = fork()) == -1) {
387 Perror("fork() failed in init_form");
388 return (1);
389 }
390 if (pid == 0) { // Child
392 int dev_null = open("/dev/null", O_WRONLY);
393 if (dev_null == -1) {
394 Perror("open(/dev/null) failed in init_pick child "
395 "process");
396 exit(EXIT_FAILURE);
397 }
398 dup2(dev_null, STDERR_FILENO);
399 close(dev_null);
400 close(pipe_fd[P_READ]);
401 dup2(pipe_fd[P_WRITE], STDOUT_FILENO);
402 stdio_fdnames(stdio_names_str, "form_engine.c:367");
403 close(pipe_fd[P_WRITE]);
404 execvp(eargv[0], eargv);
405 ssnprintf(em0, MAXLEN, "%s, line: %d", __FILE__,
406 __LINE__ - 2);
407 strnz__cpy(em1, "execvp(", MAXLEN - 1);
408 strnz__cat(em1, eargv[0], MAXLEN - 1);
409 strnz__cat(em1, ", ", MAXLEN - 1);
411 strnz__cat(em1, ")", MAXLEN - 1);
412 strerror_r(errno, em2, MAXLEN);
413 display_error(em0, em1, em2, nullptr);
414 exit(EXIT_FAILURE);
415 } // Back to parent
416 close(pipe_fd[P_WRITE]);
417 form->in_fp = fdopen(pipe_fd[P_READ], "rb");
418 form->f_in_pipe = true;
420 close(pipe_fd[P_READ]);
421 waitpid(pid, nullptr, 0);
422 stdio_fdnames(stdio_names_str, "form_engine.c:387");
425 form->chyron->key[2]->active = false; // F2 Process
426 form->chyron->key[3]->active = false; // F3 Calculate
427 form->chyron->key[4]->active = false; // F4 Query
428 form->chyron->key[5]->active = true; // F5 Edit
429 form->chyron->key[10]->active = true; // F10 Accept
430 compile_chyron(form->chyron);
431 continue;
432 }
433 break;
434 case KEY_F05:
435 if (is_set_chyron_key(form->chyron, 5)) {
436 loop = false;
437 rc = FA_CONTINUE;
438 break;
439 }
440 continue;
441 case KEY_F09:
442 loop = false;
443 rc = FA_CANCEL;
444 break;
445 case KEY_F10:
446 loop = false;
447 rc = FA_ACCEPT;
448 break;
449 case KEY_MOUSE:
450 break;
451 default:
452 break;
453 }
454 }
455 form->chyron->key[2]->active = false; // F2 Process
456 form->chyron->key[3]->active = false; // F3 Calculate
457 form->chyron->key[4]->active = false; // F4 Query
458 form->chyron->key[5]->active = false; // F5 Edit
459 return rc;
460}
#define P_READ
Definition common.h:50
#define P_WRITE
Definition common.h:51
char stdio_names_str[4096]
Definition futil.c:127
char * stdio_fdnames(char *, char *)
Definition futil.c:1082
int pipe_fd[2]
Definition pick_engine.c:46

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(), get_chyron_key(), Form::in_fp, UiEvent::in_win, is_set_chyron_key(), Chyron::key, Chyron::l, Form::lines, Perror(), Form::provider_cmd, sfc_ptr, ssnprintf(), stdio_fdnames(), stdio_names_str, str_to_args(), strnz__cat(), strnz__cpy(), ui_cursor_move(), ui_get_event_multi(), ui_getmaxyx(), ui_render(), ui_surface, WIN, UiEvent::x, and UiEvent::y.

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

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

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

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

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,
uint begy,
uint 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 rc = form_engine(init);
94 destroy_chyron(form->chyron);
95 if (sfc)
97 destroy_form(init);
98 return rc;
99}
int cm_surface_destroy(UiSurface *sfc)
Destroy the most recently created surface.
Definition dwin.c:576
Chyron * destroy_chyron(Chyron *chyron)
Destroy Chyron structure.
Definition dwin.c:984
int form_engine(Init *)
Form main processing loop.
Form * destroy_form(Init *init)
Destroy Form structure.
Definition mem.c:275
Form * new_form(Init *init, int argc, char **argv, uint begy, uint begx)
Create and initialize Form structure.
Definition mem.c:252

References Form::begx, Form::begy, Form::chyron, cm_surface_destroy(), 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, new_form(), Perror(), sfc_ptr, strnz__cat(), strnz__cpy(), Form::title, and ui_surface.

Referenced by main(), and popup_form().

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