2 * Copyright (c) 2013-2015 Devin Teske <dteske@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
43 #define STR_BUFSIZE 255
45 /* dialog(1) `.dialogrc' characteristics */
46 uint8_t use_colors = 1;
47 uint8_t use_shadow = 1;
48 char gauge_color[STR_BUFSIZE] = "47b"; /* (BLUE,WHITE,ON) */
49 char separator[STR_BUFSIZE] = "";
51 /* Function prototypes */
52 static int setattr(struct figpar_config *, uint32_t, char *, char *);
53 static int setbool(struct figpar_config *, uint32_t, char *, char *);
54 static int setnum(struct figpar_config *, uint32_t, char *, char *);
55 static int setstr(struct figpar_config *, uint32_t, char *, char *);
58 * Anatomy of DIALOGRC (~/.dialogrc by default)
59 * NOTE: Must appear after private function prototypes (above)
60 * NB: Brace-initialization of union requires cast to *first* member of union
62 static struct figpar_config dialogrc_config[] = {
63 /* TYPE DIRECTIVE DEFAULT HANDLER */
64 {FIGPAR_TYPE_INT, "aspect", {(void *)0}, &setnum},
65 {FIGPAR_TYPE_STR, "separate_widget", {separator}, &setstr},
66 {FIGPAR_TYPE_INT, "tab_len", {(void *)0}, &setnum},
67 {FIGPAR_TYPE_BOOL, "visit_items", {(void *)0}, &setbool},
68 {FIGPAR_TYPE_BOOL, "use_shadow", {(void *)1}, &setbool},
69 {FIGPAR_TYPE_BOOL, "use_colors", {(void *)1}, &setbool},
70 {FIGPAR_TYPE_STR, "screen_color", {NULL}, &setattr},
71 {FIGPAR_TYPE_STR, "shadow_color", {NULL}, &setattr},
72 {FIGPAR_TYPE_STR, "dialog_color", {NULL}, &setattr},
73 {FIGPAR_TYPE_STR, "title_color", {NULL}, &setattr},
74 {FIGPAR_TYPE_STR, "border_color", {NULL}, &setattr},
75 {FIGPAR_TYPE_STR, "button_active_color", {NULL}, &setattr},
76 {FIGPAR_TYPE_STR, "button_inactive_color", {NULL}, &setattr},
77 {FIGPAR_TYPE_STR, "button_key_active_color", {NULL}, &setattr},
78 {FIGPAR_TYPE_STR, "button_key_inactive_color", {NULL}, &setattr},
79 {FIGPAR_TYPE_STR, "button_label_active_color", {NULL}, &setattr},
80 {FIGPAR_TYPE_STR, "button_label_inactive_color", {NULL}, &setattr},
81 {FIGPAR_TYPE_STR, "inputbox_color", {NULL}, &setattr},
82 {FIGPAR_TYPE_STR, "inputbox_border_color", {NULL}, &setattr},
83 {FIGPAR_TYPE_STR, "searchbox_color", {NULL}, &setattr},
84 {FIGPAR_TYPE_STR, "searchbox_title_color", {NULL}, &setattr},
85 {FIGPAR_TYPE_STR, "searchbox_border_color", {NULL}, &setattr},
86 {FIGPAR_TYPE_STR, "position_indicator_color", {NULL}, &setattr},
87 {FIGPAR_TYPE_STR, "menubox_color", {NULL}, &setattr},
88 {FIGPAR_TYPE_STR, "menubox_border_color", {NULL}, &setattr},
89 {FIGPAR_TYPE_STR, "item_color", {NULL}, &setattr},
90 {FIGPAR_TYPE_STR, "item_selected_color", {NULL}, &setattr},
91 {FIGPAR_TYPE_STR, "tag_color", {NULL}, &setattr},
92 {FIGPAR_TYPE_STR, "tag_selected_color", {NULL}, &setattr},
93 {FIGPAR_TYPE_STR, "tag_key_color", {NULL}, &setattr},
94 {FIGPAR_TYPE_STR, "tag_key_selected_color", {NULL}, &setattr},
95 {FIGPAR_TYPE_STR, "check_color", {NULL}, &setattr},
96 {FIGPAR_TYPE_STR, "check_selected_color", {NULL}, &setattr},
97 {FIGPAR_TYPE_STR, "uarrow_color", {NULL}, &setattr},
98 {FIGPAR_TYPE_STR, "darrow_color", {NULL}, &setattr},
99 {FIGPAR_TYPE_STR, "itemhelp_color", {NULL}, &setattr},
100 {FIGPAR_TYPE_STR, "form_active_text_color", {NULL}, &setattr},
101 {FIGPAR_TYPE_STR, "form_text_color", {NULL}, &setattr},
102 {FIGPAR_TYPE_STR, "form_item_readonly_color", {NULL}, &setattr},
103 {FIGPAR_TYPE_STR, "gauge_color", {gauge_color}, &setattr},
108 * figpar call-back for interpreting value as .dialogrc `Attribute'
111 setattr(struct figpar_config *option, uint32_t line __unused,
112 char *directive __unused, char *value)
119 if (option == NULL) {
120 warnx("%s:%d:%s: Missing callback parameter", __FILE__,
122 return (-1); /* Abort processing */
125 /* Allocate memory for the data if not already done */
126 if (option->value.str == NULL) {
127 if ((option->value.str = malloc(STR_BUFSIZE)) == NULL)
132 * If the first character is left-parenthesis, the format is
133 * `(background,foreground,highlight)' otherwise, we should take it
134 * as a reference to another color.
137 /* Copy the [current] value from the referenced color */
138 val = dialogrc_config_option(cp)->value.str;
140 snprintf(option->value.str, STR_BUFSIZE, "%s", val);
148 /* Initialize the attrbuf (fg,bg,hi,NUL) */
151 attrbuf[2] = 'B'; /* \ZB = disable; \Zb = enable (see dialog(1)) */
154 /* Interpret the foreground color */
155 if (strncmp(cp, "red,", 4) == 0) attrbuf[0] = '1';
156 else if (strncmp(cp, "green,", 6) == 0) attrbuf[0] = '2';
157 else if (strncmp(cp, "yellow,", 7) == 0) attrbuf[0] = '3';
158 else if (strncmp(cp, "blue,", 5) == 0) attrbuf[0] = '4';
159 else if (strncmp(cp, "magenta,", 8) == 0) attrbuf[0] = '5';
160 else if (strncmp(cp, "cyan,", 5) == 0) attrbuf[0] = '6';
161 else if (strncmp(cp, "white,", 6) == 0) attrbuf[0] = '7';
162 else if (strncmp(cp, "black,", 6) == 0) attrbuf[0] = '8';
164 /* Advance to the background color */
165 cp = strchr(cp, ',');
171 /* Interpret the background color */
172 if (strncmp(cp, "red,", 4) == 0) attrbuf[1] = '1';
173 else if (strncmp(cp, "green,", 6) == 0) attrbuf[1] = '2';
174 else if (strncmp(cp, "yellow,", 7) == 0) attrbuf[1] = '3';
175 else if (strncmp(cp, "blue,", 5) == 0) attrbuf[1] = '4';
176 else if (strncmp(cp, "magenta,", 8) == 0) attrbuf[1] = '5';
177 else if (strncmp(cp, "cyan,", 5) == 0) attrbuf[1] = '6';
178 else if (strncmp(cp, "white,", 6) == 0) attrbuf[1] = '7';
179 else if (strncmp(cp, "black,", 6) == 0) attrbuf[1] = '8';
181 /* Advance to the highlight */
182 cp = strchr(cp, ',');
188 /* Trim trailing parenthesis */
190 if (cp[len - 1] == ')')
193 /* Interpret the highlight (initialized to off above) */
194 if (strcmp(cp, "on") == 0 || strncmp(cp, "on,", 3) == 0)
195 attrbuf[2] = 'b'; /* \Zb = enable bold (see dialog(1)) */
198 sprintf(option->value.str, "%s", attrbuf);
204 * figpar call-back for interpreting value as .dialogrc `Boolean'
207 setbool(struct figpar_config *option, uint32_t line __unused,
208 char *directive __unused, char *value)
211 if (option == NULL) {
212 warnx("%s:%d:%s: Missing callback parameter", __FILE__,
214 return (-1); /* Abort processing */
217 /* Assume ON, check for OFF (case-insensitive) */
218 option->value.boolean = 1;
220 if (strcmp(value, "off") == 0)
221 option->value.boolean = 0;
227 * figpar call-back for interpreting value as .dialogrc `Number'
230 setnum(struct figpar_config *option, uint32_t line __unused,
231 char *directive __unused, char *value)
234 if (option == NULL) {
235 warnx("%s:%d:%s: Missing callback parameter", __FILE__,
237 return (-1); /* Abort processing */
240 /* Convert the string to a 32-bit signed integer */
241 option->value.num = (int32_t)strtol(value, (char **)NULL, 10);
247 * figpar call-back for interpreting value as .dialogrc `String'
250 setstr(struct figpar_config *option, uint32_t line __unused,
251 char *directive __unused, char *value)
255 if (option == NULL) {
256 warnx("%s:%d:%s: Missing callback parameter", __FILE__,
258 return (-1); /* Abort processing */
261 /* Allocate memory for the data if not already done */
262 if (option->value.str == NULL) {
263 if ((option->value.str = malloc(STR_BUFSIZE)) == NULL)
267 /* Trim leading quote */
271 /* Write the data into the buffer */
272 snprintf(option->value.str, STR_BUFSIZE, "%s", value);
274 /* Trim trailing quote */
275 len = strlen(option->value.str);
276 if (option->value.str[len - 1] == '"')
277 option->value.str[len - 1] = '\0';
283 * Parse (in order of preference) $DIALOGRC or `$HOME/.dialogrc'. Returns zero
284 * on success, -1 on failure (and errno should be consulted).
294 /* Allow $DIALOGRC to override `$HOME/.dialogrc' default */
295 if ((cp = getenv(ENV_DIALOGRC)) != NULL && *cp != '\0')
296 snprintf(path, PATH_MAX, "%s", cp);
297 else if ((cp = getenv(ENV_HOME)) != NULL) {
298 /* Copy $HOME into buffer and append trailing `/' if missing */
299 snprintf(path, PATH_MAX, "%s", cp);
302 if (len > 0 && len < (PATH_MAX - 1) && *(cp - 1) != '/') {
308 /* If we still have room, shove in the name of rc file */
309 if (len < (PATH_MAX - 1))
310 snprintf(cp, PATH_MAX - len, "%s", DIALOGRC);
312 /* Like dialog(1), don't process a file if $HOME is unset */
317 /* Process file (either $DIALOGRC if set, or `$HOME/.dialogrc') */
318 res = parse_config(dialogrc_config,
319 path, NULL, FIGPAR_BREAK_ON_EQUALS);
321 /* Set some globals based on what we parsed */
322 use_shadow = dialogrc_config_option("use_shadow")->value.boolean;
323 use_colors = dialogrc_config_option("use_colors")->value.boolean;
324 snprintf(gauge_color, STR_BUFSIZE, "%s",
325 dialogrc_config_option("gauge_color")->value.str);
331 * Return a pointer to the `.dialogrc' config option specific to `directive' or
332 * static figpar_dummy_config (full of NULLs) if none found (see
333 * get_config_option(3); part of figpar(3)).
335 struct figpar_config *
336 dialogrc_config_option(const char *directive)
338 return (get_config_option(dialogrc_config, directive));
342 * Free allocated items initialized by setattr() (via parse_config() callback
343 * matrix [dialogrc_config] used in parse_dialogrc() above).
351 for (n = 0; dialogrc_config[n].directive != NULL; n++) {
352 if (dialogrc_config[n].action != &setattr)
354 value = dialogrc_config[n].value.str;
355 if (value != NULL && value != gauge_color) {
356 free(dialogrc_config[n].value.str);
357 dialogrc_config[n].value.str = NULL;