15382d832SPeter Avalos /*
2*a8e38dc0SAntonio Huete Jimenez * $Id: rc.c,v 1.62 2022/07/28 08:17:21 tom Exp $
35382d832SPeter Avalos *
45382d832SPeter Avalos * rc.c -- routines for processing the configuration file
55382d832SPeter Avalos *
6*a8e38dc0SAntonio Huete Jimenez * Copyright 2000-2020,2022 Thomas E. Dickey
75382d832SPeter Avalos *
85382d832SPeter Avalos * This program is free software; you can redistribute it and/or modify
95382d832SPeter Avalos * it under the terms of the GNU Lesser General Public License, version 2.1
105382d832SPeter Avalos * as published by the Free Software Foundation.
115382d832SPeter Avalos *
125382d832SPeter Avalos * This program is distributed in the hope that it will be useful, but
135382d832SPeter Avalos * WITHOUT ANY WARRANTY; without even the implied warranty of
145382d832SPeter Avalos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
155382d832SPeter Avalos * Lesser General Public License for more details.
165382d832SPeter Avalos *
175382d832SPeter Avalos * You should have received a copy of the GNU Lesser General Public
185382d832SPeter Avalos * License along with this program; if not, write to
195382d832SPeter Avalos * Free Software Foundation, Inc.
205382d832SPeter Avalos * 51 Franklin St., Fifth Floor
215382d832SPeter Avalos * Boston, MA 02110, USA.
225382d832SPeter Avalos *
235382d832SPeter Avalos * An earlier version of this program lists as authors
245382d832SPeter Avalos * Savio Lam (lam836@cs.cuhk.hk)
255382d832SPeter Avalos */
265382d832SPeter Avalos
27*a8e38dc0SAntonio Huete Jimenez #include <dlg_internals.h>
285382d832SPeter Avalos #include <dlg_keys.h>
295382d832SPeter Avalos
305382d832SPeter Avalos #ifdef HAVE_COLOR
315382d832SPeter Avalos #include <dlg_colors.h>
325940c9abSDaniel Fojt
335940c9abSDaniel Fojt #define L_PAREN '('
345940c9abSDaniel Fojt #define R_PAREN ')'
355940c9abSDaniel Fojt
365940c9abSDaniel Fojt #define MIN_TOKEN 3
375940c9abSDaniel Fojt #ifdef HAVE_RC_FILE2
385940c9abSDaniel Fojt #define MAX_TOKEN 5
395940c9abSDaniel Fojt #else
405940c9abSDaniel Fojt #define MAX_TOKEN MIN_TOKEN
415940c9abSDaniel Fojt #endif
425940c9abSDaniel Fojt
435940c9abSDaniel Fojt #define UNKNOWN_COLOR -2
445382d832SPeter Avalos
455382d832SPeter Avalos /*
465382d832SPeter Avalos * For matching color names with color values
475382d832SPeter Avalos */
485382d832SPeter Avalos static const color_names_st color_names[] =
495382d832SPeter Avalos {
505382d832SPeter Avalos #ifdef HAVE_USE_DEFAULT_COLORS
515382d832SPeter Avalos {"DEFAULT", -1},
525382d832SPeter Avalos #endif
535382d832SPeter Avalos {"BLACK", COLOR_BLACK},
545382d832SPeter Avalos {"RED", COLOR_RED},
555382d832SPeter Avalos {"GREEN", COLOR_GREEN},
565382d832SPeter Avalos {"YELLOW", COLOR_YELLOW},
575382d832SPeter Avalos {"BLUE", COLOR_BLUE},
585382d832SPeter Avalos {"MAGENTA", COLOR_MAGENTA},
595382d832SPeter Avalos {"CYAN", COLOR_CYAN},
605382d832SPeter Avalos {"WHITE", COLOR_WHITE},
615382d832SPeter Avalos }; /* color names */
625940c9abSDaniel Fojt #define COLOR_COUNT TableSize(color_names)
635382d832SPeter Avalos #endif /* HAVE_COLOR */
645382d832SPeter Avalos
655382d832SPeter Avalos #define GLOBALRC "/etc/dialogrc"
665382d832SPeter Avalos #define DIALOGRC ".dialogrc"
675382d832SPeter Avalos
685382d832SPeter Avalos /* Types of values */
695382d832SPeter Avalos #define VAL_INT 0
705382d832SPeter Avalos #define VAL_STR 1
715382d832SPeter Avalos #define VAL_BOOL 2
725382d832SPeter Avalos
735382d832SPeter Avalos /* Type of line in configuration file */
745382d832SPeter Avalos typedef enum {
755382d832SPeter Avalos LINE_ERROR = -1,
765382d832SPeter Avalos LINE_EQUALS,
775382d832SPeter Avalos LINE_EMPTY
785382d832SPeter Avalos } PARSE_LINE;
795382d832SPeter Avalos
805382d832SPeter Avalos /* number of configuration variables */
815940c9abSDaniel Fojt #define VAR_COUNT TableSize(vars)
825382d832SPeter Avalos
835382d832SPeter Avalos /* check if character is string quoting characters */
845940c9abSDaniel Fojt #define isquote(c) ((c) == '"' || (c) == '\'')
855382d832SPeter Avalos
865382d832SPeter Avalos /* get last character of string */
875382d832SPeter Avalos #define lastch(str) str[strlen(str)-1]
885382d832SPeter Avalos
895382d832SPeter Avalos /*
905382d832SPeter Avalos * Configuration variables
915382d832SPeter Avalos */
925382d832SPeter Avalos typedef struct {
935382d832SPeter Avalos const char *name; /* name of configuration variable as in DIALOGRC */
945382d832SPeter Avalos void *var; /* address of actual variable to change */
955382d832SPeter Avalos int type; /* type of value */
965382d832SPeter Avalos const char *comment; /* comment to put in "rc" file */
975382d832SPeter Avalos } vars_st;
985382d832SPeter Avalos
995382d832SPeter Avalos /*
1005382d832SPeter Avalos * This table should contain only references to dialog_state, since dialog_vars
1015382d832SPeter Avalos * is reset specially in dialog.c before each widget.
1025382d832SPeter Avalos */
1035382d832SPeter Avalos static const vars_st vars[] =
1045382d832SPeter Avalos {
1055382d832SPeter Avalos {"aspect",
1065382d832SPeter Avalos &dialog_state.aspect_ratio,
1075382d832SPeter Avalos VAL_INT,
1085382d832SPeter Avalos "Set aspect-ration."},
1095382d832SPeter Avalos
1105382d832SPeter Avalos {"separate_widget",
1115382d832SPeter Avalos &dialog_state.separate_str,
1125382d832SPeter Avalos VAL_STR,
1135382d832SPeter Avalos "Set separator (for multiple widgets output)."},
1145382d832SPeter Avalos
1155382d832SPeter Avalos {"tab_len",
1165382d832SPeter Avalos &dialog_state.tab_len,
1175382d832SPeter Avalos VAL_INT,
1185382d832SPeter Avalos "Set tab-length (for textbox tab-conversion)."},
1195382d832SPeter Avalos
1205382d832SPeter Avalos {"visit_items",
1215382d832SPeter Avalos &dialog_state.visit_items,
1225382d832SPeter Avalos VAL_BOOL,
1235382d832SPeter Avalos "Make tab-traversal for checklist, etc., include the list."},
1245382d832SPeter Avalos
125*a8e38dc0SAntonio Huete Jimenez {"use_scrollbar",
126*a8e38dc0SAntonio Huete Jimenez &dialog_state.use_scrollbar,
127*a8e38dc0SAntonio Huete Jimenez VAL_BOOL,
128*a8e38dc0SAntonio Huete Jimenez "Show scrollbar in dialog boxes?"},
129*a8e38dc0SAntonio Huete Jimenez
1305382d832SPeter Avalos #ifdef HAVE_COLOR
1315382d832SPeter Avalos {"use_shadow",
1325382d832SPeter Avalos &dialog_state.use_shadow,
1335382d832SPeter Avalos VAL_BOOL,
1345382d832SPeter Avalos "Shadow dialog boxes? This also turns on color."},
1355382d832SPeter Avalos
1365382d832SPeter Avalos {"use_colors",
1375382d832SPeter Avalos &dialog_state.use_colors,
1385382d832SPeter Avalos VAL_BOOL,
1395382d832SPeter Avalos "Turn color support ON or OFF"},
1405382d832SPeter Avalos #endif /* HAVE_COLOR */
1415382d832SPeter Avalos }; /* vars */
1425382d832SPeter Avalos
1435382d832SPeter Avalos static int
skip_whitespace(char * str,int n)1445382d832SPeter Avalos skip_whitespace(char *str, int n)
1455382d832SPeter Avalos {
1465940c9abSDaniel Fojt while (isblank(UCH(str[n])) && str[n] != '\0')
1475382d832SPeter Avalos n++;
1485382d832SPeter Avalos return n;
1495382d832SPeter Avalos }
1505382d832SPeter Avalos
1515382d832SPeter Avalos static int
skip_keyword(char * str,int n)1525382d832SPeter Avalos skip_keyword(char *str, int n)
1535382d832SPeter Avalos {
1545382d832SPeter Avalos while (isalnum(UCH(str[n])) && str[n] != '\0')
1555382d832SPeter Avalos n++;
1565382d832SPeter Avalos return n;
1575382d832SPeter Avalos }
1585382d832SPeter Avalos
1595940c9abSDaniel Fojt static void
trim_token(char ** tok)1605940c9abSDaniel Fojt trim_token(char **tok)
1615940c9abSDaniel Fojt {
1625940c9abSDaniel Fojt char *tmp = *tok + skip_whitespace(*tok, 0);
1635940c9abSDaniel Fojt
1645940c9abSDaniel Fojt *tok = tmp;
1655940c9abSDaniel Fojt
1665940c9abSDaniel Fojt while (*tmp != '\0' && !isblank(UCH(*tmp)))
1675940c9abSDaniel Fojt tmp++;
1685940c9abSDaniel Fojt
1695940c9abSDaniel Fojt *tmp = '\0';
1705940c9abSDaniel Fojt }
1715940c9abSDaniel Fojt
1725940c9abSDaniel Fojt static int
from_boolean(const char * str)1735940c9abSDaniel Fojt from_boolean(const char *str)
1745940c9abSDaniel Fojt {
1755940c9abSDaniel Fojt int code = -1;
1765940c9abSDaniel Fojt
1775940c9abSDaniel Fojt if (str != NULL && *str != '\0') {
1785940c9abSDaniel Fojt if (!dlg_strcmp(str, "ON")) {
1795940c9abSDaniel Fojt code = 1;
1805940c9abSDaniel Fojt } else if (!dlg_strcmp(str, "OFF")) {
1815940c9abSDaniel Fojt code = 0;
1825940c9abSDaniel Fojt }
1835940c9abSDaniel Fojt }
1845940c9abSDaniel Fojt return code;
1855940c9abSDaniel Fojt }
1865940c9abSDaniel Fojt
1875940c9abSDaniel Fojt static int
from_color_name(const char * str)1885940c9abSDaniel Fojt from_color_name(const char *str)
1895940c9abSDaniel Fojt {
1905940c9abSDaniel Fojt int code = UNKNOWN_COLOR;
1915940c9abSDaniel Fojt
1925940c9abSDaniel Fojt if (str != NULL && *str != '\0') {
1935940c9abSDaniel Fojt size_t i;
1945940c9abSDaniel Fojt
1955940c9abSDaniel Fojt for (i = 0; i < COLOR_COUNT; ++i) {
1965940c9abSDaniel Fojt if (!dlg_strcmp(str, color_names[i].name)) {
1975940c9abSDaniel Fojt code = color_names[i].value;
1985940c9abSDaniel Fojt break;
1995940c9abSDaniel Fojt }
2005940c9abSDaniel Fojt }
2015940c9abSDaniel Fojt }
2025940c9abSDaniel Fojt return code;
2035940c9abSDaniel Fojt }
2045940c9abSDaniel Fojt
2055382d832SPeter Avalos static int
find_vars(char * name)2065382d832SPeter Avalos find_vars(char *name)
2075382d832SPeter Avalos {
2085382d832SPeter Avalos int result = -1;
2095382d832SPeter Avalos unsigned i;
2105382d832SPeter Avalos
2115382d832SPeter Avalos for (i = 0; i < VAR_COUNT; i++) {
2125382d832SPeter Avalos if (dlg_strcmp(vars[i].name, name) == 0) {
2135382d832SPeter Avalos result = (int) i;
2145382d832SPeter Avalos break;
2155382d832SPeter Avalos }
2165382d832SPeter Avalos }
2175382d832SPeter Avalos return result;
2185382d832SPeter Avalos }
2195382d832SPeter Avalos
2205382d832SPeter Avalos #ifdef HAVE_COLOR
2215382d832SPeter Avalos static int
find_color(char * name)2225382d832SPeter Avalos find_color(char *name)
2235382d832SPeter Avalos {
2245382d832SPeter Avalos int result = -1;
2255382d832SPeter Avalos int i;
2265382d832SPeter Avalos int limit = dlg_color_count();
2275382d832SPeter Avalos
2285382d832SPeter Avalos for (i = 0; i < limit; i++) {
2295382d832SPeter Avalos if (dlg_strcmp(dlg_color_table[i].name, name) == 0) {
2305382d832SPeter Avalos result = i;
2315382d832SPeter Avalos break;
2325382d832SPeter Avalos }
2335382d832SPeter Avalos }
2345382d832SPeter Avalos return result;
2355382d832SPeter Avalos }
2365382d832SPeter Avalos
2375940c9abSDaniel Fojt static const char *
to_color_name(int code)2385940c9abSDaniel Fojt to_color_name(int code)
2395382d832SPeter Avalos {
2405940c9abSDaniel Fojt const char *result = "?";
2415940c9abSDaniel Fojt size_t n;
2425940c9abSDaniel Fojt for (n = 0; n < TableSize(color_names); ++n) {
2435940c9abSDaniel Fojt if (code == color_names[n].value) {
2445940c9abSDaniel Fojt result = color_names[n].name;
2455940c9abSDaniel Fojt break;
2465940c9abSDaniel Fojt }
2475940c9abSDaniel Fojt }
2485940c9abSDaniel Fojt return result;
2495940c9abSDaniel Fojt }
2505382d832SPeter Avalos
2515940c9abSDaniel Fojt static const char *
to_boolean(int code)2525940c9abSDaniel Fojt to_boolean(int code)
2535940c9abSDaniel Fojt {
2545940c9abSDaniel Fojt return code ? "ON" : "OFF";
2555382d832SPeter Avalos }
2565382d832SPeter Avalos
2575382d832SPeter Avalos /*
2585382d832SPeter Avalos * Extract the foreground, background and highlight values from an attribute
2595940c9abSDaniel Fojt * represented as a string in one of these forms:
2605382d832SPeter Avalos *
2615940c9abSDaniel Fojt * "(foreground,background,highlight,underline,reverse)"
2625940c9abSDaniel Fojt * "(foreground,background,highlight,underline)"
2635382d832SPeter Avalos * "(foreground,background,highlight)"
2645940c9abSDaniel Fojt * "xxxx_color"
2655382d832SPeter Avalos */
2665382d832SPeter Avalos static int
str_to_attr(char * str,DIALOG_COLORS * result)2675940c9abSDaniel Fojt str_to_attr(char *str, DIALOG_COLORS * result)
2685382d832SPeter Avalos {
2695940c9abSDaniel Fojt char *tokens[MAX_TOKEN + 1];
2705940c9abSDaniel Fojt char tempstr[MAX_LEN + 1];
2715382d832SPeter Avalos size_t have;
2725940c9abSDaniel Fojt size_t i = 0;
2735940c9abSDaniel Fojt size_t tok_count = 0;
2745382d832SPeter Avalos
2755940c9abSDaniel Fojt memset(result, 0, sizeof(*result));
2765940c9abSDaniel Fojt result->fg = -1;
2775940c9abSDaniel Fojt result->bg = -1;
2785940c9abSDaniel Fojt result->hilite = -1;
2795940c9abSDaniel Fojt
2805940c9abSDaniel Fojt if (str[0] != L_PAREN || lastch(str) != R_PAREN) {
2815940c9abSDaniel Fojt int ret;
2825940c9abSDaniel Fojt
2835940c9abSDaniel Fojt if ((ret = find_color(str)) >= 0) {
2845940c9abSDaniel Fojt *result = dlg_color_table[ret];
2855382d832SPeter Avalos return 0;
2865382d832SPeter Avalos }
2875940c9abSDaniel Fojt /* invalid representation */
2885940c9abSDaniel Fojt return -1;
2895382d832SPeter Avalos }
2905382d832SPeter Avalos
2915382d832SPeter Avalos /* remove the parenthesis */
2925382d832SPeter Avalos have = strlen(str);
2935382d832SPeter Avalos if (have > MAX_LEN) {
2945382d832SPeter Avalos have = MAX_LEN - 1;
2955382d832SPeter Avalos } else {
2965382d832SPeter Avalos have -= 2;
2975382d832SPeter Avalos }
2985382d832SPeter Avalos memcpy(tempstr, str + 1, have);
2995382d832SPeter Avalos tempstr[have] = '\0';
3005382d832SPeter Avalos
3015940c9abSDaniel Fojt /* parse comma-separated tokens, allow up to
3025940c9abSDaniel Fojt * one more than max tokens to detect extras */
3035940c9abSDaniel Fojt while (tok_count < TableSize(tokens)) {
3045382d832SPeter Avalos
3055940c9abSDaniel Fojt tokens[tok_count++] = &tempstr[i];
3065382d832SPeter Avalos
3075940c9abSDaniel Fojt while (tempstr[i] != '\0' && tempstr[i] != ',')
3085382d832SPeter Avalos i++;
3095382d832SPeter Avalos
3105382d832SPeter Avalos if (tempstr[i] == '\0')
3115382d832SPeter Avalos break;
3125940c9abSDaniel Fojt
3135940c9abSDaniel Fojt tempstr[i++] = '\0';
3145382d832SPeter Avalos }
3155382d832SPeter Avalos
3165940c9abSDaniel Fojt if (tok_count < MIN_TOKEN || tok_count > MAX_TOKEN) {
3175940c9abSDaniel Fojt /* invalid representation */
3185940c9abSDaniel Fojt return -1;
3195940c9abSDaniel Fojt }
3205382d832SPeter Avalos
3215940c9abSDaniel Fojt for (i = 0; i < tok_count; ++i)
3225940c9abSDaniel Fojt trim_token(&tokens[i]);
3235382d832SPeter Avalos
3245940c9abSDaniel Fojt /* validate */
3255940c9abSDaniel Fojt if (UNKNOWN_COLOR == (result->fg = from_color_name(tokens[0]))
3265940c9abSDaniel Fojt || UNKNOWN_COLOR == (result->bg = from_color_name(tokens[1]))
3275940c9abSDaniel Fojt || UNKNOWN_COLOR == (result->hilite = from_boolean(tokens[2]))
3285940c9abSDaniel Fojt #ifdef HAVE_RC_FILE2
3295940c9abSDaniel Fojt || (tok_count >= 4 && (result->ul = from_boolean(tokens[3])) == -1)
3305940c9abSDaniel Fojt || (tok_count >= 5 && (result->rv = from_boolean(tokens[4])) == -1)
3315940c9abSDaniel Fojt #endif /* HAVE_RC_FILE2 */
3325940c9abSDaniel Fojt ) {
3335940c9abSDaniel Fojt /* invalid representation */
3345940c9abSDaniel Fojt return -1;
3355940c9abSDaniel Fojt }
3365382d832SPeter Avalos
3375382d832SPeter Avalos return 0;
3385382d832SPeter Avalos }
3395382d832SPeter Avalos #endif /* HAVE_COLOR */
3405382d832SPeter Avalos
3415382d832SPeter Avalos /*
3425382d832SPeter Avalos * Check if the line begins with a special keyword; if so, return true while
3435382d832SPeter Avalos * pointing params to its parameters.
3445382d832SPeter Avalos */
3455382d832SPeter Avalos static int
begins_with(char * line,const char * keyword,char ** params)3465382d832SPeter Avalos begins_with(char *line, const char *keyword, char **params)
3475382d832SPeter Avalos {
3485382d832SPeter Avalos int i = skip_whitespace(line, 0);
3495382d832SPeter Avalos int j = skip_keyword(line, i);
3505382d832SPeter Avalos
3515382d832SPeter Avalos if ((j - i) == (int) strlen(keyword)) {
3525382d832SPeter Avalos char save = line[j];
3535382d832SPeter Avalos line[j] = 0;
3545382d832SPeter Avalos if (!dlg_strcmp(keyword, line + i)) {
3555382d832SPeter Avalos *params = line + skip_whitespace(line, j + 1);
3565382d832SPeter Avalos return 1;
3575382d832SPeter Avalos }
3585382d832SPeter Avalos line[j] = save;
3595382d832SPeter Avalos }
3605382d832SPeter Avalos
3615382d832SPeter Avalos return 0;
3625382d832SPeter Avalos }
3635382d832SPeter Avalos
3645382d832SPeter Avalos /*
3655382d832SPeter Avalos * Parse a line in the configuration file
3665382d832SPeter Avalos *
3675382d832SPeter Avalos * Each line is of the form: "variable = value". On exit, 'var' will contain
3685382d832SPeter Avalos * the variable name, and 'value' will contain the value string.
3695382d832SPeter Avalos *
3705382d832SPeter Avalos * Return values:
3715382d832SPeter Avalos *
3725382d832SPeter Avalos * LINE_EMPTY - line is blank or comment
3735382d832SPeter Avalos * LINE_EQUALS - line contains "variable = value"
3745382d832SPeter Avalos * LINE_ERROR - syntax error in line
3755382d832SPeter Avalos */
3765382d832SPeter Avalos static PARSE_LINE
parse_line(char * line,char ** var,char ** value)3775382d832SPeter Avalos parse_line(char *line, char **var, char **value)
3785382d832SPeter Avalos {
3795382d832SPeter Avalos int i = 0;
3805382d832SPeter Avalos
3815382d832SPeter Avalos /* ignore white space at beginning of line */
3825382d832SPeter Avalos i = skip_whitespace(line, i);
3835382d832SPeter Avalos
3845382d832SPeter Avalos if (line[i] == '\0') /* line is blank */
3855382d832SPeter Avalos return LINE_EMPTY;
3865382d832SPeter Avalos else if (line[i] == '#') /* line is comment */
3875382d832SPeter Avalos return LINE_EMPTY;
3885382d832SPeter Avalos else if (line[i] == '=') /* variable names cannot start with a '=' */
3895382d832SPeter Avalos return LINE_ERROR;
3905382d832SPeter Avalos
3915382d832SPeter Avalos /* set 'var' to variable name */
3925382d832SPeter Avalos *var = line + i++; /* skip to next character */
3935382d832SPeter Avalos
3945382d832SPeter Avalos /* find end of variable name */
3955940c9abSDaniel Fojt while (!isblank(UCH(line[i])) && line[i] != '=' && line[i] != '\0')
3965382d832SPeter Avalos i++;
3975382d832SPeter Avalos
3985382d832SPeter Avalos if (line[i] == '\0') /* syntax error */
3995382d832SPeter Avalos return LINE_ERROR;
4005382d832SPeter Avalos else if (line[i] == '=')
4015382d832SPeter Avalos line[i++] = '\0';
4025382d832SPeter Avalos else {
4035382d832SPeter Avalos line[i++] = '\0';
4045382d832SPeter Avalos
4055382d832SPeter Avalos /* skip white space before '=' */
4065382d832SPeter Avalos i = skip_whitespace(line, i);
4075382d832SPeter Avalos
4085382d832SPeter Avalos if (line[i] != '=') /* syntax error */
4095382d832SPeter Avalos return LINE_ERROR;
4105382d832SPeter Avalos else
4115382d832SPeter Avalos i++; /* skip the '=' */
4125382d832SPeter Avalos }
4135382d832SPeter Avalos
4145382d832SPeter Avalos /* skip white space after '=' */
4155382d832SPeter Avalos i = skip_whitespace(line, i);
4165382d832SPeter Avalos
4175382d832SPeter Avalos if (line[i] == '\0')
4185382d832SPeter Avalos return LINE_ERROR;
4195382d832SPeter Avalos else
4205382d832SPeter Avalos *value = line + i; /* set 'value' to value string */
4215382d832SPeter Avalos
4225382d832SPeter Avalos /* trim trailing white space from 'value' */
4235382d832SPeter Avalos i = (int) strlen(*value) - 1;
4245940c9abSDaniel Fojt while (isblank(UCH((*value)[i])) && i > 0)
4255382d832SPeter Avalos i--;
4265382d832SPeter Avalos (*value)[i + 1] = '\0';
4275382d832SPeter Avalos
4285382d832SPeter Avalos return LINE_EQUALS; /* no syntax error in line */
4295382d832SPeter Avalos }
4305382d832SPeter Avalos
4315382d832SPeter Avalos /*
4325382d832SPeter Avalos * Create the configuration file
4335382d832SPeter Avalos */
4345382d832SPeter Avalos void
dlg_create_rc(const char * filename)4355382d832SPeter Avalos dlg_create_rc(const char *filename)
4365382d832SPeter Avalos {
4375382d832SPeter Avalos unsigned i;
4385382d832SPeter Avalos FILE *rc_file;
4395382d832SPeter Avalos
4405382d832SPeter Avalos if ((rc_file = fopen(filename, "wt")) == NULL)
4415382d832SPeter Avalos dlg_exiterr("Error opening file for writing in dlg_create_rc().");
4425382d832SPeter Avalos
4435382d832SPeter Avalos fprintf(rc_file, "#\n\
4445382d832SPeter Avalos # Run-time configuration file for dialog\n\
4455382d832SPeter Avalos #\n\
4465382d832SPeter Avalos # Automatically generated by \"dialog --create-rc <file>\"\n\
4475382d832SPeter Avalos #\n\
4485382d832SPeter Avalos #\n\
4495382d832SPeter Avalos # Types of values:\n\
4505382d832SPeter Avalos #\n\
4515382d832SPeter Avalos # Number - <number>\n\
4525382d832SPeter Avalos # String - \"string\"\n\
4535382d832SPeter Avalos # Boolean - <ON|OFF>\n"
4545382d832SPeter Avalos #ifdef HAVE_COLOR
4555940c9abSDaniel Fojt #ifdef HAVE_RC_FILE2
4565940c9abSDaniel Fojt "\
4575940c9abSDaniel Fojt # Attribute - (foreground,background,highlight?,underline?,reverse?)\n"
4585940c9abSDaniel Fojt #else /* HAVE_RC_FILE2 */
4595382d832SPeter Avalos "\
4605382d832SPeter Avalos # Attribute - (foreground,background,highlight?)\n"
4615940c9abSDaniel Fojt #endif /* HAVE_RC_FILE2 */
4625940c9abSDaniel Fojt #endif /* HAVE_COLOR */
4635382d832SPeter Avalos );
4645382d832SPeter Avalos
4655382d832SPeter Avalos /* Print an entry for each configuration variable */
4665382d832SPeter Avalos for (i = 0; i < VAR_COUNT; i++) {
4675382d832SPeter Avalos fprintf(rc_file, "\n# %s\n", vars[i].comment);
4685382d832SPeter Avalos switch (vars[i].type) {
4695382d832SPeter Avalos case VAL_INT:
4705382d832SPeter Avalos fprintf(rc_file, "%s = %d\n", vars[i].name,
4715382d832SPeter Avalos *((int *) vars[i].var));
4725382d832SPeter Avalos break;
4735382d832SPeter Avalos case VAL_STR:
4745382d832SPeter Avalos fprintf(rc_file, "%s = \"%s\"\n", vars[i].name,
4755382d832SPeter Avalos (char *) vars[i].var);
4765382d832SPeter Avalos break;
4775382d832SPeter Avalos case VAL_BOOL:
4785382d832SPeter Avalos fprintf(rc_file, "%s = %s\n", vars[i].name,
4795382d832SPeter Avalos *((bool *) vars[i].var) ? "ON" : "OFF");
4805382d832SPeter Avalos break;
4815382d832SPeter Avalos }
4825382d832SPeter Avalos }
4835382d832SPeter Avalos #ifdef HAVE_COLOR
4845382d832SPeter Avalos for (i = 0; i < (unsigned) dlg_color_count(); ++i) {
4855382d832SPeter Avalos unsigned j;
4865382d832SPeter Avalos bool repeat = FALSE;
4875382d832SPeter Avalos
4885382d832SPeter Avalos fprintf(rc_file, "\n# %s\n", dlg_color_table[i].comment);
4895382d832SPeter Avalos for (j = 0; j != i; ++j) {
4905382d832SPeter Avalos if (dlg_color_table[i].fg == dlg_color_table[j].fg
4915382d832SPeter Avalos && dlg_color_table[i].bg == dlg_color_table[j].bg
4925382d832SPeter Avalos && dlg_color_table[i].hilite == dlg_color_table[j].hilite) {
4935382d832SPeter Avalos fprintf(rc_file, "%s = %s\n",
4945382d832SPeter Avalos dlg_color_table[i].name,
4955382d832SPeter Avalos dlg_color_table[j].name);
4965382d832SPeter Avalos repeat = TRUE;
4975382d832SPeter Avalos break;
4985382d832SPeter Avalos }
4995382d832SPeter Avalos }
5005382d832SPeter Avalos
5015382d832SPeter Avalos if (!repeat) {
5025940c9abSDaniel Fojt fprintf(rc_file, "%s = %c", dlg_color_table[i].name, L_PAREN);
5035940c9abSDaniel Fojt fprintf(rc_file, "%s", to_color_name(dlg_color_table[i].fg));
5045940c9abSDaniel Fojt fprintf(rc_file, ",%s", to_color_name(dlg_color_table[i].bg));
5055940c9abSDaniel Fojt fprintf(rc_file, ",%s", to_boolean(dlg_color_table[i].hilite));
5065940c9abSDaniel Fojt #ifdef HAVE_RC_FILE2
5075940c9abSDaniel Fojt if (dlg_color_table[i].ul || dlg_color_table[i].rv)
5085940c9abSDaniel Fojt fprintf(rc_file, ",%s", to_boolean(dlg_color_table[i].ul));
5095940c9abSDaniel Fojt if (dlg_color_table[i].rv)
5105940c9abSDaniel Fojt fprintf(rc_file, ",%s", to_boolean(dlg_color_table[i].rv));
5115940c9abSDaniel Fojt #endif /* HAVE_RC_FILE2 */
5125940c9abSDaniel Fojt fprintf(rc_file, "%c\n", R_PAREN);
5135382d832SPeter Avalos }
5145382d832SPeter Avalos }
5155382d832SPeter Avalos #endif /* HAVE_COLOR */
5165382d832SPeter Avalos dlg_dump_keys(rc_file);
5175382d832SPeter Avalos
5185382d832SPeter Avalos (void) fclose(rc_file);
5195382d832SPeter Avalos }
5205382d832SPeter Avalos
5215940c9abSDaniel Fojt static void
report_error(const char * filename,int line_no,const char * msg)5225940c9abSDaniel Fojt report_error(const char *filename, int line_no, const char *msg)
5235940c9abSDaniel Fojt {
5245940c9abSDaniel Fojt fprintf(stderr, "%s:%d: %s\n", filename, line_no, msg);
5255940c9abSDaniel Fojt dlg_trace_msg("%s:%d: %s\n", filename, line_no, msg);
5265940c9abSDaniel Fojt }
5275940c9abSDaniel Fojt
5285382d832SPeter Avalos /*
5295382d832SPeter Avalos * Parse the configuration file and set up variables
5305382d832SPeter Avalos */
5315382d832SPeter Avalos int
dlg_parse_rc(void)5325382d832SPeter Avalos dlg_parse_rc(void)
5335382d832SPeter Avalos {
5345382d832SPeter Avalos int i;
5355382d832SPeter Avalos int l = 1;
5365382d832SPeter Avalos PARSE_LINE parse;
5375382d832SPeter Avalos char str[MAX_LEN + 1];
5385382d832SPeter Avalos char *var;
5395382d832SPeter Avalos char *value;
5405940c9abSDaniel Fojt char *filename;
5415382d832SPeter Avalos int result = 0;
5425382d832SPeter Avalos FILE *rc_file = 0;
5435382d832SPeter Avalos char *params;
5445382d832SPeter Avalos
5455382d832SPeter Avalos /*
5465382d832SPeter Avalos * At startup, dialog determines the settings to use as follows:
5475382d832SPeter Avalos *
5485382d832SPeter Avalos * a) if the environment variable $DIALOGRC is set, its value determines
5495382d832SPeter Avalos * the name of the configuration file.
5505382d832SPeter Avalos *
5515382d832SPeter Avalos * b) if the file in (a) can't be found, use the file $HOME/.dialogrc
5525382d832SPeter Avalos * as the configuration file.
5535382d832SPeter Avalos *
5545382d832SPeter Avalos * c) if the file in (b) can't be found, try using the GLOBALRC file.
5555382d832SPeter Avalos * Usually this will be /etc/dialogrc.
5565382d832SPeter Avalos *
5575382d832SPeter Avalos * d) if the file in (c) cannot be found, use the compiled-in defaults.
5585382d832SPeter Avalos */
5595382d832SPeter Avalos
5605382d832SPeter Avalos /* try step (a) */
561*a8e38dc0SAntonio Huete Jimenez if ((filename = dlg_getenv_str("DIALOGRC")) != NULL)
5625940c9abSDaniel Fojt rc_file = fopen(filename, "rt");
5635382d832SPeter Avalos
5645382d832SPeter Avalos if (rc_file == NULL) { /* step (a) failed? */
5655382d832SPeter Avalos /* try step (b) */
566*a8e38dc0SAntonio Huete Jimenez if ((filename = dlg_getenv_str("HOME")) != NULL
5675940c9abSDaniel Fojt && strlen(filename) < MAX_LEN - (sizeof(DIALOGRC) + 3)) {
5685940c9abSDaniel Fojt if (filename[0] == '\0' || lastch(filename) == '/')
5695940c9abSDaniel Fojt sprintf(str, "%s%s", filename, DIALOGRC);
5705382d832SPeter Avalos else
5715940c9abSDaniel Fojt sprintf(str, "%s/%s", filename, DIALOGRC);
5725940c9abSDaniel Fojt rc_file = fopen(filename = str, "rt");
5735382d832SPeter Avalos }
5745382d832SPeter Avalos }
5755382d832SPeter Avalos
5765382d832SPeter Avalos if (rc_file == NULL) { /* step (b) failed? */
5775382d832SPeter Avalos /* try step (c) */
5785382d832SPeter Avalos strcpy(str, GLOBALRC);
5795940c9abSDaniel Fojt if ((rc_file = fopen(filename = str, "rt")) == NULL)
5805382d832SPeter Avalos return 0; /* step (c) failed, use default values */
5815382d832SPeter Avalos }
5825382d832SPeter Avalos
5835940c9abSDaniel Fojt DLG_TRACE(("# opened rc file \"%s\"\n", filename));
5845382d832SPeter Avalos /* Scan each line and set variables */
5855382d832SPeter Avalos while ((result == 0) && (fgets(str, MAX_LEN, rc_file) != NULL)) {
5865940c9abSDaniel Fojt DLG_TRACE(("#\t%s", str));
5875382d832SPeter Avalos if (*str == '\0' || lastch(str) != '\n') {
5885382d832SPeter Avalos /* ignore rest of file if line too long */
5895940c9abSDaniel Fojt report_error(filename, l, "line too long");
5905382d832SPeter Avalos result = -1; /* parse aborted */
5915382d832SPeter Avalos break;
5925382d832SPeter Avalos }
5935382d832SPeter Avalos
5945382d832SPeter Avalos lastch(str) = '\0';
5955382d832SPeter Avalos if (begins_with(str, "bindkey", ¶ms)) {
5965382d832SPeter Avalos if (!dlg_parse_bindkey(params)) {
5975940c9abSDaniel Fojt report_error(filename, l, "invalid bindkey");
5985382d832SPeter Avalos result = -1;
5995382d832SPeter Avalos }
6005382d832SPeter Avalos continue;
6015382d832SPeter Avalos }
6025382d832SPeter Avalos parse = parse_line(str, &var, &value); /* parse current line */
6035382d832SPeter Avalos
6045382d832SPeter Avalos switch (parse) {
6055382d832SPeter Avalos case LINE_EMPTY: /* ignore blank lines and comments */
6065382d832SPeter Avalos break;
6075382d832SPeter Avalos case LINE_EQUALS:
6085382d832SPeter Avalos /* search table for matching config variable name */
6095382d832SPeter Avalos if ((i = find_vars(var)) >= 0) {
6105382d832SPeter Avalos switch (vars[i].type) {
6115382d832SPeter Avalos case VAL_INT:
6125382d832SPeter Avalos *((int *) vars[i].var) = atoi(value);
6135382d832SPeter Avalos break;
6145382d832SPeter Avalos case VAL_STR:
6155382d832SPeter Avalos if (!isquote(value[0]) || !isquote(lastch(value))
6165382d832SPeter Avalos || strlen(value) < 2) {
6175940c9abSDaniel Fojt report_error(filename, l, "expected string value");
6185382d832SPeter Avalos result = -1; /* parse aborted */
6195382d832SPeter Avalos } else {
6205382d832SPeter Avalos /* remove the (") quotes */
6215382d832SPeter Avalos value++;
6225382d832SPeter Avalos lastch(value) = '\0';
6235382d832SPeter Avalos strcpy((char *) vars[i].var, value);
6245382d832SPeter Avalos }
6255382d832SPeter Avalos break;
6265382d832SPeter Avalos case VAL_BOOL:
6275382d832SPeter Avalos if (!dlg_strcmp(value, "ON"))
6285382d832SPeter Avalos *((bool *) vars[i].var) = TRUE;
6295382d832SPeter Avalos else if (!dlg_strcmp(value, "OFF"))
6305382d832SPeter Avalos *((bool *) vars[i].var) = FALSE;
6315382d832SPeter Avalos else {
6325940c9abSDaniel Fojt report_error(filename, l, "expected boolean value");
6335382d832SPeter Avalos result = -1; /* parse aborted */
6345382d832SPeter Avalos }
6355382d832SPeter Avalos break;
6365382d832SPeter Avalos }
6375382d832SPeter Avalos #ifdef HAVE_COLOR
6385382d832SPeter Avalos } else if ((i = find_color(var)) >= 0) {
6395940c9abSDaniel Fojt DIALOG_COLORS temp;
6405940c9abSDaniel Fojt if (str_to_attr(value, &temp) == -1) {
6415940c9abSDaniel Fojt report_error(filename, l, "expected attribute value");
6425382d832SPeter Avalos result = -1; /* parse aborted */
6435382d832SPeter Avalos } else {
6445940c9abSDaniel Fojt dlg_color_table[i].fg = temp.fg;
6455940c9abSDaniel Fojt dlg_color_table[i].bg = temp.bg;
6465940c9abSDaniel Fojt dlg_color_table[i].hilite = temp.hilite;
6475940c9abSDaniel Fojt #ifdef HAVE_RC_FILE2
6485940c9abSDaniel Fojt dlg_color_table[i].ul = temp.ul;
6495940c9abSDaniel Fojt dlg_color_table[i].rv = temp.rv;
6505940c9abSDaniel Fojt #endif /* HAVE_RC_FILE2 */
6515382d832SPeter Avalos }
6525382d832SPeter Avalos } else {
6535382d832SPeter Avalos #endif /* HAVE_COLOR */
6545940c9abSDaniel Fojt report_error(filename, l, "unknown variable");
6555382d832SPeter Avalos result = -1; /* parse aborted */
6565382d832SPeter Avalos }
6575382d832SPeter Avalos break;
6585382d832SPeter Avalos case LINE_ERROR:
6595940c9abSDaniel Fojt report_error(filename, l, "syntax error");
6605382d832SPeter Avalos result = -1; /* parse aborted */
6615382d832SPeter Avalos break;
6625382d832SPeter Avalos }
6635382d832SPeter Avalos l++; /* next line */
6645382d832SPeter Avalos }
6655382d832SPeter Avalos
6665382d832SPeter Avalos (void) fclose(rc_file);
6675382d832SPeter Avalos return result;
6685382d832SPeter Avalos }
669