C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
init.c
Go to the documentation of this file.
1/** @file init.c
2 @brief Initialization for Menu Application Programs
3 @author Bill Waller
4 Copyright (c) 2025
5 MIT License
6 billxwaller@gmail.com
7 @date 2026-02-09
8 */
9
10/**
11 @defgroup init C-Menu Initialization
12 @brief Capture Data from the Environment, Command Line, and
13 Configuration File and Populate the Init and SIO Data Structures
14 @verbatim
15 SIO Struct for screen I/O settings (colors, gamma, etc.)
16 Init Struct for application settings (file paths, commands, flags, etc.)
17 @endverbatim
18 */
19
20#include <argp.h>
21#include <common.h>
22#include <locale.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27enum {
28 IN_SPEC = 257,
65};
66
67bool f_write_config = false;
68bool f_dump_config = false;
69
70int write_config(Init *init);
71void display_version();
72
73Init *init = NULL;
74void mapp_initialization(Init *, int, char **);
75void zero_opt_args(Init *);
76int parse_config(Init *);
77int parse_opt_args(Init *, int, char **);
78void dump_config(Init *, char *);
79
80bool derive_file_spec(char *, char *, char *);
81int executor = 0;
82
84const char *argp_program_bug_address = "billxwaller@gmail.com";
85static char doc[] = "C-Menu - User Interface Toolkit";
86static char args_doc[] = "[INPUT] [OUTPUT] [HELP] [ARG4] [ARG5]";
87const int opt_doc_col = 33;
88
89static struct argp_option options[] = {
90 {"f_dump_config", 'D', 0, 0, "dump configuration", 0},
91 {"f_write_config", 'W', 0, 0, "write configuration", 0},
92 {"minitrc", 'a', "file_spec", 0, "configuration file spec", 1},
93 {"parent_cmd", 'k', 0, 0, "parent command", 1},
94 {"begx", 'X', "number", 0, "begin on column", 2},
95 {"begy", 'Y', "number", 0, "begin on line", 2},
96 {"cols", 'C', "number", 0, "width in columns", 2},
97 {"lines", 'L', "number", 0, "height in lines", 2},
98 {"out_spec", 'o', "file_spec", 0, "output spec", 2},
99 {"select_max", 'n', "number", 0, "number of selections", 2},
100 {"cmd", 'c', "file_spec", 0, "view cmd, first file", 3},
101 {"cmd_all", 'A', "file_spec", 0, "view cmd, all files", 3},
102 {"help_spec", 'H', "file_spec", 0, "help spec", 3},
103 {"in_spec", 'i', "file_spec", 0, "input spec", 3},
104 {"mapp_spec", 'd', "file_spec", 0, "description spec", 3},
105 {"provider_cmd", 'S', "file_spec", 0, "execute provider of piped input", 3},
106 {"receiver_cmd", 'R', "file_spec", 0, "execute receiver of piped output",
107 3},
108 {"title", 'T', "text", 0, "Window title", 3},
109 {"wait_timeout", 'w', "seconds", 0, "Wait timer", 3},
110 {"f_erase_remainder", 'e', "bool", 0, "erase remainder of line on enter",
111 4},
112 {"f_strip_ansi", 'j', "bool", 0, "always strip ansi when writing", 4},
113 {"f_squeeze", 's', "bool", 0, "squeeze multiple blank lines", 4},
114 {"f_ignore_case", 'x', "bool", 0, "ignore case in search", 4},
115 {"f_ln", 'N', "bool", 0, "line numbers in view", 5},
116 {"fill_char", 'f', "char", 0, "field fill_char", 5},
117 {"brackets", 'u', "text", 0, "brackets around fields", 5},
118 {"editor", CM_EDITOR, "text", 0, "default editor", 8},
119 {"tab_stop", 't', "number", 0, "number of spaces per tab", 5},
120 {"bg_clr_x", BG_XCLR, "hex_clr", 0, "background color", 6},
121 {"bo_clr_x", BO_XCLR, "hex_clr", 0, "border color", 6},
122 {"fg_clr_x", FG_XCLR, "hex_clr", 0, "foreground color", 6},
123 {"ln__bg_clr_x", LN_BG_CLR, "hex_clr", 0, "line number background", 6},
124 {"ln_clr_x", LN_XCLR, "hex_clr", 0, "line number color", 6},
125 {"blue_gamma", GM_BLUE, "float", 0, "blue_gamma (View)", 7},
126 {"gray_gamma", GM_GRAY, "float", 0, "gray gamma (View)", 7},
127 {"green_gamma", GM_GREEN, "float", 0, "green gamma (View)", 7},
128 {"red_gamma", GM_RED, "float", 0, "red gamma (View)", 7},
129 {"black", XBLACK, "hex_clr", 0, "black (#000000)", 8},
130 {"red", XRED, "hex_clr", 0, "red (#bf0000)", 8},
131 {"green", XGREEN, "hex_clr", 0, "green (#00cf00)", 8},
132 {"yellow", XYELLOW, "hex_clr", 0, "yellow (#efbf00)", 8},
133 {"blue", XBLUE, "hex_clr", 0, "blue (#0000FF)", 8},
134 {"magenta", XMAGENTA, "hex_clr", 0, "magenta (#9f009f)", 8},
135 {"cyan", XCYAN, "hex_clr", 0, "cyan (#00dfdf)", 8},
136 {"white", XWHITE, "hex_clr", 0, "white (#d0d0d0)", 8},
137 {"bblack", XBBLACK, "hex_clr", 0, "bright black (#7f7f7f)", 8},
138 {"bred", XBRED, "hex_clr", 0, "bright red (#FF3737)", 8},
139 {"bgreen", XBGREEN, "hex_clr", 0, "bright green (#00FF7f)", 8},
140 {"byellow", XBYELLOW, "hex_clr", 0, "bright yellow (#FFeF00)", 8},
141 {"bblue", XBBLUE, "hex_clr", 0, "bright blue (#00cfFF)", 8},
142 {"bmagenta", XMAGENTA, "hex_clr", 0, "bright magenta (#FF00FF)", 8},
143 {"bcyan", XBCYAN, "hex_clr", 0, "bright cyan (#00FFFF)", 8},
144 {"bwhite", XBWHITE, "hex_clr", 0, "bright white (#FFFFFF)", 8},
145 {"mapp_data", MAPP_DATA, "directory", 0, "data directory", 9},
146 {"mapp_help", MAPP_HELP, "directory", 0, "help directory", 9},
147 {"mapp_home", MAPP_HOME, "directory", 0, "home directory", 9},
148 {"mapp_msrc", MAPP_MSRC, "directory", 0, "source directory", 9},
149 {"mapp_user", MAPP_USER, "directory", 0, "user directory", 9},
150 {0},
151};
152
153static error_t parse_opt(int key, char *arg, struct argp_state *state) {
154 Init *init = state->input;
155 SIO *sio = init->sio;
156 switch (key) {
157 case 'a':
159 break;
160 case 'b':
162 break;
163 case 'c':
164 strnz__cpy(init->cmd, arg, MAXLEN - 1);
165 break;
166 case 'd':
168 break;
169 case 'e':
171 break;
172 case 'f':
174 break;
175 case 'g':
177 break;
178 case 'i':
180 break;
181 case 'j':
182 init->f_strip_ansi = true;
183 break;
184 case 'k':
186 break;
187 case 'm':
189 break;
190 case 'n':
191 init->select_max = atoi(arg);
192 break;
193 case 'o':
195 break;
196 case 'r':
198 break;
199 case 's':
200 init->f_squeeze = str_to_bool(arg);
201 break;
202 case 't':
203 init->tab_stop = atoi(arg);
204 if (init->tab_stop < 1)
205 init->tab_stop = 1;
206 break;
207 case 'w':
208 wait_timeout = atoi(arg);
211 break;
212 case 'u':
213 strnz__cpy(init->brackets, arg, 2);
214 break;
215 case 'x':
217 break;
218 case 'A':
220 break;
221 case 'B':
223 break;
224 case 'C':
225 init->cols = atoi(arg);
226 break;
227 case 'D':
228 f_dump_config = true;
229 break;
230 case 'F':
232 break;
233 case 'G':
235 break;
236 case 'H':
238 break;
239 case 'L':
240 init->lines = atoi(arg);
241 break;
242 case 'M':
244 break;
245 case 'N':
246 init->f_ln = str_to_bool(arg);
247 break;
248 case 'O':
250 break;
251 case 'R':
253 break;
254 case 'S':
256 break;
257 case 'T':
258 strnz__cpy(init->title, arg, MAXLEN - 1);
259 break;
260 case 'U':
262 break;
263 case 'W':
264 f_write_config = true;
265 break;
266 case 'X':
267 init->begx = atoi(arg);
268 break;
269 case 'Y':
270 init->begy = atoi(arg);
271 break;
272 case MAPP_DATA_DIR:
274 break;
275 case MAPP_HELP_DIR:
277 break;
278 case MAPP_SPEC:
280 break;
281 case HELP_SPEC:
283 break;
284 case IN_SPEC:
286 break;
287 case OUT_SPEC:
289 break;
290 case MAPP_MSRC:
292 break;
293 case ARGP_KEY_ARG:
294 if (state->arg_num >= 5)
295 argp_usage(state);
296 init->argv[state->arg_num] = arg;
297 break;
298 case ARGP_KEY_END:
299 init->argc = state->arg_num;
300 init->argv[state->arg_num + 1] = NULL;
301 break;
302 default:
303 return ARGP_ERR_UNKNOWN;
304 }
305 return 0;
306}
307
308static struct argp argp = {options, parse_opt, args_doc, doc,
310
311/** @brief Main initialization function for MAPP - Menu Application
312 @ingroup init
313 @param init - pointer to Init struct to be initialized
314 @param argc - argument count from main()
315 @param argv - argument vector from main()
316 @code
317 1. Read environment variables and set defaults
318 2. Parse configuration file
319 3. Parse command-line options
320 4. Set up SIO struct with colors and other settings
321 5. Handle special options like help and version
322 @endcode
323 */
324void mapp_initialization(Init *init, int argc, char **argv) {
325 char term[MAXLEN];
326 char tmp_str[MAXLEN];
327 char *e;
328 setlocale(LC_ALL, "en_US.UTF-8");
329 SIO *sio = init->sio;
330 if (!init) {
331 ssnprintf(tmp_str, sizeof(tmp_str), "%s",
332 "init struct not allocated on entry");
333 abend(-1, tmp_str);
334 exit(-1);
335 }
336
337 e = getenv("CMENU_HOME");
338 if (!e || *e == '\0')
339 strnz__cpy(init->mapp_home, "~/menuapp", MAXLEN);
340 else
342 e = getenv("CMENU_RC");
343 if (!e || *e == '\0')
344 strnz__cpy(init->minitrc, "~/menuapp/.minitrc", MAXLEN);
345 else
347 if (init->minitrc[0] == '\0')
348 strnz__cpy(init->minitrc, "~/.minitrc", MAXLEN - 1);
349 strnz__cpy(sio->bg_clr_x, "#000007", COLOR_LEN - 1); /**< background color */
350 strnz__cpy(sio->fg_clr_x, "#c0c0c0", COLOR_LEN - 1); /**< foreground color */
351 strnz__cpy(sio->bo_clr_x, "#f00000", COLOR_LEN - 1); /**< bold color */
352 strnz__cpy(sio->ln_clr_x, "#0070ff", COLOR_LEN - 1); /**< line number olor */
353 strnz__cpy(sio->ln_bg_clr_x, "#101010",
354 COLOR_LEN - 1); /**< line number background */
355 init->f_erase_remainder = true; /**< erase remainder on enter */
356 init->brackets[0] = '\0'; /**< field enclosure brackets */
357 strnz__cpy(init->fill_char, "_", MAXLEN - 1); /**< field fill character */
358 init->mapp_spec[0] = '\0'; /**< menu specification file */
359 strnz__cpy(init->mapp_home, "~/menuapp", MAXLEN - 1);
360 strnz__cpy(init->mapp_user, "~/menuapp/user", MAXLEN - 1);
361 strnz__cpy(init->mapp_msrc, "~/menuapp/msrc", MAXLEN - 1);
362 strnz__cpy(init->mapp_data, "~/menuapp/data", MAXLEN - 1);
363 strnz__cpy(init->mapp_help, "~/menuapp/help", MAXLEN - 1);
364
365 e = getenv("TERM");
366 if (e == nullptr || *e == '\0')
367 strnz__cpy(term, "xterm-256color", MAXLEN);
368 else
369 strnz__cpy(term, e, MAXLEN - 1);
370 e = getenv("EDITOR");
371 if (e && *e != '\0')
372 strnz__cpy(init->editor, "vi", MAXLEN - 1);
373 else
375 parse_config(init);
376 init->argc = argc;
377 argp_parse(&argp, argc, argv, 0, 0, init);
378 if (f_write_config) {
379 write_config(init);
380 exit(EXIT_SUCCESS);
381 }
382 if (f_dump_config) {
383 dump_config(init, "Current Configuration");
384 exit(EXIT_SUCCESS);
385 }
386 if (init->mapp_home[0] != '\0') {
388 if (!verify_dir(init->mapp_home, R_OK))
389 abend(-1, "MAPP_HOME directory invalid");
390 }
391}
392
393int parse_opt_args(Init *init, int argc, char **argv) {
394 init->argc = 0;
395 argp_parse(&argp, argc, argv, 0, 0, init);
396 return 0;
397}
398
399/** @brief Initialize optional arguments in the Init struct to default
400 values
401 @ingroup init
402 @param init - pointer to Init struct to be initialized This function
403 sets all optional argument fields in the Init struct to their default
404 values before parsing command-line options or configuration file. This
405 ensures that any fields not specified by the user will have known default
406 values.
407 */
408void zero_opt_args(Init *init) {
409 init->f_mapp_desc = false;
410 init->f_provider_cmd = false;
411 init->f_receiver_cmd = false;
412 init->f_title = false;
413 init->f_mapp_spec = false;
414 init->f_help_spec = false;
415 init->f_in_spec = false;
416 init->f_out_spec = false;
417 init->mapp_spec[0] = init->help_spec[0] = '\0';
418 init->provider_cmd[0] = init->receiver_cmd[0] = '\0';
419 init->title[0] = '\0';
420 init->cmd[0] = init->cmd_all[0] = '\0';
421 init->parent_cmd[0] = '\0';
422 init->in_spec[0] = init->out_spec[0] = '\0';
423 init->help_spec[0] = '\0';
424 init->in_spec[0] = '\0';
425 init->out_spec[0] = '\0';
426}
427/** @brief parse the configuration file specified in init->minitrc and set
428 Init struct values accordingly
429 @ingroup init
430 @returns on success, -1 on failure
431 @note lines beginning with '#" are comments, discard
432 @note copy line to tmp_str removing quotes, spaces, semicolons, and
433 newlines
434 @note record structure is "parse key=value pairs"
435 @note skip lines without '='
436 @note set init struct values based on key
437 @note skips unknown keys */
438int parse_config(Init *init) {
439 char ts[MAXLEN];
440 char *sp, *dp;
441 char tmp_str[MAXLEN];
442 SIO *sio = init->sio;
443 if (!init->minitrc[0]) {
444 char *e = getenv("MINITRC");
445 if (e)
447 else
448 strnz__cpy(init->minitrc, "~/.minitrc", MAXLEN - 1);
449 }
451 FILE *config_fp = fopen(init->minitrc, "r");
452 if (!config_fp) {
453 fprintf(stderr, "failed to read file: %s\n", init->minitrc);
454 return (-1);
455 }
456 while (fgets(ts, sizeof(ts), config_fp)) {
457 if (ts[0] != '#') {
458 sp = ts;
459 dp = tmp_str;
460 while (*sp != '\0') {
461 if (*sp == '\n') {
462 *dp = *sp = '\0';
463 } else {
464 if (*sp != '"' && *sp != ' ' && *sp != ';') {
465 *dp++ = *sp;
466 }
467 sp++;
468 }
469 }
470 *dp = '\0';
471 char *key = strtok(tmp_str, "=");
472 char *value = strtok(nullptr, "=");
473 if (value == nullptr)
474 continue;
475 if (!strcmp(key, "minitrc")) {
476 strnz__cpy(init->minitrc, value, MAXLEN - 1);
477 continue;
478 }
479 if (!strcmp(key, "lines")) {
480 init->lines = atoi(value);
481 continue;
482 }
483 if (!strcmp(key, "cols")) {
484 init->cols = atoi(value);
485 continue;
486 }
487 if (!strcmp(key, "begy")) {
488 init->begy = atoi(value);
489 continue;
490 }
491 if (!strcmp(key, "begx")) {
492 init->begx = atoi(value);
493 continue;
494 }
495 if (!strcmp(key, "fg_clr_x")) {
497 continue;
498 }
499 if (!strcmp(key, "bg_clr_x")) {
501 continue;
502 }
503 if (!strcmp(key, "f_ln")) {
504 init->f_ln = str_to_bool(value);
505 continue;
506 }
507 if (!strcmp(key, "bo_clr_x")) {
509 continue;
510 }
511 if (!strcmp(key, "ln_clr_x")) {
513 continue;
514 }
515 if (!strcmp(key, "ln_bg_clr_x")) {
517 continue;
518 }
519 if (!strcmp(key, "red_gamma")) {
521 continue;
522 }
523 if (!strcmp(key, "green_gamma")) {
525 continue;
526 }
527 if (!strcmp(key, "blue_gamma")) {
529 continue;
530 }
531 if (!strcmp(key, "gray_gamma")) {
533 continue;
534 }
535 if (!strcmp(key, "f_at_end_remove")) {
537 continue;
538 }
539 if (!strcmp(key, "f_erase_remainder")) {
541 continue;
542 }
543 if (!strcmp(key, "brackets")) {
544 strnz__cpy(init->brackets, value, 2);
545 continue;
546 }
547 if (!strcmp(key, "fill_char")) {
548 strnz__cpy(init->fill_char, value, 2);
549 continue;
550 }
551 if (!strcmp(key, "f_ignore_case")) {
553 continue;
554 }
555 if (!strcmp(key, "f_squeeze")) {
556 init->f_squeeze = str_to_bool(value);
557 continue;
558 }
559 if (!strcmp(key, "f_strip_ansi")) {
560 init->f_strip_ansi = str_to_bool(value);
561 continue;
562 }
563 if (!strcmp(key, "select_max")) {
564 init->select_max = atoi(value);
565 continue;
566 }
567 if (!strcmp(key, "tab_stop")) {
568 init->tab_stop = atoi(value);
569 continue;
570 }
571 if (!strcmp(key, "wait_timeout")) {
572 wait_timeout = atoi(value);
573 continue;
574 }
575 if (!strcmp(key, "title")) {
576 strnz__cpy(init->title, value, MAXLEN - 1);
577 continue;
578 }
579 if (!strcmp(key, "cmd")) {
580 strnz__cpy(init->cmd, value, MAXLEN - 1);
581 continue;
582 }
583 if (!strcmp(key, "cmd_all")) {
584 strnz__cpy(init->cmd_all, value, MAXLEN - 1);
585 continue;
586 }
587 if (!strcmp(key, "parent_cmd")) {
589 continue;
590 }
591 if (!strcmp(key, "provider_cmd")) {
593 continue;
594 }
595 if (!strcmp(key, "receiver_cmd")) {
597 continue;
598 }
599 if (!strcmp(key, "bg")) {
600 strnz__cpy(sio->bg, value, COLOR_LEN - 1);
601 continue;
602 }
603 if (!strcmp(key, "black")) {
604 strnz__cpy(sio->black, value, COLOR_LEN - 1);
605 continue;
606 }
607 if (!strcmp(key, "red")) {
608 strnz__cpy(sio->red, value, COLOR_LEN - 1);
609 continue;
610 }
611 if (!strcmp(key, "green")) {
612 strnz__cpy(sio->green, value, COLOR_LEN - 1);
613 continue;
614 }
615 if (!strcmp(key, "yellow")) {
617 continue;
618 }
619 if (!strcmp(key, "blue")) {
620 strnz__cpy(sio->blue, value, COLOR_LEN - 1);
621 continue;
622 }
623 if (!strcmp(key, "magenta")) {
625 continue;
626 }
627 if (!strcmp(key, "cyan")) {
628 strnz__cpy(sio->cyan, value, COLOR_LEN - 1);
629 continue;
630 }
631 if (!strcmp(key, "white")) {
632 strnz__cpy(sio->white, value, COLOR_LEN - 1);
633 continue;
634 }
635 if (!strcmp(key, "orange")) {
637 continue;
638 }
639 if (!strcmp(key, "bblack")) {
641 continue;
642 }
643 if (!strcmp(key, "bred")) {
644 strnz__cpy(sio->bred, value, COLOR_LEN - 1);
645 continue;
646 }
647 if (!strcmp(key, "bgreen")) {
649 continue;
650 }
651 if (!strcmp(key, "byellow")) {
653 continue;
654 }
655 if (!strcmp(key, "bblue")) {
656 strnz__cpy(sio->bblue, value, COLOR_LEN - 1);
657 continue;
658 }
659 if (!strcmp(key, "bmagenta")) {
661 continue;
662 }
663 if (!strcmp(key, "bcyan")) {
664 strnz__cpy(sio->bcyan, value, COLOR_LEN - 1);
665 continue;
666 }
667 if (!strcmp(key, "bwhite")) {
669 continue;
670 }
671 if (!strcmp(key, "borange")) {
673 continue;
674 }
675 if (!strcmp(key, "bg")) {
676 strnz__cpy(sio->bg, value, COLOR_LEN - 1);
677 continue;
678 }
679 if (!strcmp(key, "editor")) {
680 strnz__cpy(init->editor, value, MAXLEN - 1);
681 continue;
682 }
683 if (!strcmp(key, "mapp_spec")) {
684 strnz__cpy(init->mapp_spec, value, MAXLEN - 1);
685 continue;
686 }
687 if (!strcmp(key, "mapp_data")) {
688 strnz__cpy(init->mapp_data, value, MAXLEN - 1);
689 continue;
690 }
691 if (!strcmp(key, "mapp_help")) {
692 strnz__cpy(init->mapp_help, value, MAXLEN - 1);
693 continue;
694 }
695 if (!strcmp(key, "mapp_home")) {
696 strnz__cpy(init->mapp_home, value, MAXLEN - 1);
697 continue;
698 }
699 if (!strcmp(key, "mapp_msrc")) {
700 strnz__cpy(init->mapp_msrc, value, MAXLEN - 1);
701 continue;
702 }
703 if (!strcmp(key, "mapp_user")) {
704 strnz__cpy(init->mapp_user, value, MAXLEN - 1);
705 continue;
706 }
707 }
708 }
709 (void)fclose(config_fp);
710 return 0;
711}
712/** @brief Write the current configuration to a file specified in
713 init->minitrc
714 @ingroup init
715 @param init - pointer to Init struct containing current configuration
716 @returns 0 on success, -1 on failure
717 @note The configuration is written in key=value format, one per line
718 @note Lines beginning with '#' are comments and are ignored when reading
719 the config file
720 @note The file is created if it does not exist, and overwritten if it
721 does exist
722 */
723int write_config(Init *init) {
724 char *e;
725 char minitrc_dmp[MAXLEN];
726 char tmp_str[MAXLEN];
727 SIO *sio = init->sio;
728 e = getenv("HOME");
729 if (e) {
730 strnz__cpy(minitrc_dmp, e, MAXLEN - 1);
731 strnz__cat(minitrc_dmp, "/", MAXLEN - 1);
732 strnz__cat(minitrc_dmp, "menuapp/minitrc.dmp", MAXLEN - 1);
733 ;
734 } else {
735 strnz__cpy(minitrc_dmp, "./minitrc.dmp", MAXLEN - 1);
736 }
737 FILE *minitrc_fp = fopen(minitrc_dmp, "w");
738 if (minitrc_fp == (FILE *)0) {
739 fprintf(stderr, "failed to open file: %s\n", minitrc_dmp);
740 return (-1);
741 }
742 (void)fprintf(minitrc_fp, "# %s\n", "~/.minitrc");
743 (void)fprintf(minitrc_fp, "%s=%s\n", "parent_cmd", init->parent_cmd);
744 (void)fprintf(minitrc_fp, "%s=%d\n", "cols", init->cols);
745 (void)fprintf(minitrc_fp, "%s=%d\n", "lines", init->lines);
746 (void)fprintf(minitrc_fp, "%s=%d\n", "select_max", init->select_max);
747 (void)fprintf(minitrc_fp, "%s=%s\n", "out_spec", init->out_spec);
748 (void)fprintf(minitrc_fp, "%s=%d\n", "begx", init->begx);
749 (void)fprintf(minitrc_fp, "%s=%d\n", "begy", init->begy);
750 (void)fprintf(minitrc_fp, "%s=%s\n", "cmd_all", init->cmd_all);
751 (void)fprintf(minitrc_fp, "%s=%s\n", "cmd", init->cmd);
752 (void)fprintf(minitrc_fp, "%s=%s\n", "mapp_spec", init->mapp_spec);
753 (void)fprintf(minitrc_fp, "%s=%s\n", "help_spec", init->help_spec);
754 (void)fprintf(minitrc_fp, "%s=%s\n", "in_spec", init->in_spec);
755 (void)fprintf(minitrc_fp, "%s=%s\n", "receiver_cmd", init->receiver_cmd);
756 (void)fprintf(minitrc_fp, "%s=%s\n", "provider_cmd", init->provider_cmd);
757 (void)fprintf(minitrc_fp, "%s=%s\n", "title", init->title);
758 (void)fprintf(minitrc_fp, "%s=%s\n", "f_erase_remainder",
759 init->f_erase_remainder ? "true" : "false");
760 (void)fprintf(minitrc_fp, "%s=%s\n", "f_strip_ansi",
761 init->f_strip_ansi ? "true" : "false");
762 (void)fprintf(minitrc_fp, "%s=%s\n", "f_squeeze",
763 init->f_squeeze ? "true" : "false");
764 (void)fprintf(minitrc_fp, "%s=%s\n", "f_ignore_case",
765 init->f_ignore_case ? "true" : "false");
766 (void)fprintf(minitrc_fp, "%s=%s\n", "f_ln", init->f_ln ? "true" : "false");
767 (void)fprintf(minitrc_fp, "%s=%s\n", "brackets", init->brackets);
768 (void)fprintf(minitrc_fp, "%s=%s\n", "fill_char", init->fill_char);
769 (void)fprintf(minitrc_fp, "%s=%s\n", "editor", init->editor);
770 (void)fprintf(minitrc_fp, "%s=%d\n", "tab_stop", init->tab_stop);
771 (void)fprintf(minitrc_fp, "%s=%d\n", "wait_timeout", wait_timeout);
772 (void)fprintf(minitrc_fp, "%s=%s\n", "bg_clr_x", sio->bg_clr_x);
773 (void)fprintf(minitrc_fp, "%s=%s\n", "bo_clr_x", sio->bo_clr_x);
774 (void)fprintf(minitrc_fp, "%s=%s\n", "fg_clr_x", sio->fg_clr_x);
775 (void)fprintf(minitrc_fp, "%s=%s\n", "ln_bg_clr_x", sio->ln_bg_clr_x);
776 (void)fprintf(minitrc_fp, "%s=%s\n", "ln_clr_x", sio->ln_clr_x);
777 (void)fprintf(minitrc_fp, "%s=%0.2f\n", "blue_gamma", sio->blue_gamma);
778 (void)fprintf(minitrc_fp, "%s=%0.2f\n", "gray_gamma", sio->gray_gamma);
779 (void)fprintf(minitrc_fp, "%s=%0.2f\n", "green_gamma", sio->green_gamma);
780 (void)fprintf(minitrc_fp, "%s=%0.2f\n", "red_gamma", sio->red_gamma);
781 (void)fprintf(minitrc_fp, "%s=%s\n", "black", sio->black);
782 (void)fprintf(minitrc_fp, "%s=%s\n", "red", sio->red);
783 (void)fprintf(minitrc_fp, "%s=%s\n", "green", sio->green);
784 (void)fprintf(minitrc_fp, "%s=%s\n", "yellow", sio->yellow);
785 (void)fprintf(minitrc_fp, "%s=%s\n", "blue", sio->blue);
786 (void)fprintf(minitrc_fp, "%s=%s\n", "magenta", sio->magenta);
787 (void)fprintf(minitrc_fp, "%s=%s\n", "cyan", sio->cyan);
788 (void)fprintf(minitrc_fp, "%s=%s\n", "white", sio->white);
789 (void)fprintf(minitrc_fp, "%s=%s\n", "bblack", sio->bblack);
790 (void)fprintf(minitrc_fp, "%s=%s\n", "bred", sio->bred);
791 (void)fprintf(minitrc_fp, "%s=%s\n", "bgreen", sio->bgreen);
792 (void)fprintf(minitrc_fp, "%s=%s\n", "byellow", sio->byellow);
793 (void)fprintf(minitrc_fp, "%s=%s\n", "bblue", sio->bblue);
794 (void)fprintf(minitrc_fp, "%s=%s\n", "bmagenta", sio->bmagenta);
795 (void)fprintf(minitrc_fp, "%s=%s\n", "bcyan", sio->bcyan);
796 (void)fprintf(minitrc_fp, "%s=%s\n", "bwhite", sio->bwhite);
797 (void)fprintf(minitrc_fp, "%s=%s\n", "editor", init->editor);
798 (void)fprintf(minitrc_fp, "%s=%s\n", "mapp_data", init->mapp_data);
799 (void)fprintf(minitrc_fp, "%s=%s\n", "mapp_help", init->mapp_help);
800 (void)fprintf(minitrc_fp, "%s=%s\n", "mapp_home", init->mapp_home);
801 (void)fprintf(minitrc_fp, "%s=%s\n", "mapp_msrc", init->mapp_msrc);
802 (void)fprintf(minitrc_fp, "%s=%s\n", "mapp_user", init->mapp_user);
803 (void)fclose(minitrc_fp);
804 strnz__cpy(tmp_str, "Configuration written to file: ", MAXLEN - 1);
805 strnz__cat(tmp_str, minitrc_dmp, MAXLEN - 1);
806 Perror(tmp_str);
807 return 0;
808}
809/** @brief Derive full file specification from directory and file name
810 @ingroup init
811 @param file_spec - output full file specification
812 @param dir - directory path
813 @param file_name - file name
814 @returns true if file_spec is derived, false otherwise
815 @note If dir is nullptr, use MAPP_DIR environment variable or default
816 directory
817 ~/menuapp
818 @note file_spec should be a pre-allocated char array of size MAXLEN to
819 hold the resulting file specification
820 */
821bool derive_file_spec(char *file_spec, char *dir, char *file_name) {
822 char ts[MAXLEN];
823 char ts2[MAXLEN];
824 char *e;
825
826 if (!file_name || !*file_name) {
827 *file_spec = '\0';
828 return false;
829 }
830 if (dir) {
831 strnz__cpy(ts, dir, MAXLEN - 1);
832 } else {
833 e = getenv("MAPP_DIR");
834 if (e) {
835 strnz__cpy(ts, e, MAXLEN - 1);
836 } else {
837 strnz__cpy(ts, "~/menuapp", MAXLEN - 1);
838 }
839 }
840 trim_path(ts);
841 strnz__cpy(ts2, ts, MAXLEN - 1);
842 // construct the full file specification
843 // check that the file exists and is readable
844 strnz__cpy(file_spec, ts2, MAXLEN - 1);
845 strnz__cat(file_spec, "/", MAXLEN - 1);
846 strnz__cat(file_spec, file_name, MAXLEN - 1);
847 return true;
848}
849/** @brief Display the version information of the application
850 @ingroup init
851 @note The version information is defined in the mapp_version variable
852 and is printed to stdout when this function is called. */
854 fprintf(stdout, "\nC-Menu %s\n", CM_VERSION);
855 fprintf(stdout, "\nC-Menu %s\n", CM_VERSION);
856 fprintf(stdout, "C version: %ld\n", __STDC_VERSION__);
857}
858/** @brief Print an option and its value in a formatted manner
859 @ingroup init
860 @param o - option flag (e.g., "-a:")
861 @param name - option name (e.g., "--minitrc")
862 @param value - option value to print
863 @note This function is used to display the current configuration options
864 and their values in a readable format. */
865void opt_prt_char(const char *o, const char *name, const char *value) {
866 fprintf(stdout, "%3s %-15s: %s\n", o, name, value);
867}
868/** @brief Print an option and its value in a formatted manner for integer
869 values
870 @ingroup init
871 @param o - option flag (e.g., "-C:")
872 @param name - option name (e.g., "--cols")
873 @param value - integer option value to print
874 @note This function is used to display the current configuration options
875 and their integer values in a readable format. */
876void opt_prt_str(const char *o, const char *name, const char *value) {
877 fprintf(stdout, "%3s %-15s: %s\n", o, name, value);
878}
879/** @brief Print an option and its value in a formatted manner for integer
880 values
881 @ingroup init
882 @param o - option flag (e.g., "-C:")
883 @param name - option name (e.g., "--cols")
884 @param value - integer option value to print
885 @note This function is used to display the current configuration options
886 and their integer values in a readable format. */
887void opt_prt_int(const char *o, const char *name, int value) {
888 fprintf(stdout, "%3s %-15s: %d\n", o, name, value);
889}
890/** @brief Print an option and its value in a formatted manner for double
891 values
892 @ingroup init
893 @param o - option flag (e.g., "-r:")
894 @param name - option name (e.g., "red_gamma")
895 @param value - double option value to print
896 @note This function is used to display the current configuration options
897 and their double values in a readable format. */
898void opt_prt_double(const char *o, const char *name, double value) {
899 fprintf(stdout, "%3s %-15s: %0.2f\n", o, name, value);
900}
901/** @brief Print an option and its value in a formatted manner for boolean
902 values
903 @ingroup init
904 @param o - option flag (e.g., "-z")
905 @param name - option name (e.g., "f_squeeze")
906 @param value - boolean option value to print
907 @note This function is used to display the current configuration options
908 and their boolean values in a readable format, printing "true" or "false"
909 based on the value. */
910void opt_prt_bool(const char *o, const char *name, bool value) {
911 fprintf(stdout, "%3s %-15s: %s\n", o, name, value ? "true" : "false");
912}
913/** @brief Dump the current configuration to stdout for debugging purposes
914 @ingroup init
915 @param init - pointer to Init struct containing the current
916 configuration
917 @param msg - string to print before dumping the configuration to stdout
918 in a readable format, prefixed by the provided title string. */
919void dump_config(Init *init, char *msg) {
920 SIO *sio = init->sio;
921 opt_prt_str("-a:", "--minitrc", init->minitrc);
922 opt_prt_str("-k:", " parent_cmd", init->parent_cmd);
923 opt_prt_int("-C:", " cols", init->cols);
924 opt_prt_int("-L:", " lines", init->lines);
925 opt_prt_int("-n:", " select_max", init->select_max);
926 opt_prt_str("-o:", " out_spec", init->out_spec);
927 opt_prt_int("-X:", " begx", init->begx);
928 opt_prt_int("-Y:", " begy", init->begy);
929 opt_prt_str("-A:", " cmd_all", init->cmd_all);
930 opt_prt_str("-c:", " cmd", init->cmd);
931 opt_prt_str("-d:", "--mapp_spec", init->mapp_spec);
932 opt_prt_str(" ", " help_spec", init->help_spec);
933 opt_prt_str("-i:", " in_spec", init->in_spec);
934 opt_prt_str("-R:", " receiver_cmd", init->receiver_cmd);
935 opt_prt_str("-S:", " provider_cmd", init->provider_cmd);
936 opt_prt_str(" ", " title", init->title);
937 opt_prt_bool("-e:", " f_erase_remainder", init->f_erase_remainder);
938 opt_prt_bool("-a ", " f_strip_ansi", init->f_strip_ansi);
939 opt_prt_bool("-s ", " f_squeeze", init->f_squeeze);
940 opt_prt_bool("-x:", " f_ignore_case", init->f_ignore_case);
941 opt_prt_bool("-N:", " f_ln", init->f_ln);
942 opt_prt_int("-t:", " tab_stop", init->tab_stop);
943 opt_prt_int("-w:", " wait_timeout", wait_timeout);
944 opt_prt_str("-u ", " brackets", init->brackets);
945 opt_prt_str("-f:", " fill_char", init->fill_char);
946 opt_prt_str(" ", " editor", init->editor);
947 opt_prt_str(" ", " bg_clr_x", sio->bg_clr_x);
948 opt_prt_str(" ", " bo_clr_x", sio->bo_clr_x);
949 opt_prt_str(" ", " fg_clr_x", sio->fg_clr_x);
950 opt_prt_str(" ", " ln_bg_clr_x", sio->ln_bg_clr_x);
951 opt_prt_str(" ", " ln_clr_x", sio->ln_clr_x);
952 opt_prt_double(" ", " blue_gamma", sio->blue_gamma);
953 opt_prt_double(" ", " gray_gamma", sio->gray_gamma);
954 opt_prt_double(" ", " green_gamma", sio->green_gamma);
955 opt_prt_double(" ", " red_gamma", sio->red_gamma);
956 opt_prt_str(" ", " black", sio->black);
957 opt_prt_str(" ", " red", sio->red);
958 opt_prt_str(" ", " green", sio->green);
959 opt_prt_str(" ", " yellow", sio->yellow);
960 opt_prt_str(" ", " blue", sio->blue);
961 opt_prt_str(" ", " magenta", sio->magenta);
962 opt_prt_str(" ", " cyan", sio->cyan);
963 opt_prt_str(" ", " white", sio->white);
964 opt_prt_str(" ", " orange", sio->orange);
965 opt_prt_str(" ", " bblack", sio->bblack);
966 opt_prt_str(" ", " bred", sio->bred);
967 opt_prt_str(" ", " bgreen", sio->bgreen);
968 opt_prt_str(" ", " byellow", sio->byellow);
969 opt_prt_str(" ", " bblue", sio->bblue);
970 opt_prt_str(" ", " bmagenta", sio->bmagenta);
971 opt_prt_str(" ", " bcyan", sio->bcyan);
972 opt_prt_str(" ", " bwhite", sio->bwhite);
973 opt_prt_str(" ", " borange", sio->borange);
974 opt_prt_str(" ", "--mapp_data", init->mapp_data);
975 opt_prt_str(" ", "--mapp_help", init->mapp_help);
976 opt_prt_str(" ", "--mapp_home", init->mapp_home);
977 opt_prt_str(" ", "--mapp_msrc", init->mapp_msrc);
978 opt_prt_str(" ", "--mapp_user", init->mapp_user);
979 (void)fprintf(stdout, "\n%s\n\n", msg);
980}
Init * init
Definition common.h:186
int parse_opt_args(Init *, int, char **)
Definition init.c:393
int wait_timeout
Definition futil.c:98
#define COLOR_LEN
Definition cm.h:180
#define nullptr
Definition cm.h:23
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:55
bool str_to_bool(const char *)
Converts String to boolean true or false.
Definition futil.c:649
#define max(a, b)
max macro evaluates two expressions, returning greatest result.
Definition cm.h:48
#define CM_VERSION
Definition version.h:7
#define MAXLEN
Definition curskeys.c:15
bool f_dump_config
Definition init.c:68
const int opt_doc_col
Definition init.c:87
const char * argp_program_version
Definition init.c:83
@ XBRED
Definition init.c:46
@ MAPP_HOME
Definition init.c:58
@ XGREEN
Definition init.c:51
@ XRED
Definition init.c:53
@ MAPP_DATA
Definition init.c:56
@ XBCYAN
Definition init.c:41
@ XYELLOW
Definition init.c:55
@ FG_XCLR
Definition init.c:32
@ MAPP_SPEC
Definition init.c:63
@ XBYELLOW
Definition init.c:48
@ BO_XCLR
Definition init.c:31
@ GM_BLUE
Definition init.c:35
@ XCYAN
Definition init.c:49
@ XBBLACK
Definition init.c:39
@ XBLUE
Definition init.c:44
@ XWHITE
Definition init.c:54
@ GM_GRAY
Definition init.c:36
@ GM_GREEN
Definition init.c:37
@ BG_XCLR
Definition init.c:30
@ HELP_SPEC
Definition init.c:64
@ OUT_SPEC
Definition init.c:29
@ LN_BG_CLR
Definition init.c:33
@ XBWHITE
Definition init.c:47
@ MAPP_DATA_DIR
Definition init.c:62
@ MAPP_USER
Definition init.c:60
@ XBGREEN
Definition init.c:42
@ MAPP_HELP_DIR
Definition init.c:61
@ MAPP_MSRC
Definition init.c:59
@ XBLACK
Definition init.c:43
@ XBMAGENTA
Definition init.c:45
@ XBBLUE
Definition init.c:40
@ IN_SPEC
Definition init.c:28
@ LN_XCLR
Definition init.c:34
@ GM_RED
Definition init.c:38
@ CM_EDITOR
Definition init.c:50
@ XMAGENTA
Definition init.c:52
@ MAPP_HELP
Definition init.c:57
int executor
Definition init.c:81
const char * argp_program_bug_address
Definition init.c:84
bool f_write_config
Definition init.c:67
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1110
void abend(int, char *)
Abnormal program termination.
Definition dwin.c:1331
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:269
double str_to_double(char *)
converts string to double
Definition futil.c:637
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:147
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:298
bool expand_tilde(char *, int)
Replace Leading Tilde With Home Directory.
Definition futil.c:684
bool verify_dir(char *, int)
Verifies that the directory specified by "spec" exists and is accessible with the permissions specifi...
Definition futil.c:841
bool trim_path(char *)
Trims trailing spaces and slashes from directory path in place.
Definition futil.c:713
void opt_prt_str(const char *o, const char *name, const char *value)
Print an option and its value in a formatted manner for integer values.
Definition init.c:876
void dump_config(Init *, char *)
Dump the current configuration to stdout for debugging purposes.
Definition init.c:919
bool derive_file_spec(char *, char *, char *)
Derive full file specification from directory and file name.
Definition init.c:821
void display_version()
Display the version information of the application.
Definition init.c:853
void opt_prt_double(const char *o, const char *name, double value)
Print an option and its value in a formatted manner for double values.
Definition init.c:898
void opt_prt_char(const char *o, const char *name, const char *value)
Print an option and its value in a formatted manner.
Definition init.c:865
int write_config(Init *)
Write the current configuration to a file specified in init->minitrc.
Definition init.c:723
void opt_prt_bool(const char *o, const char *name, bool value)
Print an option and its value in a formatted manner for boolean values.
Definition init.c:910
void opt_prt_int(const char *o, const char *name, int value)
Print an option and its value in a formatted manner for integer values.
Definition init.c:887
int parse_config(Init *)
parse the configuration file specified in init->minitrc and set Init struct values accordingly
Definition init.c:438
void mapp_initialization(Init *, int, char **)
Main initialization function for MAPP - Menu Application.
Definition init.c:324
void zero_opt_args(Init *)
Initialize optional arguments in the Init struct to default values.
Definition init.c:408
char title[MAXLEN]
Definition common.h:123
char mapp_data[MAXLEN]
Definition common.h:139
char minitrc[MAXLEN]
Definition common.h:164
bool f_out_spec
Definition common.h:161
char mapp_help[MAXLEN]
Definition common.h:140
int begx
Definition common.h:112
bool f_title
Definition common.h:156
SIO * sio
Definition common.h:108
char in_spec[MAXLEN]
Definition common.h:158
char cmd_all[MAXLEN]
Definition common.h:117
int argc
Definition common.h:124
char fill_char[2]
Definition common.h:137
char mapp_msrc[MAXLEN]
Definition common.h:141
int cols
Definition common.h:110
int tab_stop
Definition common.h:171
bool f_erase_remainder
Definition common.h:134
bool f_mapp_desc
Definition common.h:151
char mapp_home[MAXLEN]
Definition common.h:138
bool f_squeeze
Definition common.h:130
int begy
Definition common.h:111
char parent_cmd[MAXLEN]
Definition common.h:118
char mapp_spec[MAXLEN]
Definition common.h:166
char receiver_cmd[MAXLEN]
Definition common.h:115
bool f_multiple_cmd_args
Definition common.h:132
int select_max
Definition common.h:169
bool f_ln
Definition common.h:135
bool f_mapp_spec
Definition common.h:146
char provider_cmd[MAXLEN]
Definition common.h:114
char out_spec[MAXLEN]
Definition common.h:159
bool f_strip_ansi
Definition common.h:129
bool f_at_end_remove
Definition common.h:128
char brackets[3]
Definition common.h:136
bool f_ignore_case
Definition common.h:127
char ** argv
Definition common.h:125
int lines
Definition common.h:109
char mapp_user[MAXLEN]
Definition common.h:142
char cmd[MAXLEN]
Definition common.h:116
bool f_help_spec
Definition common.h:157
bool f_receiver_cmd
Definition common.h:153
bool f_provider_cmd
Definition common.h:152
char help_spec[MAXLEN]
Definition common.h:167
char editor[MAXLEN]
Definition common.h:162
bool f_in_spec
Definition common.h:160
double green_gamma
Definition cm.h:628
char black[COLOR_LEN]
Definition cm.h:631
char bg_clr_x[COLOR_LEN]
Definition cm.h:652
char fg_clr_x[COLOR_LEN]
Definition cm.h:651
double blue_gamma
Definition cm.h:629
char bred[COLOR_LEN]
Definition cm.h:641
char yellow[COLOR_LEN]
Definition cm.h:634
char bo_clr_x[COLOR_LEN]
Definition cm.h:653
char bcyan[COLOR_LEN]
Definition cm.h:646
char borange[COLOR_LEN]
Definition cm.h:648
double red_gamma
Definition cm.h:627
char red[COLOR_LEN]
Definition cm.h:632
char magenta[COLOR_LEN]
Definition cm.h:636
char bgreen[COLOR_LEN]
Definition cm.h:642
char ln_clr_x[COLOR_LEN]
Definition cm.h:654
char byellow[COLOR_LEN]
Definition cm.h:643
char bwhite[COLOR_LEN]
Definition cm.h:647
char ln_bg_clr_x[COLOR_LEN]
Definition cm.h:655
char cyan[COLOR_LEN]
Definition cm.h:637
char orange[COLOR_LEN]
Definition cm.h:639
char green[COLOR_LEN]
Definition cm.h:633
char white[COLOR_LEN]
Definition cm.h:638
char bg[COLOR_LEN]
Definition cm.h:649
char bblue[COLOR_LEN]
Definition cm.h:644
char bmagenta[COLOR_LEN]
Definition cm.h:645
char blue[COLOR_LEN]
Definition cm.h:635
double gray_gamma
Definition cm.h:630
char bblack[COLOR_LEN]
Definition cm.h:640