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#define _GNU_SOURCE
21#include <argp.h>
22#include <common.h>
23#include <locale.h>
24#include <stddef.h>
25#include <stdlib.h>
26#include <string.h>
27#include <time.h>
28#include <unistd.h>
29#include <wchar.h>
30
31typedef enum {
32 BG = 257,
86} InitVariables;
87
88bool f_write_config = false;
89int write_config(Init *init);
90void display_version();
91
92// Init *init = nullptr;
93void mapp_initialization(Init *, int, char **);
94void zero_opt_args(Init *);
95int process_config_files(Init *);
96int process_config_file(char *, Init *);
97int parse_opt_args(Init *, int, char **);
98void opt_prt_char(const char *o, const char *name, const char *value);
99void opt_prt_str(const char *o, const char *name, const char *value);
100void opt_prt_int(const char *o, const char *name, int value);
101void opt_prt_double(const char *o, const char *name, double value);
102void opt_prt_bool(const char *o, const char *name, bool value);
103
104bool derive_file_spec(char *, char *, char *);
105void print_argp_doc(FILE *, char *, char *);
106int executor = 0;
107
109const char *argp_program_bug_address = "billxwaller@gmail.com";
110static char doc[] = "C-Menu - User Interface Toolkit";
111static char args_doc[] = "[INPUT] [OUTPUT] [HELP] [ARG4] [ARG5]";
112// const int opt_doc_col = 33;
113
114static struct argp_option options[] = {
115 {"f_write_config", 'W', 0, OPTION_ARG_OPTIONAL, "write configuration", 0},
116 {"minitrc", 'a', "file_spec", 0, "configuration file spec", 1},
117 {"parent_cmd", 'k', 0, 0, "parent command", 1},
118 {"begx", 'X', "number", 0, "begin on column", 2},
119 {"begy", 'Y', "number", 0, "begin on line", 2},
120 {"cols", 'C', "number", 0, "width in columns", 2},
121 {"lines", 'L', "number", 0, "height in lines", 2},
122 {"title", 'T', "text", 0, "Window title", 2},
123 {"out_spec", 'o', "file_spec", 0, "output file spec", 3},
124 {"cmd", 'c', "file_spec", 0, "view cmd, first file", 3},
125 {"cmd_all", 'A', "file_spec", 0, "view cmd, all files", 3},
126 {"help_spec", 'H', "file_spec", 0, "help file spec", 3},
127 {"in_spec", 'i', "file_spec", 0, "input file spec", 3},
128 {"mapp_spec", 'd', "file_spec", 0, "description file spec", 3},
129 {"provider_cmd", 'S', "file_spec", 0, "execute provider of piped input", 3},
130 {"receiver_cmd", 'R', "file_spec", 0, "execute receiver of piped output", 3},
131 {"wait_timeout", 'w', "seconds", 0, "Wait timer", 5},
132 {"select_max", 'n', "number", 0, "number of selections", 5},
133 {"f_erase_remainder", 'e', "bool", OPTION_ARG_OPTIONAL, "erase remainder of line on enter", 5},
134 {"f_strip_ansi", 'j', "bool", OPTION_ARG_OPTIONAL, "always strip ansi when writing", 5},
135 {"f_multiple_cmd_args", 'M', "bool", OPTION_ARG_OPTIONAL, "allow multiple command arguments", 5},
136 {"f_read_theme", 'r', "bool", OPTION_ARG_OPTIONAL, "read and process theme file", 5},
137 {"f_squeeze", 's', "bool", OPTION_ARG_OPTIONAL, "squeeze multiple blank lines", 5},
138 {"f_ignore_case", 'x', "bool", OPTION_ARG_OPTIONAL, "ignore case in search", 5},
139 {"p_view_files", 'v', "bool", OPTION_ARG_OPTIONAL, "File View in Pick", 5},
140 {"f_ln", 'N', "bool", OPTION_ARG_OPTIONAL, "line numbers in view", 5},
141 {"fill_char", 'f', "char", 0, "field fill_char (_,.,empty)", 5},
142 {"brackets", 'u', "text", 0, "brackets around fields ([]{}<>)", 5},
143 {"editor", CM_EDITOR, "text", 0, "default editor", 5},
144 {"tab_stop", 't', "number", 0, "number of spaces per tab (4)", 5},
145 {"h_shift", 'z', "number", 0, "horizontal shift width (16)", 5},
146 {"bg", BG, "hex_clr", 0, "Terminal (stdscr) background (#000000)", 6},
147 {"fg", FG, "hex_clr", 0, "Terminal (stdscr) foreground (#d0d0d0)", 6},
148 {"box_fg", BOX_FG, "hex_clr", 0, "box foreground (#d0d0d0)", 6},
149 {"box_bg", BOX_BG, "hex_clr", 0, "box background (#000000)", 6},
150 {"ind_fg", IND_FG, "hex_clr", 0, "indicator foreground (#d0d0d0)", 6},
151 {"ind_bg", IND_BG, "hex_clr", 0, "indicator background (#000000)", 6},
152 {"brackets_fg", BRACKETS_FG, "hex_clr", 0, "brackets foreground (#d0d0d0)", 6},
153 {"brackets_bg", BRACKETS_BG, "hex_clr", 0, "brackets background (#000000)", 6},
154 {"fill_char_fg", FILL_CHAR_FG, "hex_clr", 0, "fill character foreground (#d0d0d0)", 6},
155 {"fill_char_bg", FILL_CHAR_BG, "hex_clr", 0, "fill character background (#000000)", 6},
156 {"nt_fg", NT_FG, "hex_clr", 0, "normal foreground (#d0d0d0)", 6},
157 {"nt_bg", NT_BG, "hex_clr", 0, "normal background (#000000)", 6},
158 {"nt_rev_fg", NT_REV_FG, "hex_clr", 0, "normal reverse foreground (#000000)", 6},
159 {"nt_rev_bg", NT_REV_BG, "hex_clr", 0, "normal reverse background (#d0d0d0)", 6},
160 {"nt_hl_fg", NT_HL_FG, "hex_clr", 0, "normal highlight foreground (#ffffff)", 6},
161 {"nt_hl_bg", NT_HL_BG, "hex_clr", 0, "normal highlight background (#000000)", 6},
162 {"nt_hl_rev_fg", NT_HL_REV_FG, "hex_clr", 0, "normal highlight reverse foreground (#f00000)", 6},
163 {"nt_hl_rev_bg", NT_HL_REV_BG, "hex_clr", 0, "normal highlight reverse background (#d0d0d0)", 6},
164
165 {"ln_fg", LN_FG, "hex_clr", 0, "line number foreground (#0000b0)", 6},
166 {"ln_bg", LN_BG, "hex_clr", 0, "line number background (#202020)", 6},
167 {"cmdln_fg", CMDLN_FG, "hex_clr", 0, "line number foreground (#0000b0)", 6},
168 {"cmdln_bg", CMDLN_BG, "hex_clr", 0, "line number background (#202020)", 6},
169 {"title_fg", TITLE_FG, "hex_clr", 0, "title foreground (#d0d0d0)", 6},
170 {"title_bg", TITLE_BG, "hex_clr", 0, "title background (#000000)", 6},
171 {"blue_gamma", GM_BLUE, "float", 0, "blue_gamma (1.2)", 7},
172 {"gray_gamma", GM_GRAY, "float", 0, "gray gamma (1.2)", 7},
173 {"green_gamma", GM_GREEN, "float", 0, "green gamma (1.2)", 7},
174 {"red_gamma", GM_RED, "float", 0, "red gamma (View)", 7},
175 {"black", XBLACK, "hex_clr", 0, "black (#000000)", 8},
176 {"red", XRED, "hex_clr", 0, "red (#bf0000)", 8},
177 {"green", XGREEN, "hex_clr", 0, "green (#00cf00)", 8},
178 {"yellow", XYELLOW, "hex_clr", 0, "yellow (#efbf00)", 8},
179 {"blue", XBLUE, "hex_clr", 0, "blue (#0000FF)", 8},
180 {"magenta", XMAGENTA, "hex_clr", 0, "magenta (#9f009f)", 8},
181 {"cyan", XCYAN, "hex_clr", 0, "cyan (#00dfdf)", 8},
182 {"white", XWHITE, "hex_clr", 0, "white (#d0d0d0)", 8},
183 {"bblack", XBBLACK, "hex_clr", 0, "bright black (#7f7f7f)", 8},
184 {"bred", XBRED, "hex_clr", 0, "bright red (#FF3737)", 8},
185 {"bgreen", XBGREEN, "hex_clr", 0, "bright green (#00FF7f)", 8},
186 {"byellow", XBYELLOW, "hex_clr", 0, "bright yellow (#FFeF00)", 8},
187 {"bblue", XBBLUE, "hex_clr", 0, "bright blue (#00cfFF)", 8},
188 {"bmagenta", XMAGENTA, "hex_clr", 0, "bright magenta (#FF00FF)", 8},
189 {"bcyan", XBCYAN, "hex_clr", 0, "bright cyan (#00FFFF)", 8},
190 {"bwhite", XBWHITE, "hex_clr", 0, "bright white (#FFFFFF)", 8},
191 {"mapp_data", MAPP_DATA, "directory", 0, "data directory", 9},
192 {"mapp_help", MAPP_HELP, "directory", 0, "help directory", 9},
193 {"mapp_home", MAPP_HOME, "directory", 0, "home directory", 9},
194 {"mapp_msrc", MAPP_MSRC, "directory", 0, "source directory", 9},
195 {"mapp_user", MAPP_USER, "directory", 0, "user directory", 9},
196 {"mapp_theme", MAPP_THEME, "file", 0, "default theme file", 9},
197 {0},
198};
199
200static error_t
201parse_opt(int key, char *arg, struct argp_state *state) {
202 Init *init = state->input;
203 SIO *sio = init->sio;
204 switch (key) {
205 case 'W':
206 f_write_config = true;
207 break;
208 case 'a':
210 break;
211 case 'k':
213 break;
214 case 'C':
215 init->cols = atoi(arg);
216 break;
217 case 'L':
218 init->lines = atoi(arg);
219 break;
220 case 'T':
221 strnz__cpy(init->title, arg, MAXLEN - 1);
222 break;
223 case 'X':
224 init->begx = atoi(arg);
225 break;
226 case 'Y':
227 init->begy = atoi(arg);
228 break;
229 case 'A':
231 break;
232 case 'c':
233 strnz__cpy(init->cmd, arg, MAXLEN - 1);
234 break;
235 case 'd':
237 break;
238 case 'H':
240 break;
241 case 'i':
243 break;
244 case 'o':
246 break;
247 case 'R':
249 break;
250 case 'S':
252 break;
253 case 'e':
254 init->f_erase_remainder = true;
255 break;
256 case 'f':
258 break;
259 case 'j':
260 init->f_strip_ansi = true;
261 break;
262 case 'M':
263 init->f_multiple_cmd_args = true;
264 break;
265 case 'n':
266 init->select_max = atoi(arg);
267 break;
268 case 'N':
269 init->f_ln = true;
270 if (arg)
271 init->f_ln = str_to_bool(arg);
272 break;
273 case 'r':
274 init->f_read_theme = true;
275 break;
276 case 's':
277 init->f_squeeze = true;
278 break;
279 case 't':
280 init->tab_stop = atoi(arg);
281 if (init->tab_stop < 1)
282 init->tab_stop = 1;
283 break;
284 case 'z':
285 init->h_shift = atoi(arg);
286 if (init->h_shift < 1)
287 init->h_shift = 1;
288 break;
289 case 'u':
290 strnz__cpy(init->brackets, arg, 2);
291 break;
292 case 'w':
293 wait_timeout = atoi(arg);
296 break;
297 case 'v':
298 init->p_view_files = true;
299 if (arg)
301 break;
302 case BG:
303 strnz__cpy(sio->bg, arg, MAXLEN - 1);
304 break;
305 case FG:
306 strnz__cpy(sio->fg, arg, MAXLEN - 1);
307 break;
308 case BOX_FG:
310 break;
311 case BOX_BG:
313 break;
314 case IND_FG:
316 break;
317 case IND_BG:
319 break;
320 case BRACKETS_FG:
322 break;
323 case BRACKETS_BG:
325 break;
326 case FILL_CHAR_FG:
328 break;
329 case FILL_CHAR_BG:
331 break;
332 case NT_FG:
333 strnz__cpy(sio->nt_fg, arg, MAXLEN - 1);
334 break;
335 case NT_BG:
336 strnz__cpy(sio->nt_bg, arg, MAXLEN - 1);
337 break;
338 case NT_REV_FG:
340 break;
341 case NT_REV_BG:
343 break;
344 case NT_HL_FG:
346 break;
347 case NT_HL_BG:
349 break;
350 case NT_HL_REV_FG:
352 break;
353 case NT_HL_REV_BG:
355 break;
356 case TITLE_FG:
358 break;
359 case TITLE_BG:
361 break;
362 case LN_FG:
363 strnz__cpy(sio->ln_fg, arg, MAXLEN - 1);
364 break;
365 case LN_BG:
366 strnz__cpy(sio->ln_bg, arg, MAXLEN - 1);
367 break;
368 case CMDLN_FG:
370 break;
371 case CMDLN_BG:
373 break;
374 case GM_BLUE:
376 break;
377 case GM_GRAY:
379 break;
380 case GM_GREEN:
382 break;
383 case GM_RED:
385 break;
386 case MAPP_USER:
388 break;
389 case MAPP_DATA:
391 break;
392 case MAPP_HELP:
394 break;
395 case MAPP_HOME:
397 break;
398 case MAPP_MSRC:
400 break;
401 case MAPP_SPEC:
403 break;
404 case HELP_SPEC:
406 break;
407 case MAPP_THEME:
409 break;
410 case ARGP_KEY_ARG:
411 if (state->arg_num >= 35)
412 argp_usage(state);
413 init->argv[state->arg_num] = strdup(arg);
414 break;
415 case ARGP_KEY_END:
416 init->argc = state->arg_num;
417 init->argv[state->arg_num + 1] = nullptr;
418 break;
419 default:
420 return ARGP_ERR_UNKNOWN;
421 }
422 return 0;
423}
424
425static struct argp argp = {options, parse_opt, args_doc, doc,
426 nullptr, nullptr, nullptr};
427
428/** @brief Main initialization function for MAPP - Menu Application
429 @ingroup init
430 @param init - pointer to Init struct to be initialized
431 @param argc - argument count from main()
432 @param argv - argument vector from main()
433 @code
434 1. Read environment variables and set defaults
435 2. Parse configuration file
436 3. Parse command-line options
437 4. Set up SIO struct with colors and other settings
438 5. Handle special options like help and version
439 @endcode
440 */
441void mapp_initialization(Init *init, int argc, char **argv) {
442 char term[MAXLEN];
443 char tmp_str[MAXLEN];
444 char *e;
445 setlocale(LC_ALL, "en_US.UTF-8");
446 SIO *sio = init->sio;
447 if (!init) {
448 ssnprintf(tmp_str, sizeof(tmp_str), "%s",
449 "init struct not allocated on entry");
450 abend(-1, tmp_str);
451 exit(-1);
452 }
453#ifdef DEBUG_LOG
454 open_cmenu_log();
455#endif
456 e = getenv("CMENU_HOME");
457 if (!e || *e == '\0')
458 strnz__cpy(init->mapp_home, "~/menuapp", MAXLEN);
459 else
461
462 if (init->mapp_home[0] != '\0') {
464 if (!verify_dir(init->mapp_home, R_OK))
465 abend(-1, "MAPP_HOME directory invalid");
466 }
467 // CMENU_RC should be an absolute path
468 e = getenv("CMENU_RC");
469 if (!e || *e == '\0') {
471 strnz__cat(init->minitrc, "/.minitrc", MAXLEN);
472 } else
474 if (init->mapp_user[0] == '\0') {
476 strnz__cat(init->mapp_user, "/user", MAXLEN - 1);
477 }
478 if (init->mapp_theme[0] == '\0') {
480 strnz__cat(init->mapp_theme, "/themes/default", MAXLEN - 1);
481 }
482 if (init->mapp_msrc[0] == '\0') {
484 strnz__cat(init->mapp_msrc, "/msrc", MAXLEN - 1);
485 }
486 if (init->mapp_data[0] == '\0') {
488 strnz__cat(init->mapp_data, "/data", MAXLEN - 1);
489 }
490 if (init->mapp_help[0] == '\0') {
492 strnz__cat(init->mapp_help, "/help", MAXLEN - 1);
493 }
494 init->mapp_spec[0] = '\0'; /**< menu specification file */
495 // Set default colors and settings in SIO struct
496 // These can be overridden by the config file or command-line options
497 // Included here to ensure SIO has valid defaults even if config parsing fails
498 strnz__cpy(sio->bg, "#000000",
499 COLOR_LEN - 1); /**< background color */
500 strnz__cpy(sio->fg, "#c0c0c0",
501 COLOR_LEN - 1); /**< foreground color */
502 strnz__cpy(sio->box_fg, "#f00000", COLOR_LEN - 1); /**< bold color */
503 strnz__cpy(sio->box_bg, "#000000", COLOR_LEN - 1); /**< bold color */
504 strnz__cpy(sio->ind_fg, "#f00000", COLOR_LEN - 1); /**< bold color */
505 strnz__cpy(sio->ind_bg, "#000000", COLOR_LEN - 1); /**< bold color */
506 strnz__cpy(sio->title_fg, "#f0f0f0", COLOR_LEN - 1); /**< title foreground color */
507 strnz__cpy(sio->title_bg, "#000000", COLOR_LEN - 1); /**< title background color */
508 strnz__cpy(sio->nt_fg, "#c0c0c0", COLOR_LEN - 1); /**< normal foreground color */
509 strnz__cpy(sio->nt_bg, "#000000", COLOR_LEN - 1); /**< normal background color */
510 strnz__cpy(sio->nt_rev_fg, "#000000", COLOR_LEN - 1); /**< normal reverse foreground color */
511 strnz__cpy(sio->nt_rev_bg, "#c0c0c0", COLOR_LEN - 1); /**< normal reverse background color */
512 strnz__cpy(sio->nt_hl_fg, "#f00000", COLOR_LEN - 1); /**< normal highlight foreground color */
513 strnz__cpy(sio->nt_hl_bg, "#000000", COLOR_LEN - 1); /**< normal highlight background color */
514 strnz__cpy(sio->nt_hl_rev_fg, "#000000", COLOR_LEN - 1); /**< normal reverse foreground color */
515 strnz__cpy(sio->nt_hl_rev_bg, "#c0c0c0", COLOR_LEN - 1); /**< normal reverse background color */
516 strnz__cpy(sio->ln_fg, "#0070ff",
517 COLOR_LEN - 1); /**< line number olor */
518 strnz__cpy(sio->ln_bg, "#101010",
519 COLOR_LEN - 1); /**< line number background */
520
521 strnz__cpy(sio->cmdln_fg, "#d0d0d0",
522 COLOR_LEN - 1); /**< line number olor */
523 strnz__cpy(sio->cmdln_bg, "#000000",
524 COLOR_LEN - 1); /**< line number background */
525
526 init->f_erase_remainder = true; /**< erase remainder on enter */
527 init->brackets[0] = '\0'; /**< field enclosure brackets */
528 strnz__cpy(init->fill_char, " ", MAXLEN - 1); /**< field fill character */
529 e = getenv("TERM");
530 if (e == nullptr || *e == '\0')
531 strnz__cpy(term, "xterm-256color", MAXLEN);
532 else
533 strnz__cpy(term, e, MAXLEN - 1);
534 e = getenv("EDITOR");
535 if (e && *e != '\0')
536 strnz__cpy(init->editor, "vi", MAXLEN - 1);
537 else
540 init->mapp_spec[0] = '\0';
541 init->argc = argc;
542 argp_parse(&argp, argc, argv, 0, 0, init);
543 if (f_write_config) {
544 write_config(init);
545 exit(EXIT_SUCCESS);
546 }
547}
548/** @brief Parse command-line options and set Init struct values accordingly
549 @ingroup init
550 @param init - pointer to Init struct to be populated with option values
551 @param argc - argument count from main()
552 @param argv - argument vector from main()
553 @returns 0 on success, -1 on failure
554 @details This function uses the argp library to parse command-line
555 options defined in the options array. It updates the Init struct with
556 values from the options and handles any special flags for dumping or
557 writing configuration.
558 */
559int parse_opt_args(Init *init, int argc, char **argv) {
560 init->argc = destroy_argv(init->argc, init->argv);
561 argp_parse(&argp, argc, argv, 0, 0, init);
562 return 0;
563}
564
565/** @brief Initialize optional arguments in the Init struct to default
566 values
567 @ingroup init
568 @param init - pointer to Init struct to be initialized This function
569 sets all optional argument fields in the Init struct to their default
570 values before parsing command-line options or configuration file. This
571 ensures that any fields not specified by the user will have known default
572 values.
573 */
574void zero_opt_args(Init *init) {
575 init->lines = 0;
576 init->cols = 0;
577 init->begx = 0;
578 init->begy = 0;
579 init->f_mapp_desc = false;
580 init->f_provider_cmd = false;
581 init->f_receiver_cmd = false;
582 init->f_title = false;
583 init->f_mapp_spec = false;
584 init->f_help_spec = false;
585 init->f_in_spec = false;
586 init->f_out_spec = false;
587 init->p_view_files = false;
588 init->h_shift = 0;
589 init->mapp_spec[0] = init->help_spec[0] = '\0';
590 init->provider_cmd[0] = init->receiver_cmd[0] = '\0';
591 init->title[0] = '\0';
592 init->cmd[0] = init->cmd_all[0] = '\0';
593 init->parent_cmd[0] = '\0';
594 init->in_spec[0] = init->out_spec[0] = '\0';
595 init->help_spec[0] = '\0';
596 init->in_spec[0] = '\0';
597 init->out_spec[0] = '\0';
598}
599/** @brief parse the configuration file specified in init->minitrc and set
600 Init struct values accordingly
601 @ingroup init
602 @returns on success, -1 on failure
603 @details Lines beginning with '#" are comments, discard.
604 Copy line to tmp_str removing quotes, spaces, semicolons, and
605 newlines.
606 Record structure is "parse key=value pairs".
607 Skip lines without '='.
608 Set init struct values based on key.
609 Skip unknown keys. */
610int process_config_files(Init *init) {
611 char config_file_name[MAXLEN];
612 int rc;
613 if (!init->minitrc[0]) {
614 char *e = getenv("MINITRC");
615 if (e)
617 else
618 strnz__cpy(init->minitrc, "~/.minitrc", MAXLEN - 1);
619 }
620
622 strnz__cpy(config_file_name, init->minitrc, MAXLEN - 1);
623 rc = process_config_file(config_file_name, init);
624
626 strnz__cpy(config_file_name, init->mapp_theme, MAXLEN - 1);
627 rc = process_config_file(config_file_name, init);
628 return rc;
629}
630
631int process_config_file(char *config_file_name, Init *init) {
632 char include_file_name[MAXLEN];
633 char tmp_str[MAXLEN];
634 char *src_p, *dp;
635 SIO *sio = init->sio;
636 char hex_clr_str[8];
637 char key[MAXLEN];
638 char value[MAXLEN];
639 FILE *config_fp = fopen(config_file_name, "r");
640 char quote_char = '\0';
641 if (!config_fp) {
642 fprintf(stderr, "failed to read file: %s %s\n", config_file_name, strerror(errno));
643 return (-1);
644 }
645 while (fgets(tmp_str, sizeof(tmp_str), config_fp)) {
646 bool inquotes = false;
647 if (tmp_str[0] == '#')
648 continue;
649 src_p = tmp_str;
650 key[0] = '\0';
651 dp = key;
652 // copy delimited by "=" into value
653 while (*src_p != '\0') {
654 if (*src_p == '\n')
655 *dp = *src_p = '\0';
656 if (*src_p == '=') {
657 *dp = '\0';
658 src_p++;
659 break;
660 }
661 if (*src_p == '"' && *src_p == ' ') {
662 src_p++;
663 continue;
664 }
665 *dp++ = *src_p++;
666 }
667 value[0] = '\0';
668 dp = value;
669 // copy delimited by newline or unquoted "#" into value, removing quotes, spaces, semicolons, and newlines, but respecting quotes
670 while (*src_p != '\0') {
671 if ((*src_p == '"' || *src_p == '\'') && (*(src_p + 1) != '\\')) {
672 if (!inquotes) {
673 inquotes = true;
674 quote_char = *src_p++;
675 } else if (*src_p == quote_char) {
676 inquotes = false;
677 quote_char = '\0';
678 }
679 }
680 if (!inquotes) {
681 if (*src_p == '#') {
682 if (unstr_hex_clr(hex_clr_str, src_p)) {
683 strnz__cpy(value, hex_clr_str, MAXLEN - 1);
684 dp = value + strlen(value);
685 }
686 break;
687 }
688 }
689 if (*src_p == ' ' || *src_p == ';') {
690 src_p++;
691 continue;
692 }
693 if (*src_p == '\n') {
694 *src_p = '\0';
695 break;
696 }
697 *dp++ = *src_p++;
698 }
699 *dp = '\0';
700 if (key[0] == '\0')
701 continue;
702 if (value[0] == '\0')
703 continue;
704 if (!strcmp(key, "include")) {
705 strnz__cpy(include_file_name, value, MAXLEN - 1);
706 expand_tilde(include_file_name, MAXLEN - 1);
707 process_config_file(include_file_name, init);
708 continue;
709 }
710 if (!strcmp(key, "minitrc")) {
711 strnz__cpy(init->minitrc, value, MAXLEN - 1);
712 continue;
713 }
714 if (!strcmp(key, "lines")) {
715 init->lines = atoi(value);
716 continue;
717 }
718 if (!strcmp(key, "cols")) {
719 init->cols = atoi(value);
720 continue;
721 }
722 if (!strcmp(key, "begy")) {
723 init->begy = atoi(value);
724 continue;
725 }
726 if (!strcmp(key, "begx")) {
727 init->begx = atoi(value);
728 continue;
729 }
730 if (!strcmp(key, "f_ln")) {
731 init->f_ln = str_to_bool(value);
732 continue;
733 }
734 if (!strcmp(key, "f_at_end_remove")) {
736 continue;
737 }
738 if (!strcmp(key, "f_erase_remainder")) {
740 continue;
741 }
742 if (!strcmp(key, "brackets")) {
743 strnz__cpy(init->brackets, value, 2);
744 continue;
745 }
746 if (!strcmp(key, "fill_char")) {
747 if (strlen(value) > 1)
748 value[1] = '\0';
749 if (wcwidth((int)value[0]) > 1)
750 value[0] = '?';
751 strnz__cpy(init->fill_char, value, 4);
752 continue;
753 }
754 if (!strcmp(key, "f_ignore_case")) {
756 continue;
757 }
758 if (!strcmp(key, "p_view_files")) {
759 init->p_view_files = str_to_bool(value);
760 continue;
761 }
762 if (!strcmp(key, "f_read_theme")) {
763 init->f_read_theme = str_to_bool(value);
764 continue;
765 }
766 if (!strcmp(key, "f_squeeze")) {
767 init->f_squeeze = str_to_bool(value);
768 continue;
769 }
770 if (!strcmp(key, "f_strip_ansi")) {
771 init->f_strip_ansi = str_to_bool(value);
772 continue;
773 }
774 if (!strcmp(key, "f_multiple_cmd_args")) {
776 continue;
777 }
778 if (!strcmp(key, "select_max")) {
779 init->select_max = atoi(value);
780 continue;
781 }
782 if (!strcmp(key, "tab_stop")) {
783 init->tab_stop = atoi(value);
784 continue;
785 }
786 if (!strcmp(key, "h_shift")) {
787 init->h_shift = atoi(value);
788 continue;
789 }
790 if (!strcmp(key, "wait_timeout")) {
791 wait_timeout = atoi(value);
792 continue;
793 }
794 if (!strcmp(key, "title")) {
795 strnz__cpy(init->title, value, MAXLEN - 1);
796 continue;
797 }
798 if (!strcmp(key, "cmd")) {
799 strnz__cpy(init->cmd, value, MAXLEN - 1);
800 continue;
801 }
802 if (!strcmp(key, "cmd_all")) {
803 strnz__cpy(init->cmd_all, value, MAXLEN - 1);
804 continue;
805 }
806 if (!strcmp(key, "parent_cmd")) {
808 continue;
809 }
810 if (!strcmp(key, "provider_cmd")) {
812 continue;
813 }
814 if (!strcmp(key, "receiver_cmd")) {
816 continue;
817 }
818 if (!strcmp(key, "editor")) {
819 strnz__cpy(init->editor, value, MAXLEN - 1);
820 continue;
821 }
822 if (!strcmp(key, "fg")) {
823 strnz__cpy(sio->fg, value, COLOR_LEN - 1);
824 continue;
825 }
826 if (!strcmp(key, "bg")) {
827 strnz__cpy(sio->bg, value, COLOR_LEN - 1);
828 continue;
829 }
830 if (!strcmp(key, "box_fg")) {
832 continue;
833 }
834 if (!strcmp(key, "box_bg")) {
836 continue;
837 }
838 if (!strcmp(key, "ind_fg")) {
840 continue;
841 }
842 if (!strcmp(key, "ind_bg")) {
844 continue;
845 }
846 if (!strcmp(key, "brackets_fg")) {
848 continue;
849 }
850 if (!strcmp(key, "brackets_bg")) {
852 continue;
853 }
854 if (!strcmp(key, "fill_char_fg")) {
856 continue;
857 }
858 if (!strcmp(key, "fill_char_bg")) {
860 continue;
861 }
862 if (!strcmp(key, "ln_fg")) {
863 strnz__cpy(sio->ln_fg, value, COLOR_LEN - 1);
864 continue;
865 }
866 if (!strcmp(key, "ln_bg")) {
867 strnz__cpy(sio->ln_bg, value, COLOR_LEN - 1);
868 continue;
869 }
870 if (!strcmp(key, "cmdln_fg")) {
871 strnz__cpy(sio->ln_fg, value, COLOR_LEN - 1);
872 continue;
873 }
874 if (!strcmp(key, "cmdln_bg")) {
875 strnz__cpy(sio->ln_bg, value, COLOR_LEN - 1);
876 continue;
877 }
878 if (!strcmp(key, "nt_fg")) {
879 strnz__cpy(sio->nt_fg, value, COLOR_LEN - 1);
880 continue;
881 }
882 if (!strcmp(key, "nt_bg")) {
883 strnz__cpy(sio->nt_bg, value, COLOR_LEN - 1);
884 continue;
885 }
886 if (!strcmp(key, "nt_rev_fg")) {
888 continue;
889 }
890 if (!strcmp(key, "nt_rev_bg")) {
892 continue;
893 }
894 if (!strcmp(key, "nt_hl_fg")) {
896 continue;
897 }
898 if (!strcmp(key, "nt_hl_bg")) {
900 continue;
901 }
902 if (!strcmp(key, "nt_hl_rev_fg")) {
904 continue;
905 }
906 if (!strcmp(key, "nt_hl_rev_bg")) {
908 continue;
909 }
910 if (!strcmp(key, "title_fg")) {
912 continue;
913 }
914 if (!strcmp(key, "title_bg")) {
916 continue;
917 }
918 if (!strcmp(key, "red_gamma")) {
920 continue;
921 }
922 if (!strcmp(key, "green_gamma")) {
924 continue;
925 }
926 if (!strcmp(key, "blue_gamma")) {
928 continue;
929 }
930 if (!strcmp(key, "gray_gamma")) {
932 continue;
933 }
934 if (!strcmp(key, "black")) {
935 strnz__cpy(sio->black, value, COLOR_LEN - 1);
936 continue;
937 }
938 if (!strcmp(key, "red")) {
939 strnz__cpy(sio->red, value, COLOR_LEN - 1);
940 continue;
941 }
942 if (!strcmp(key, "green")) {
943 strnz__cpy(sio->green, value, COLOR_LEN - 1);
944 continue;
945 }
946 if (!strcmp(key, "yellow")) {
948 continue;
949 }
950 if (!strcmp(key, "blue")) {
951 strnz__cpy(sio->blue, value, COLOR_LEN - 1);
952 continue;
953 }
954 if (!strcmp(key, "magenta")) {
956 continue;
957 }
958 if (!strcmp(key, "cyan")) {
959 strnz__cpy(sio->cyan, value, COLOR_LEN - 1);
960 continue;
961 }
962 if (!strcmp(key, "white")) {
963 strnz__cpy(sio->white, value, COLOR_LEN - 1);
964 continue;
965 }
966 if (!strcmp(key, "orange")) {
968 continue;
969 }
970 if (!strcmp(key, "bblack")) {
972 continue;
973 }
974 if (!strcmp(key, "bred")) {
975 strnz__cpy(sio->bred, value, COLOR_LEN - 1);
976 continue;
977 }
978 if (!strcmp(key, "bgreen")) {
980 continue;
981 }
982 if (!strcmp(key, "byellow")) {
984 continue;
985 }
986 if (!strcmp(key, "bblue")) {
987 strnz__cpy(sio->bblue, value, COLOR_LEN - 1);
988 continue;
989 }
990 if (!strcmp(key, "bmagenta")) {
992 continue;
993 }
994 if (!strcmp(key, "bcyan")) {
995 strnz__cpy(sio->bcyan, value, COLOR_LEN - 1);
996 continue;
997 }
998 if (!strcmp(key, "bwhite")) {
1000 continue;
1001 }
1002 if (!strcmp(key, "borange")) {
1004 continue;
1005 }
1006 if (!strcmp(key, "mapp_spec")) {
1007 strnz__cpy(init->mapp_spec, value, MAXLEN - 1);
1008 continue;
1009 }
1010 if (!strcmp(key, "mapp_data")) {
1011 strnz__cpy(init->mapp_data, value, MAXLEN - 1);
1012 continue;
1013 }
1014 if (!strcmp(key, "mapp_help")) {
1015 strnz__cpy(init->mapp_help, value, MAXLEN - 1);
1016 continue;
1017 }
1018 if (!strcmp(key, "mapp_home")) {
1019 strnz__cpy(init->mapp_home, value, MAXLEN - 1);
1020 continue;
1021 }
1022 if (!strcmp(key, "mapp_msrc")) {
1023 strnz__cpy(init->mapp_msrc, value, MAXLEN - 1);
1024 continue;
1025 }
1026 if (!strcmp(key, "mapp_user")) {
1027 strnz__cpy(init->mapp_user, value, MAXLEN - 1);
1028 continue;
1029 }
1030 if (!strcmp(key, "mapp_theme")) {
1031 strnz__cpy(init->mapp_theme, value, MAXLEN - 1);
1032 continue;
1033 }
1034 }
1035 (void)fclose(config_fp);
1036 return 0;
1037}
1038/** @brief Write the current configuration to a file specified in
1039 init->minitrc
1040 @ingroup init
1041 @param init - pointer to Init struct containing current configuration
1042 @returns 0 on success, -1 on failure
1043 @details The configuration is written in key=value format, one per line.
1044 Lines beginning with '#' are comments and are ignored when reading
1045 the config file.
1046 The file is created if it does not exist, and overwritten if it
1047 does exist
1048 */
1049int write_config(Init *init) {
1050 char *e;
1051 char minitrc_dmp[MAXLEN];
1052 char tmp_str[MAXLEN];
1053 SIO *sio = init->sio;
1054 e = getenv("CMENU_HOME");
1055 minitrc_dmp[0] = '\0';
1056 char config_s[MAXLEN];
1057 if (e) {
1058 strnz__cpy(minitrc_dmp, e, MAXLEN - 1);
1059 strnz__cat(minitrc_dmp, "/", MAXLEN - 1);
1060 }
1061 strnz__cat(minitrc_dmp, "minitrc.dmp", MAXLEN - 1);
1062 FILE *minitrc_fp = fopen(minitrc_dmp, "w");
1063 if (minitrc_fp == (FILE *)0) {
1064 fprintf(stderr, "failed to open file: %s\n", minitrc_dmp);
1065 return (-1);
1066 }
1067 (void)fprintf(minitrc_fp, "# %s\n", minitrc_dmp);
1068 char *doc_tbl[50] = {
1069 "# C-Menu example configuration file",
1070 "#",
1071 "# This file is generated by C-Menu when run with the -W option.",
1072 "# Copy this file and edit the copy because this file will be",
1073 "# overwritten each time C-Menu is run with the - W option.",
1074 "#",
1075 "# C-Menu processes key value pairs in reading order from its",
1076 "# main configuraiton file, ~/ menuapp /.minitrc, and any other",
1077 "# configuration files sourced with include statements such as",
1078 "# the following:",
1079 "#",
1080 "# include = ~/menuapp/theme/default",
1081 "#",
1082 "# Assuming your configuration file is in ~/menuapp/theme/Red,",
1083 "# you could create a symbolic link named default that points to",
1084 "# Red, and then include default in your main configuration file.",
1085 "# (Actually ~/menuapp/.minitrc already includes default, so you",
1086 "# would only need to create the theme file and the symbolic link.",
1087 "#",
1088 "# ln -s Red default",
1089 "#",
1090 "# Key value pairs included from configuration files are",
1091 "# processed in reading order as they are included.",
1092 "#",
1093 "# This is significant in the event that a key is included more",
1094 "# than once in the configuration file and / or included files.",
1095 "# Only the last value read for a key will be used by C-Menu.",
1096 "#",
1097 "# If you want to override key values in the C-Menu configuration",
1098 "# file, you can do so by inserting an include statement for a",
1099 "# supplemental configuration file below the keys you want to",
1100 "# override in the C-Menu configuration file. Conversely, if you",
1101 "# want to use a supplemental configuration as the default,",
1102 "# include it first.",
1103 "#",
1104 "# Parsing: Lines beginning with # are comments and are ignored.",
1105 "# Lines containing key=value pairs are parsed and the key and",
1106 "# value are extracted. Lines without an '=' are ignored. Values",
1107 "# are stripped of leading and trailing whitespace and quotes.",
1108 "# Values can be enclosed in single or double quotes to preserve",
1109 "# leading and trailing whitespace. Values can also be specified",
1110 "# as hex color codes such as #ff0000 for red. If a value is",
1111 "# specified as a hex color code, it is parsed and stored as a",
1112 "# hex color code in the configuration. An unquoted '#' that is",
1113 "# not part of a six digit hex color code and after key values",
1114 "# have been extracted is the beginning of a comment.", ""};
1115 for (int i = 0; doc_tbl[i][0] != '\0'; i++)
1116 (void)fprintf(minitrc_fp, "%s\n", doc_tbl[i]);
1117 (void)fprintf(minitrc_fp, "#\n");
1118 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "parent_cmd", init->parent_cmd);
1119 print_argp_doc(minitrc_fp, config_s, "parent_cmd");
1120 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "cols", init->cols);
1121 print_argp_doc(minitrc_fp, config_s, "cols");
1122 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "lines", init->lines);
1123 print_argp_doc(minitrc_fp, config_s, "lines");
1124 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "title", init->title);
1125 print_argp_doc(minitrc_fp, config_s, "title");
1126 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "begx", init->begx);
1127 print_argp_doc(minitrc_fp, config_s, "begx");
1128 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "begy", init->begy);
1129 print_argp_doc(minitrc_fp, config_s, "begy");
1130 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "cmd_all", init->cmd_all);
1131 print_argp_doc(minitrc_fp, config_s, "cmd_all");
1132 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "cmd", init->cmd);
1133 print_argp_doc(minitrc_fp, config_s, "cmd");
1134 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_spec", init->mapp_spec);
1135 print_argp_doc(minitrc_fp, config_s, "mapp_spec");
1136 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "help_spec", init->help_spec);
1137 print_argp_doc(minitrc_fp, config_s, "help_spec");
1138 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "in_spec", init->in_spec);
1139 print_argp_doc(minitrc_fp, config_s, "in_spec");
1140 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "out_spec", init->out_spec);
1141 print_argp_doc(minitrc_fp, config_s, "out_spec");
1142 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "receiver_cmd", init->receiver_cmd);
1143 print_argp_doc(minitrc_fp, config_s, "receiver_cmd");
1144 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "provider_cmd", init->provider_cmd);
1145 print_argp_doc(minitrc_fp, config_s, "provider_cmd");
1146 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_erase_remainder", init->f_erase_remainder ? "true" : "false");
1147 print_argp_doc(minitrc_fp, config_s, "f_erase_remainder");
1148 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "fill_char", init->fill_char);
1149 print_argp_doc(minitrc_fp, config_s, "fill_char");
1150 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_strip_ansi", init->f_strip_ansi ? "true" : "false");
1151 print_argp_doc(minitrc_fp, config_s, "f_strip_ansi");
1152 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_multiple_cmd_args", init->f_multiple_cmd_args ? "true" : "false");
1153 print_argp_doc(minitrc_fp, config_s, "f_multiple_cmd_args");
1154 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "select_max", init->select_max);
1155 print_argp_doc(minitrc_fp, config_s, "select_max");
1156 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_ln", init->f_ln ? "true" : "false");
1157 print_argp_doc(minitrc_fp, config_s, "f_ln");
1158 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_squeeze", init->f_squeeze ? "true" : "false");
1159 print_argp_doc(minitrc_fp, config_s, "f_squeeze");
1160 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "tab_stop", init->tab_stop);
1161 print_argp_doc(minitrc_fp, config_s, "tab_stop");
1162 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "h_shift", init->h_shift);
1163 print_argp_doc(minitrc_fp, config_s, "h_shift");
1164 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "brackets", init->brackets);
1165 print_argp_doc(minitrc_fp, config_s, "brackets");
1166 ssnprintf(config_s, MAXLEN - 1, "%s=%d", "wait_timeout", wait_timeout);
1167 print_argp_doc(minitrc_fp, config_s, "wait_timeout");
1168 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_ignore_case", init->f_ignore_case ? "true" : "false");
1169 print_argp_doc(minitrc_fp, config_s, "f_ignore_case");
1170 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "p_view_files", init->p_view_files ? "true" : "false");
1171 print_argp_doc(minitrc_fp, config_s, "p_view_files");
1172 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "f_read_theme", init->f_read_theme ? "true" : "false");
1173 print_argp_doc(minitrc_fp, config_s, "f_read_theme");
1174 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "editor", init->editor);
1175 print_argp_doc(minitrc_fp, config_s, "editor");
1176 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bg", sio->bg);
1177 print_argp_doc(minitrc_fp, config_s, "bg");
1178 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "fg", sio->fg);
1179 print_argp_doc(minitrc_fp, config_s, "fg");
1180 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "box_fg", sio->box_fg);
1181 print_argp_doc(minitrc_fp, config_s, "box_fg");
1182 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "box_bg", sio->box_bg);
1183 print_argp_doc(minitrc_fp, config_s, "box_bg");
1184 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "ind_fg", sio->ind_fg);
1185 print_argp_doc(minitrc_fp, config_s, "ind_fg");
1186 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "ind_bg", sio->ind_bg);
1187 print_argp_doc(minitrc_fp, config_s, "ind_bg");
1188 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "brackets_fg", sio->brackets_fg);
1189 print_argp_doc(minitrc_fp, config_s, "brackets_fg");
1190 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "brackets_bg", sio->brackets_bg);
1191 print_argp_doc(minitrc_fp, config_s, "brackets_bg");
1192 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "fill_char_fg", sio->fill_char_fg);
1193 print_argp_doc(minitrc_fp, config_s, "fill_char_fg");
1194 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "fill_char_bg", sio->fill_char_bg);
1195 print_argp_doc(minitrc_fp, config_s, "fill_char_bg");
1196
1197 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "ln_bg", sio->ln_bg);
1198 print_argp_doc(minitrc_fp, config_s, "ln_bg");
1199
1200 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "ln_fg", sio->ln_fg);
1201 print_argp_doc(minitrc_fp, config_s, "ln_bg");
1202
1203 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "cmdln_bg", sio->cmdln_bg);
1204 print_argp_doc(minitrc_fp, config_s, "cmdln_bg");
1205 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "cmdln_fg", sio->cmdln_fg);
1206 print_argp_doc(minitrc_fp, config_s, "cmdln_fg");
1207
1208 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_fg", sio->nt_fg);
1209 print_argp_doc(minitrc_fp, config_s, "nt_fg");
1210 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_bg", sio->nt_bg);
1211 print_argp_doc(minitrc_fp, config_s, "nt_bg");
1212 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_hl_fg", sio->nt_hl_fg);
1213 print_argp_doc(minitrc_fp, config_s, "nt_hl_fg");
1214 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_hl_bg", sio->nt_hl_bg);
1215 print_argp_doc(minitrc_fp, config_s, "nt_hl_bg");
1216 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_rev_fg", sio->nt_rev_fg);
1217 print_argp_doc(minitrc_fp, config_s, "nt_rev_fg");
1218 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_rev_bg", sio->nt_rev_bg);
1219 print_argp_doc(minitrc_fp, config_s, "nt_rev_bg");
1220 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_hl_rev_fg", sio->nt_hl_rev_fg);
1221 print_argp_doc(minitrc_fp, config_s, "nt_hl_rev_fg");
1222 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "nt_hl_rev_bg", sio->nt_hl_rev_bg);
1223 print_argp_doc(minitrc_fp, config_s, "nt_hl_rev_bg");
1224 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "title_fg", sio->title_fg);
1225 print_argp_doc(minitrc_fp, config_s, "title_fg");
1226 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "title_bg", sio->title_bg);
1227 print_argp_doc(minitrc_fp, config_s, "title_bg");
1228 ssnprintf(config_s, MAXLEN - 1, "%s=%0.2f", "blue_gamma", sio->blue_gamma);
1229 print_argp_doc(minitrc_fp, config_s, "blue_gamma");
1230 ssnprintf(config_s, MAXLEN - 1, "%s=%0.2f", "gray_gamma", sio->gray_gamma);
1231 print_argp_doc(minitrc_fp, config_s, "gray_gamma");
1232 ssnprintf(config_s, MAXLEN - 1, "%s=%0.2f", "green_gamma", sio->green_gamma);
1233 print_argp_doc(minitrc_fp, config_s, "green_gamma");
1234 ssnprintf(config_s, MAXLEN - 1, "%s=%0.2f", "red_gamma", sio->red_gamma);
1235 print_argp_doc(minitrc_fp, config_s, "red_gamma");
1236 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "black", sio->black);
1237 print_argp_doc(minitrc_fp, config_s, "black");
1238 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "red", sio->red);
1239 print_argp_doc(minitrc_fp, config_s, "red");
1240 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "green", sio->green);
1241 print_argp_doc(minitrc_fp, config_s, "green");
1242 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "yellow", sio->yellow);
1243 print_argp_doc(minitrc_fp, config_s, "yellow");
1244 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "blue", sio->blue);
1245 print_argp_doc(minitrc_fp, config_s, "blue");
1246 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "magenta", sio->magenta);
1247 print_argp_doc(minitrc_fp, config_s, "magenta");
1248 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "cyan", sio->cyan);
1249 print_argp_doc(minitrc_fp, config_s, "cyan");
1250 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "white", sio->white);
1251 print_argp_doc(minitrc_fp, config_s, "white");
1252 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bblack", sio->bblack);
1253 print_argp_doc(minitrc_fp, config_s, "bblack");
1254 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bred", sio->bred);
1255 print_argp_doc(minitrc_fp, config_s, "bred");
1256 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bgreen", sio->bgreen);
1257 print_argp_doc(minitrc_fp, config_s, "bgreen");
1258 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "byellow", sio->byellow);
1259 print_argp_doc(minitrc_fp, config_s, "byellow");
1260 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bblue", sio->bblue);
1261 print_argp_doc(minitrc_fp, config_s, "bblue");
1262 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bmagenta", sio->bmagenta);
1263 print_argp_doc(minitrc_fp, config_s, "bmagenta");
1264 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bcyan", sio->bcyan);
1265 print_argp_doc(minitrc_fp, config_s, "bcyan");
1266 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "bwhite", sio->bwhite);
1267 print_argp_doc(minitrc_fp, config_s, "bwhite");
1268 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_data", init->mapp_data);
1269 print_argp_doc(minitrc_fp, config_s, "mapp_data");
1270 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_help", init->mapp_help);
1271 print_argp_doc(minitrc_fp, config_s, "mapp_help");
1272 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_home", init->mapp_home);
1273 print_argp_doc(minitrc_fp, config_s, "mapp_home");
1274 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_msrc", init->mapp_msrc);
1275 print_argp_doc(minitrc_fp, config_s, "mapp_msrc");
1276 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_user", init->mapp_user);
1277 print_argp_doc(minitrc_fp, config_s, "mapp_user");
1278 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "mapp_theme", init->mapp_theme);
1279 print_argp_doc(minitrc_fp, config_s, "mapp_theme");
1280 ssnprintf(config_s, MAXLEN - 1, "%s=%s", "include", init->mapp_theme);
1281 (void)fprintf(minitrc_fp, "%-34s # default theme file\n", config_s);
1282 strnz__cpy(tmp_str, "Configuration written to file: ", MAXLEN - 1);
1283 strnz__cat(tmp_str, minitrc_dmp, MAXLEN - 1);
1284 Perror(tmp_str);
1285 return 0;
1286}
1287void print_argp_doc(FILE *minitrc_fp, char *config_s, char *key) {
1288 char comment[MAXLEN];
1289 comment[0] = '\0';
1290 if (get_argp_doc_by_name(comment, options, key))
1291 (void)fprintf(minitrc_fp, "%-34s # %s\n", config_s, comment);
1292 else
1293 (void)fprintf(minitrc_fp, "%-34s #\n", config_s);
1294}
1295/** @brief Derive full file specification from directory and file name
1296 @ingroup init
1297 @param file_spec - output full file specification
1298 @param dir - directory path
1299 @param file_name - file name
1300 @returns true if file_spec is derived, false otherwise
1301 @details If dir is nullptr, use MAPP_DIR environment variable or default
1302 directory, ~/menuapp.
1303 file_spec should be a pre-allocated char array of size MAXLEN to
1304 hold the resulting file specification
1305 */
1306bool derive_file_spec(char *file_spec, char *dir, char *file_name) {
1307 char tmp_str[MAXLEN];
1308 char ts2[MAXLEN];
1309 char *e;
1310
1311 if (!file_name || !*file_name) {
1312 *file_spec = '\0';
1313 return false;
1314 }
1315 if (dir) {
1316 strnz__cpy(tmp_str, dir, MAXLEN - 1);
1317 } else {
1318 e = getenv("MAPP_DIR");
1319 if (e) {
1320 strnz__cpy(tmp_str, e, MAXLEN - 1);
1321 } else {
1322 strnz__cpy(tmp_str, "~/menuapp", MAXLEN - 1);
1323 }
1324 }
1325 trim_path(tmp_str);
1326 strnz__cpy(ts2, tmp_str, MAXLEN - 1);
1327 // construct the full file specification
1328 // check that the file exists and is readable
1329 strnz__cpy(file_spec, ts2, MAXLEN - 1);
1330 strnz__cat(file_spec, "/", MAXLEN - 1);
1331 strnz__cat(file_spec, file_name, MAXLEN - 1);
1332 return true;
1333}
1334/** @brief Display the version information of the application
1335 @ingroup init
1336 @details The version information is defined in the mapp_version variable
1337 and is printed to stdout when this function is called. */
1339 fprintf(stdout, "\nC-Menu %s\n", CM_VERSION);
1340 fprintf(stdout, "\nC-Menu %s\n", CM_VERSION);
1341 fprintf(stdout, "C version: %ld\n", __STDC_VERSION__);
1342}
1343/** @brief Print an option and its value in a formatted manner
1344 @ingroup init
1345 @param o - option flag (e.g., "-a:")
1346 @param name - option name (e.g., "--minitrc")
1347 @param value - option value to print
1348 @details This function is used to display the current configuration options
1349 and their values in a readable format. */
1350void opt_prt_char(const char *o, const char *name, const char *value) {
1351 fprintf(stdout, "%3s %-15s: %s\n", o, name, value);
1352}
1353/** @brief Print an option and its value in a formatted manner for integer
1354 values
1355 @ingroup init
1356 @param o - option flag (e.g., "-C:")
1357 @param name - option name (e.g., "--cols")
1358 @param value - integer option value to print
1359 @details This function is used to display the current configuration options
1360 and their integer values in a readable format. */
1361void opt_prt_str(const char *o, const char *name, const char *value) {
1362 fprintf(stdout, "%3s %-15s: %s\n", o, name, value);
1363}
1364/** @brief Print an option and its value in a formatted manner for integer
1365 values
1366 @ingroup init
1367 @param o - option flag (e.g., "-C:")
1368 @param name - option name (e.g., "--cols")
1369 @param value - integer option value to print
1370 @details This function is used to display the current configuration options
1371 and their integer values in a readable format. */
1372void opt_prt_int(const char *o, const char *name, int value) {
1373 fprintf(stdout, "%3s %-15s: %d\n", o, name, value);
1374}
1375/** @brief Print an option and its value in a formatted manner for double
1376 values
1377 @ingroup init
1378 @param o - option flag (e.g., "-r:")
1379 @param name - option name (e.g., "red_gamma")
1380 @param value - double option value to print
1381 @details This function is used to display the current configuration options
1382 and their double values in a readable format. */
1383void opt_prt_double(const char *o, const char *name, double value) {
1384 fprintf(stdout, "%3s %-15s: %0.2f\n", o, name, value);
1385}
1386/** @brief Print an option and its value in a formatted manner for boolean
1387 values
1388 @ingroup init
1389 @param o - option flag (e.g., "-z")
1390 @param name - option name (e.g., "f_squeeze")
1391 @param value - boolean option value to print
1392 @details This function is used to display the current configuration options
1393 and their boolean values in a readable format, printing "true" or "false"
1394 based on the value. */
1395void opt_prt_bool(const char *o, const char *name, bool value) {
1396 fprintf(stdout, "%3s %-15s: %s\n", o, name, value ? "true" : "false");
1397}
int process_config_file(char *, Init *)
Definition init.c:631
int wait_timeout
Definition futil.c:152
#define COLOR_LEN
Definition cm.h:283
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:89
bool str_to_bool(const char *)
Converts String to boolean true or false.
Definition futil.c:941
#define max(a, b)
max macro evaluates two expressions, returning greatest result.
Definition cm.h:82
#define CM_VERSION
Definition version.h:7
#define MAXLEN
Definition curskeys.c:15
const char * argp_program_version
Definition init.c:108
void print_argp_doc(FILE *, char *, char *)
Definition init.c:1287
@ NT_BG
Definition init.c:43
@ XBRED
Definition init.c:63
@ IND_FG
Definition init.c:36
@ MAPP_HOME
Definition init.c:79
@ XGREEN
Definition init.c:68
@ XRED
Definition init.c:70
@ TITLE_FG
Definition init.c:50
@ MAPP_DATA
Definition init.c:77
@ BG
Definition init.c:32
@ NT_REV_BG
Definition init.c:45
@ XBCYAN
Definition init.c:58
@ XYELLOW
Definition init.c:72
@ CMDLN_FG
Definition init.c:54
@ NT_HL_FG
Definition init.c:46
@ MAPP_SPEC
Definition init.c:82
@ XBYELLOW
Definition init.c:65
@ FILL_CHAR_FG
Definition init.c:40
@ LN_FG
Definition init.c:52
@ GM_BLUE
Definition init.c:73
@ XCYAN
Definition init.c:66
@ XBBLACK
Definition init.c:56
@ XBLUE
Definition init.c:61
@ XWHITE
Definition init.c:71
@ BRACKETS_FG
Definition init.c:38
@ BRACKETS_BG
Definition init.c:39
@ GM_GRAY
Definition init.c:74
@ GM_GREEN
Definition init.c:75
@ BOX_FG
Definition init.c:34
@ HELP_SPEC
Definition init.c:83
@ IND_BG
Definition init.c:37
@ NT_REV_FG
Definition init.c:44
@ XBWHITE
Definition init.c:64
@ NT_FG
Definition init.c:42
@ MAPP_THEME
Definition init.c:84
@ MAPP_USER
Definition init.c:81
@ XBGREEN
Definition init.c:59
@ TITLE_BG
Definition init.c:51
@ NT_HL_REV_BG
Definition init.c:49
@ MAPP_MSRC
Definition init.c:80
@ XBLACK
Definition init.c:60
@ NT_HL_BG
Definition init.c:47
@ BOX_BG
Definition init.c:35
@ END_INIT_VARS
Definition init.c:85
@ XBMAGENTA
Definition init.c:62
@ FG
Definition init.c:33
@ XBBLUE
Definition init.c:57
@ FILL_CHAR_BG
Definition init.c:41
@ LN_BG
Definition init.c:53
@ CMDLN_BG
Definition init.c:55
@ GM_RED
Definition init.c:76
@ CM_EDITOR
Definition init.c:67
@ XMAGENTA
Definition init.c:69
@ NT_HL_REV_FG
Definition init.c:48
@ MAPP_HELP
Definition init.c:78
int executor
Definition init.c:106
const char * argp_program_bug_address
Definition init.c:109
bool f_write_config
Definition init.c:88
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1526
void abend(int, char *)
Abnormal program termination.
Definition dwin.c:2018
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:544
int destroy_argv(int argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:494
double str_to_double(char *)
converts string to double
Definition futil.c:929
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:420
bool expand_tilde(char *, int)
Replaces "~/" in string with the user's home directory.
Definition futil.c:970
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:573
bool get_argp_doc_by_name(char *comment, const struct argp_option *, const char *)
Retrieves the documentation string for a given key name from an argp options array.
Definition futil.c:176
bool verify_dir(char *, int)
Verifies that the directory specified by "spec" exists and is accessible with the permissions specifi...
Definition futil.c:1189
bool trim_path(char *)
Trims trailing spaces and slashes from directory path in place.
Definition futil.c:988
bool unstr_hex_clr(char *, char *)
Validates that a string is a hex color code in the format "#RRGGBB".
Definition futil.c:232
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:1361
int parse_opt_args(Init *, int, char **)
Parse command-line options and set Init struct values accordingly.
Definition init.c:559
bool derive_file_spec(char *, char *, char *)
Derive full file specification from directory and file name.
Definition init.c:1306
void display_version()
Display the version information of the application.
Definition init.c:1338
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:1383
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:1350
int write_config(Init *)
Write the current configuration to a file specified in init->minitrc.
Definition init.c:1049
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:1395
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:1372
int process_config_files(Init *)
parse the configuration file specified in init->minitrc and set Init struct values accordingly
Definition init.c:610
void mapp_initialization(Init *, int, char **)
Main initialization function for MAPP - Menu Application.
Definition init.c:441
void zero_opt_args(Init *)
Initialize optional arguments in the Init struct to default values.
Definition init.c:574
char title[MAXLEN]
Definition common.h:129
char mapp_data[MAXLEN]
Definition common.h:147
char minitrc[MAXLEN]
Definition common.h:173
bool f_out_spec
Definition common.h:170
char mapp_help[MAXLEN]
Definition common.h:148
int begx
Definition common.h:118
bool f_title
Definition common.h:165
SIO * sio
Definition common.h:114
char in_spec[MAXLEN]
Definition common.h:167
char cmd_all[MAXLEN]
Definition common.h:123
int argc
Definition common.h:130
char mapp_msrc[MAXLEN]
Definition common.h:149
int cols
Definition common.h:116
int tab_stop
Definition common.h:180
bool f_erase_remainder
Definition common.h:141
bool f_read_theme
Definition common.h:142
bool f_mapp_desc
Definition common.h:160
char mapp_home[MAXLEN]
Definition common.h:146
char fill_char[4]
Definition common.h:145
bool f_squeeze
Definition common.h:137
int begy
Definition common.h:117
char parent_cmd[MAXLEN]
Definition common.h:124
char mapp_spec[MAXLEN]
Definition common.h:175
char receiver_cmd[MAXLEN]
Definition common.h:121
int h_shift
Definition common.h:181
bool f_multiple_cmd_args
Definition common.h:139
int select_max
Definition common.h:178
bool f_ln
Definition common.h:143
bool f_mapp_spec
Definition common.h:155
char provider_cmd[MAXLEN]
Definition common.h:120
char out_spec[MAXLEN]
Definition common.h:168
bool f_strip_ansi
Definition common.h:136
bool p_view_files
Definition common.h:134
bool f_at_end_remove
Definition common.h:135
char brackets[3]
Definition common.h:144
bool f_ignore_case
Definition common.h:133
char ** argv
Definition common.h:131
int lines
Definition common.h:115
char mapp_user[MAXLEN]
Definition common.h:150
char cmd[MAXLEN]
Definition common.h:122
char mapp_theme[MAXLEN]
Definition common.h:151
bool f_help_spec
Definition common.h:166
bool f_receiver_cmd
Definition common.h:162
bool f_provider_cmd
Definition common.h:161
char help_spec[MAXLEN]
Definition common.h:176
char editor[MAXLEN]
Definition common.h:171
bool f_in_spec
Definition common.h:169
char nt_hl_rev_bg[COLOR_LEN]
Definition cm.h:852
double green_gamma
Definition cm.h:807
char nt_rev_bg[COLOR_LEN]
Definition cm.h:846
char ln_fg[COLOR_LEN]
Definition cm.h:839
char black[COLOR_LEN]
Definition cm.h:810
char title_bg[COLOR_LEN]
Definition cm.h:854
double blue_gamma
Definition cm.h:808
char bred[COLOR_LEN]
Definition cm.h:820
char yellow[COLOR_LEN]
Definition cm.h:813
char nt_hl_bg[COLOR_LEN]
Definition cm.h:848
char nt_hl_fg[COLOR_LEN]
Definition cm.h:847
char cmdln_bg[COLOR_LEN]
Definition cm.h:842
char ind_fg[COLOR_LEN]
Definition cm.h:833
char bcyan[COLOR_LEN]
Definition cm.h:825
char borange[COLOR_LEN]
Definition cm.h:827
double red_gamma
Definition cm.h:806
char red[COLOR_LEN]
Definition cm.h:811
char nt_fg[COLOR_LEN]
Definition cm.h:843
char magenta[COLOR_LEN]
Definition cm.h:815
char ln_bg[COLOR_LEN]
Definition cm.h:840
char bgreen[COLOR_LEN]
Definition cm.h:821
char nt_rev_fg[COLOR_LEN]
Definition cm.h:845
char brackets_fg[COLOR_LEN]
Definition cm.h:835
char fill_char_fg[COLOR_LEN]
Definition cm.h:837
char byellow[COLOR_LEN]
Definition cm.h:822
char bwhite[COLOR_LEN]
Definition cm.h:826
char box_bg[COLOR_LEN]
Definition cm.h:832
char fg[COLOR_LEN]
Definition cm.h:829
char cyan[COLOR_LEN]
Definition cm.h:816
char brackets_bg[COLOR_LEN]
Definition cm.h:836
char box_fg[COLOR_LEN]
Definition cm.h:831
char orange[COLOR_LEN]
Definition cm.h:818
char fill_char_bg[COLOR_LEN]
Definition cm.h:838
char green[COLOR_LEN]
Definition cm.h:812
char white[COLOR_LEN]
Definition cm.h:817
char bg[COLOR_LEN]
Definition cm.h:830
char bblue[COLOR_LEN]
Definition cm.h:823
char title_fg[COLOR_LEN]
Definition cm.h:853
char cmdln_fg[COLOR_LEN]
Definition cm.h:841
char bmagenta[COLOR_LEN]
Definition cm.h:824
char blue[COLOR_LEN]
Definition cm.h:814
char nt_hl_rev_fg[COLOR_LEN]
Definition cm.h:850
double gray_gamma
Definition cm.h:809
char bblack[COLOR_LEN]
Definition cm.h:819
char ind_bg[COLOR_LEN]
Definition cm.h:834
char nt_bg[COLOR_LEN]
Definition cm.h:844