xref: /freebsd/contrib/dialog/rc.c (revision f4f33ea0c752ff0f9bfad34991d5bbb54e71133d)
14c8945a0SNathan Whitehorn /*
2*f4f33ea0SBaptiste Daroussin  *  $Id: rc.c,v 1.53 2018/05/31 20:32:15 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  rc.c -- routines for processing the configuration file
54c8945a0SNathan Whitehorn  *
6*f4f33ea0SBaptiste Daroussin  *  Copyright 2000-2012,2018	Thomas E. Dickey
74c8945a0SNathan Whitehorn  *
84c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
94c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
104c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
114c8945a0SNathan Whitehorn  *
124c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
134c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
144c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
154c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
164c8945a0SNathan Whitehorn  *
174c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
184c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
194c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
204c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
214c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
224c8945a0SNathan Whitehorn  *
234c8945a0SNathan Whitehorn  *  An earlier version of this program lists as authors
244c8945a0SNathan Whitehorn  *	Savio Lam (lam836@cs.cuhk.hk)
254c8945a0SNathan Whitehorn  */
264c8945a0SNathan Whitehorn 
274c8945a0SNathan Whitehorn #include <dialog.h>
284c8945a0SNathan Whitehorn 
294c8945a0SNathan Whitehorn #include <dlg_keys.h>
304c8945a0SNathan Whitehorn 
314c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
324c8945a0SNathan Whitehorn #include <dlg_colors.h>
334c8945a0SNathan Whitehorn 
344c8945a0SNathan Whitehorn /*
354c8945a0SNathan Whitehorn  * For matching color names with color values
364c8945a0SNathan Whitehorn  */
374c8945a0SNathan Whitehorn static const color_names_st color_names[] =
384c8945a0SNathan Whitehorn {
394c8945a0SNathan Whitehorn #ifdef HAVE_USE_DEFAULT_COLORS
404c8945a0SNathan Whitehorn     {"DEFAULT", -1},
414c8945a0SNathan Whitehorn #endif
424c8945a0SNathan Whitehorn     {"BLACK", COLOR_BLACK},
434c8945a0SNathan Whitehorn     {"RED", COLOR_RED},
444c8945a0SNathan Whitehorn     {"GREEN", COLOR_GREEN},
454c8945a0SNathan Whitehorn     {"YELLOW", COLOR_YELLOW},
464c8945a0SNathan Whitehorn     {"BLUE", COLOR_BLUE},
474c8945a0SNathan Whitehorn     {"MAGENTA", COLOR_MAGENTA},
484c8945a0SNathan Whitehorn     {"CYAN", COLOR_CYAN},
494c8945a0SNathan Whitehorn     {"WHITE", COLOR_WHITE},
504c8945a0SNathan Whitehorn };				/* color names */
514c8945a0SNathan Whitehorn #define COLOR_COUNT	(sizeof(color_names) / sizeof(color_names[0]))
524c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
534c8945a0SNathan Whitehorn 
544c8945a0SNathan Whitehorn #define GLOBALRC "/etc/dialogrc"
554c8945a0SNathan Whitehorn #define DIALOGRC ".dialogrc"
564c8945a0SNathan Whitehorn 
574c8945a0SNathan Whitehorn /* Types of values */
584c8945a0SNathan Whitehorn #define VAL_INT  0
594c8945a0SNathan Whitehorn #define VAL_STR  1
604c8945a0SNathan Whitehorn #define VAL_BOOL 2
614c8945a0SNathan Whitehorn 
624c8945a0SNathan Whitehorn /* Type of line in configuration file */
634c8945a0SNathan Whitehorn typedef enum {
644c8945a0SNathan Whitehorn     LINE_ERROR = -1,
654c8945a0SNathan Whitehorn     LINE_EQUALS,
664c8945a0SNathan Whitehorn     LINE_EMPTY
674c8945a0SNathan Whitehorn } PARSE_LINE;
684c8945a0SNathan Whitehorn 
694c8945a0SNathan Whitehorn /* number of configuration variables */
704c8945a0SNathan Whitehorn #define VAR_COUNT        (sizeof(vars) / sizeof(vars_st))
714c8945a0SNathan Whitehorn 
724c8945a0SNathan Whitehorn /* check if character is string quoting characters */
73*f4f33ea0SBaptiste Daroussin #define isquote(c)       ((c) == '"' || (c) == '\'')
744c8945a0SNathan Whitehorn 
754c8945a0SNathan Whitehorn /* get last character of string */
764c8945a0SNathan Whitehorn #define lastch(str)      str[strlen(str)-1]
774c8945a0SNathan Whitehorn 
784c8945a0SNathan Whitehorn /*
794c8945a0SNathan Whitehorn  * Configuration variables
804c8945a0SNathan Whitehorn  */
814c8945a0SNathan Whitehorn typedef struct {
824c8945a0SNathan Whitehorn     const char *name;		/* name of configuration variable as in DIALOGRC */
834c8945a0SNathan Whitehorn     void *var;			/* address of actual variable to change */
844c8945a0SNathan Whitehorn     int type;			/* type of value */
854c8945a0SNathan Whitehorn     const char *comment;	/* comment to put in "rc" file */
864c8945a0SNathan Whitehorn } vars_st;
874c8945a0SNathan Whitehorn 
884c8945a0SNathan Whitehorn /*
894c8945a0SNathan Whitehorn  * This table should contain only references to dialog_state, since dialog_vars
904c8945a0SNathan Whitehorn  * is reset specially in dialog.c before each widget.
914c8945a0SNathan Whitehorn  */
924c8945a0SNathan Whitehorn static const vars_st vars[] =
934c8945a0SNathan Whitehorn {
944c8945a0SNathan Whitehorn     {"aspect",
954c8945a0SNathan Whitehorn      &dialog_state.aspect_ratio,
964c8945a0SNathan Whitehorn      VAL_INT,
974c8945a0SNathan Whitehorn      "Set aspect-ration."},
984c8945a0SNathan Whitehorn 
994c8945a0SNathan Whitehorn     {"separate_widget",
1004c8945a0SNathan Whitehorn      &dialog_state.separate_str,
1014c8945a0SNathan Whitehorn      VAL_STR,
1024c8945a0SNathan Whitehorn      "Set separator (for multiple widgets output)."},
1034c8945a0SNathan Whitehorn 
1044c8945a0SNathan Whitehorn     {"tab_len",
1054c8945a0SNathan Whitehorn      &dialog_state.tab_len,
1064c8945a0SNathan Whitehorn      VAL_INT,
1074c8945a0SNathan Whitehorn      "Set tab-length (for textbox tab-conversion)."},
1084c8945a0SNathan Whitehorn 
1094c8945a0SNathan Whitehorn     {"visit_items",
1104c8945a0SNathan Whitehorn      &dialog_state.visit_items,
1114c8945a0SNathan Whitehorn      VAL_BOOL,
1124c8945a0SNathan Whitehorn      "Make tab-traversal for checklist, etc., include the list."},
1134c8945a0SNathan Whitehorn 
1144c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1154c8945a0SNathan Whitehorn     {"use_shadow",
1164c8945a0SNathan Whitehorn      &dialog_state.use_shadow,
1174c8945a0SNathan Whitehorn      VAL_BOOL,
1184c8945a0SNathan Whitehorn      "Shadow dialog boxes? This also turns on color."},
1194c8945a0SNathan Whitehorn 
1204c8945a0SNathan Whitehorn     {"use_colors",
1214c8945a0SNathan Whitehorn      &dialog_state.use_colors,
1224c8945a0SNathan Whitehorn      VAL_BOOL,
1234c8945a0SNathan Whitehorn      "Turn color support ON or OFF"},
1244c8945a0SNathan Whitehorn #endif				/* HAVE_COLOR */
1254c8945a0SNathan Whitehorn };				/* vars */
1264c8945a0SNathan Whitehorn 
1274c8945a0SNathan Whitehorn static int
1284c8945a0SNathan Whitehorn skip_whitespace(char *str, int n)
1294c8945a0SNathan Whitehorn {
130*f4f33ea0SBaptiste Daroussin     while (isblank(UCH(str[n])) && str[n] != '\0')
1314c8945a0SNathan Whitehorn 	n++;
1324c8945a0SNathan Whitehorn     return n;
1334c8945a0SNathan Whitehorn }
1344c8945a0SNathan Whitehorn 
1354c8945a0SNathan Whitehorn static int
1364c8945a0SNathan Whitehorn skip_keyword(char *str, int n)
1374c8945a0SNathan Whitehorn {
1384c8945a0SNathan Whitehorn     while (isalnum(UCH(str[n])) && str[n] != '\0')
1394c8945a0SNathan Whitehorn 	n++;
1404c8945a0SNathan Whitehorn     return n;
1414c8945a0SNathan Whitehorn }
1424c8945a0SNathan Whitehorn 
1434c8945a0SNathan Whitehorn static int
1444c8945a0SNathan Whitehorn find_vars(char *name)
1454c8945a0SNathan Whitehorn {
1464c8945a0SNathan Whitehorn     int result = -1;
1474c8945a0SNathan Whitehorn     unsigned i;
1484c8945a0SNathan Whitehorn 
1494c8945a0SNathan Whitehorn     for (i = 0; i < VAR_COUNT; i++) {
1504c8945a0SNathan Whitehorn 	if (dlg_strcmp(vars[i].name, name) == 0) {
1514c8945a0SNathan Whitehorn 	    result = (int) i;
1524c8945a0SNathan Whitehorn 	    break;
1534c8945a0SNathan Whitehorn 	}
1544c8945a0SNathan Whitehorn     }
1554c8945a0SNathan Whitehorn     return result;
1564c8945a0SNathan Whitehorn }
1574c8945a0SNathan Whitehorn 
1584c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1594c8945a0SNathan Whitehorn static int
1604c8945a0SNathan Whitehorn find_color(char *name)
1614c8945a0SNathan Whitehorn {
1624c8945a0SNathan Whitehorn     int result = -1;
1634c8945a0SNathan Whitehorn     int i;
1644c8945a0SNathan Whitehorn     int limit = dlg_color_count();
1654c8945a0SNathan Whitehorn 
1664c8945a0SNathan Whitehorn     for (i = 0; i < limit; i++) {
1674c8945a0SNathan Whitehorn 	if (dlg_strcmp(dlg_color_table[i].name, name) == 0) {
1684c8945a0SNathan Whitehorn 	    result = i;
1694c8945a0SNathan Whitehorn 	    break;
1704c8945a0SNathan Whitehorn 	}
1714c8945a0SNathan Whitehorn     }
1724c8945a0SNathan Whitehorn     return result;
1734c8945a0SNathan Whitehorn }
1744c8945a0SNathan Whitehorn 
1754c8945a0SNathan Whitehorn /*
1764c8945a0SNathan Whitehorn  * Convert an attribute to a string representation like this:
1774c8945a0SNathan Whitehorn  *
1784c8945a0SNathan Whitehorn  * "(foreground,background,highlight)"
1794c8945a0SNathan Whitehorn  */
1804c8945a0SNathan Whitehorn static char *
1814c8945a0SNathan Whitehorn attr_to_str(char *str, int fg, int bg, int hl)
1824c8945a0SNathan Whitehorn {
1834c8945a0SNathan Whitehorn     int i;
1844c8945a0SNathan Whitehorn 
1854c8945a0SNathan Whitehorn     strcpy(str, "(");
1864c8945a0SNathan Whitehorn     /* foreground */
1874c8945a0SNathan Whitehorn     for (i = 0; fg != color_names[i].value; i++) ;
1884c8945a0SNathan Whitehorn     strcat(str, color_names[i].name);
1894c8945a0SNathan Whitehorn     strcat(str, ",");
1904c8945a0SNathan Whitehorn 
1914c8945a0SNathan Whitehorn     /* background */
1924c8945a0SNathan Whitehorn     for (i = 0; bg != color_names[i].value; i++) ;
1934c8945a0SNathan Whitehorn     strcat(str, color_names[i].name);
1944c8945a0SNathan Whitehorn 
1954c8945a0SNathan Whitehorn     /* highlight */
1964c8945a0SNathan Whitehorn     strcat(str, hl ? ",ON)" : ",OFF)");
1974c8945a0SNathan Whitehorn 
1984c8945a0SNathan Whitehorn     return str;
1994c8945a0SNathan Whitehorn }
2004c8945a0SNathan Whitehorn 
2014c8945a0SNathan Whitehorn /*
2024c8945a0SNathan Whitehorn  * Extract the foreground, background and highlight values from an attribute
2032a3e3873SBaptiste Daroussin  * represented as a string in one of two forms:
2044c8945a0SNathan Whitehorn  *
2054c8945a0SNathan Whitehorn  * "(foreground,background,highlight)"
2062a3e3873SBaptiste Daroussin  " "xxxx_color"
2074c8945a0SNathan Whitehorn  */
2084c8945a0SNathan Whitehorn static int
2094c8945a0SNathan Whitehorn str_to_attr(char *str, int *fg, int *bg, int *hl)
2104c8945a0SNathan Whitehorn {
2114c8945a0SNathan Whitehorn     int i = 0, get_fg = 1;
2124c8945a0SNathan Whitehorn     unsigned j;
2134c8945a0SNathan Whitehorn     char tempstr[MAX_LEN + 1], *part;
2142a3e3873SBaptiste Daroussin     size_t have;
2154c8945a0SNathan Whitehorn 
2162a3e3873SBaptiste Daroussin     if (str[0] != '(' || lastch(str) != ')') {
2172a3e3873SBaptiste Daroussin 	if ((i = find_color(str)) >= 0) {
2182a3e3873SBaptiste Daroussin 	    *fg = dlg_color_table[i].fg;
2192a3e3873SBaptiste Daroussin 	    *bg = dlg_color_table[i].bg;
2202a3e3873SBaptiste Daroussin 	    *hl = dlg_color_table[i].hilite;
2212a3e3873SBaptiste Daroussin 	    return 0;
2222a3e3873SBaptiste Daroussin 	}
2234c8945a0SNathan Whitehorn 	return -1;		/* invalid representation */
2242a3e3873SBaptiste Daroussin     }
2254c8945a0SNathan Whitehorn 
2264c8945a0SNathan Whitehorn     /* remove the parenthesis */
2272a3e3873SBaptiste Daroussin     have = strlen(str);
2282a3e3873SBaptiste Daroussin     if (have > MAX_LEN) {
2292a3e3873SBaptiste Daroussin 	have = MAX_LEN - 1;
2302a3e3873SBaptiste Daroussin     } else {
2312a3e3873SBaptiste Daroussin 	have -= 2;
2322a3e3873SBaptiste Daroussin     }
2332a3e3873SBaptiste Daroussin     memcpy(tempstr, str + 1, have);
2342a3e3873SBaptiste Daroussin     tempstr[have] = '\0';
2354c8945a0SNathan Whitehorn 
2364c8945a0SNathan Whitehorn     /* get foreground and background */
2374c8945a0SNathan Whitehorn 
2384c8945a0SNathan Whitehorn     while (1) {
2394c8945a0SNathan Whitehorn 	/* skip white space before fg/bg string */
2404c8945a0SNathan Whitehorn 	i = skip_whitespace(tempstr, i);
2414c8945a0SNathan Whitehorn 	if (tempstr[i] == '\0')
2424c8945a0SNathan Whitehorn 	    return -1;		/* invalid representation */
2434c8945a0SNathan Whitehorn 	part = tempstr + i;	/* set 'part' to start of fg/bg string */
2444c8945a0SNathan Whitehorn 
2454c8945a0SNathan Whitehorn 	/* find end of fg/bg string */
246*f4f33ea0SBaptiste Daroussin 	while (!isblank(UCH(tempstr[i])) && tempstr[i] != ','
2474c8945a0SNathan Whitehorn 	       && tempstr[i] != '\0')
2484c8945a0SNathan Whitehorn 	    i++;
2494c8945a0SNathan Whitehorn 
2504c8945a0SNathan Whitehorn 	if (tempstr[i] == '\0')
2514c8945a0SNathan Whitehorn 	    return -1;		/* invalid representation */
252*f4f33ea0SBaptiste Daroussin 	else if (isblank(UCH(tempstr[i]))) {	/* not yet ',' */
2534c8945a0SNathan Whitehorn 	    tempstr[i++] = '\0';
2544c8945a0SNathan Whitehorn 
2554c8945a0SNathan Whitehorn 	    /* skip white space before ',' */
2564c8945a0SNathan Whitehorn 	    i = skip_whitespace(tempstr, i);
2574c8945a0SNathan Whitehorn 	    if (tempstr[i] != ',')
2584c8945a0SNathan Whitehorn 		return -1;	/* invalid representation */
2594c8945a0SNathan Whitehorn 	}
2604c8945a0SNathan Whitehorn 	tempstr[i++] = '\0';	/* skip the ',' */
2614c8945a0SNathan Whitehorn 	for (j = 0; j < COLOR_COUNT && dlg_strcmp(part, color_names[j].name);
2624c8945a0SNathan Whitehorn 	     j++) ;
2634c8945a0SNathan Whitehorn 	if (j == COLOR_COUNT)	/* invalid color name */
2644c8945a0SNathan Whitehorn 	    return -1;
2654c8945a0SNathan Whitehorn 	if (get_fg) {
2664c8945a0SNathan Whitehorn 	    *fg = color_names[j].value;
2674c8945a0SNathan Whitehorn 	    get_fg = 0;		/* next we have to get the background */
2684c8945a0SNathan Whitehorn 	} else {
2694c8945a0SNathan Whitehorn 	    *bg = color_names[j].value;
2704c8945a0SNathan Whitehorn 	    break;
2714c8945a0SNathan Whitehorn 	}
2724c8945a0SNathan Whitehorn     }				/* got foreground and background */
2734c8945a0SNathan Whitehorn 
2744c8945a0SNathan Whitehorn     /* get highlight */
2754c8945a0SNathan Whitehorn 
2764c8945a0SNathan Whitehorn     /* skip white space before highlight string */
2774c8945a0SNathan Whitehorn     i = skip_whitespace(tempstr, i);
2784c8945a0SNathan Whitehorn     if (tempstr[i] == '\0')
2794c8945a0SNathan Whitehorn 	return -1;		/* invalid representation */
2804c8945a0SNathan Whitehorn     part = tempstr + i;		/* set 'part' to start of highlight string */
2814c8945a0SNathan Whitehorn 
2824c8945a0SNathan Whitehorn     /* trim trailing white space from highlight string */
2834c8945a0SNathan Whitehorn     i = (int) strlen(part) - 1;
284*f4f33ea0SBaptiste Daroussin     while (isblank(UCH(part[i])) && i > 0)
2854c8945a0SNathan Whitehorn 	i--;
2864c8945a0SNathan Whitehorn     part[i + 1] = '\0';
2874c8945a0SNathan Whitehorn 
2884c8945a0SNathan Whitehorn     if (!dlg_strcmp(part, "ON"))
2894c8945a0SNathan Whitehorn 	*hl = TRUE;
2904c8945a0SNathan Whitehorn     else if (!dlg_strcmp(part, "OFF"))
2914c8945a0SNathan Whitehorn 	*hl = FALSE;
2924c8945a0SNathan Whitehorn     else
2934c8945a0SNathan Whitehorn 	return -1;		/* invalid highlight value */
2944c8945a0SNathan Whitehorn 
2954c8945a0SNathan Whitehorn     return 0;
2964c8945a0SNathan Whitehorn }
2974c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
2984c8945a0SNathan Whitehorn 
2994c8945a0SNathan Whitehorn /*
3004c8945a0SNathan Whitehorn  * Check if the line begins with a special keyword; if so, return true while
3014c8945a0SNathan Whitehorn  * pointing params to its parameters.
3024c8945a0SNathan Whitehorn  */
3034c8945a0SNathan Whitehorn static int
3044c8945a0SNathan Whitehorn begins_with(char *line, const char *keyword, char **params)
3054c8945a0SNathan Whitehorn {
3064c8945a0SNathan Whitehorn     int i = skip_whitespace(line, 0);
3074c8945a0SNathan Whitehorn     int j = skip_keyword(line, i);
3084c8945a0SNathan Whitehorn 
3094c8945a0SNathan Whitehorn     if ((j - i) == (int) strlen(keyword)) {
3104c8945a0SNathan Whitehorn 	char save = line[j];
3114c8945a0SNathan Whitehorn 	line[j] = 0;
3124c8945a0SNathan Whitehorn 	if (!dlg_strcmp(keyword, line + i)) {
3134c8945a0SNathan Whitehorn 	    *params = line + skip_whitespace(line, j + 1);
3144c8945a0SNathan Whitehorn 	    return 1;
3154c8945a0SNathan Whitehorn 	}
3164c8945a0SNathan Whitehorn 	line[j] = save;
3174c8945a0SNathan Whitehorn     }
3184c8945a0SNathan Whitehorn 
3194c8945a0SNathan Whitehorn     return 0;
3204c8945a0SNathan Whitehorn }
3214c8945a0SNathan Whitehorn 
3224c8945a0SNathan Whitehorn /*
3234c8945a0SNathan Whitehorn  * Parse a line in the configuration file
3244c8945a0SNathan Whitehorn  *
3254c8945a0SNathan Whitehorn  * Each line is of the form:  "variable = value". On exit, 'var' will contain
3264c8945a0SNathan Whitehorn  * the variable name, and 'value' will contain the value string.
3274c8945a0SNathan Whitehorn  *
3284c8945a0SNathan Whitehorn  * Return values:
3294c8945a0SNathan Whitehorn  *
3304c8945a0SNathan Whitehorn  * LINE_EMPTY   - line is blank or comment
3314c8945a0SNathan Whitehorn  * LINE_EQUALS  - line contains "variable = value"
3324c8945a0SNathan Whitehorn  * LINE_ERROR   - syntax error in line
3334c8945a0SNathan Whitehorn  */
3344c8945a0SNathan Whitehorn static PARSE_LINE
3354c8945a0SNathan Whitehorn parse_line(char *line, char **var, char **value)
3364c8945a0SNathan Whitehorn {
3374c8945a0SNathan Whitehorn     int i = 0;
3384c8945a0SNathan Whitehorn 
3394c8945a0SNathan Whitehorn     /* ignore white space at beginning of line */
3404c8945a0SNathan Whitehorn     i = skip_whitespace(line, i);
3414c8945a0SNathan Whitehorn 
3424c8945a0SNathan Whitehorn     if (line[i] == '\0')	/* line is blank */
3434c8945a0SNathan Whitehorn 	return LINE_EMPTY;
3444c8945a0SNathan Whitehorn     else if (line[i] == '#')	/* line is comment */
3454c8945a0SNathan Whitehorn 	return LINE_EMPTY;
3464c8945a0SNathan Whitehorn     else if (line[i] == '=')	/* variable names cannot start with a '=' */
3474c8945a0SNathan Whitehorn 	return LINE_ERROR;
3484c8945a0SNathan Whitehorn 
3494c8945a0SNathan Whitehorn     /* set 'var' to variable name */
3504c8945a0SNathan Whitehorn     *var = line + i++;		/* skip to next character */
3514c8945a0SNathan Whitehorn 
3524c8945a0SNathan Whitehorn     /* find end of variable name */
353*f4f33ea0SBaptiste Daroussin     while (!isblank(UCH(line[i])) && line[i] != '=' && line[i] != '\0')
3544c8945a0SNathan Whitehorn 	i++;
3554c8945a0SNathan Whitehorn 
3564c8945a0SNathan Whitehorn     if (line[i] == '\0')	/* syntax error */
3574c8945a0SNathan Whitehorn 	return LINE_ERROR;
3584c8945a0SNathan Whitehorn     else if (line[i] == '=')
3594c8945a0SNathan Whitehorn 	line[i++] = '\0';
3604c8945a0SNathan Whitehorn     else {
3614c8945a0SNathan Whitehorn 	line[i++] = '\0';
3624c8945a0SNathan Whitehorn 
3634c8945a0SNathan Whitehorn 	/* skip white space before '=' */
3644c8945a0SNathan Whitehorn 	i = skip_whitespace(line, i);
3654c8945a0SNathan Whitehorn 
3664c8945a0SNathan Whitehorn 	if (line[i] != '=')	/* syntax error */
3674c8945a0SNathan Whitehorn 	    return LINE_ERROR;
3684c8945a0SNathan Whitehorn 	else
3694c8945a0SNathan Whitehorn 	    i++;		/* skip the '=' */
3704c8945a0SNathan Whitehorn     }
3714c8945a0SNathan Whitehorn 
3724c8945a0SNathan Whitehorn     /* skip white space after '=' */
3734c8945a0SNathan Whitehorn     i = skip_whitespace(line, i);
3744c8945a0SNathan Whitehorn 
3754c8945a0SNathan Whitehorn     if (line[i] == '\0')
3764c8945a0SNathan Whitehorn 	return LINE_ERROR;
3774c8945a0SNathan Whitehorn     else
3784c8945a0SNathan Whitehorn 	*value = line + i;	/* set 'value' to value string */
3794c8945a0SNathan Whitehorn 
3804c8945a0SNathan Whitehorn     /* trim trailing white space from 'value' */
3814c8945a0SNathan Whitehorn     i = (int) strlen(*value) - 1;
382*f4f33ea0SBaptiste Daroussin     while (isblank(UCH((*value)[i])) && i > 0)
3834c8945a0SNathan Whitehorn 	i--;
3844c8945a0SNathan Whitehorn     (*value)[i + 1] = '\0';
3854c8945a0SNathan Whitehorn 
3864c8945a0SNathan Whitehorn     return LINE_EQUALS;		/* no syntax error in line */
3874c8945a0SNathan Whitehorn }
3884c8945a0SNathan Whitehorn 
3894c8945a0SNathan Whitehorn /*
3904c8945a0SNathan Whitehorn  * Create the configuration file
3914c8945a0SNathan Whitehorn  */
3924c8945a0SNathan Whitehorn void
3934c8945a0SNathan Whitehorn dlg_create_rc(const char *filename)
3944c8945a0SNathan Whitehorn {
3954c8945a0SNathan Whitehorn     unsigned i;
3964c8945a0SNathan Whitehorn     FILE *rc_file;
3974c8945a0SNathan Whitehorn 
3984c8945a0SNathan Whitehorn     if ((rc_file = fopen(filename, "wt")) == NULL)
3994c8945a0SNathan Whitehorn 	dlg_exiterr("Error opening file for writing in dlg_create_rc().");
4004c8945a0SNathan Whitehorn 
4014c8945a0SNathan Whitehorn     fprintf(rc_file, "#\n\
4024c8945a0SNathan Whitehorn # Run-time configuration file for dialog\n\
4034c8945a0SNathan Whitehorn #\n\
4044c8945a0SNathan Whitehorn # Automatically generated by \"dialog --create-rc <file>\"\n\
4054c8945a0SNathan Whitehorn #\n\
4064c8945a0SNathan Whitehorn #\n\
4074c8945a0SNathan Whitehorn # Types of values:\n\
4084c8945a0SNathan Whitehorn #\n\
4094c8945a0SNathan Whitehorn # Number     -  <number>\n\
4104c8945a0SNathan Whitehorn # String     -  \"string\"\n\
4114c8945a0SNathan Whitehorn # Boolean    -  <ON|OFF>\n"
4124c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4134c8945a0SNathan Whitehorn 	    "\
4144c8945a0SNathan Whitehorn # Attribute  -  (foreground,background,highlight?)\n"
4154c8945a0SNathan Whitehorn #endif
4164c8945a0SNathan Whitehorn 	);
4174c8945a0SNathan Whitehorn 
4184c8945a0SNathan Whitehorn     /* Print an entry for each configuration variable */
4194c8945a0SNathan Whitehorn     for (i = 0; i < VAR_COUNT; i++) {
4204c8945a0SNathan Whitehorn 	fprintf(rc_file, "\n# %s\n", vars[i].comment);
4214c8945a0SNathan Whitehorn 	switch (vars[i].type) {
4224c8945a0SNathan Whitehorn 	case VAL_INT:
4234c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %d\n", vars[i].name,
4244c8945a0SNathan Whitehorn 		    *((int *) vars[i].var));
4254c8945a0SNathan Whitehorn 	    break;
4264c8945a0SNathan Whitehorn 	case VAL_STR:
4274c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = \"%s\"\n", vars[i].name,
4284c8945a0SNathan Whitehorn 		    (char *) vars[i].var);
4294c8945a0SNathan Whitehorn 	    break;
4304c8945a0SNathan Whitehorn 	case VAL_BOOL:
4314c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %s\n", vars[i].name,
4324c8945a0SNathan Whitehorn 		    *((bool *) vars[i].var) ? "ON" : "OFF");
4334c8945a0SNathan Whitehorn 	    break;
4344c8945a0SNathan Whitehorn 	}
4354c8945a0SNathan Whitehorn     }
4364c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4374c8945a0SNathan Whitehorn     for (i = 0; i < (unsigned) dlg_color_count(); ++i) {
4384c8945a0SNathan Whitehorn 	char buffer[MAX_LEN + 1];
4392a3e3873SBaptiste Daroussin 	unsigned j;
4402a3e3873SBaptiste Daroussin 	bool repeat = FALSE;
4414c8945a0SNathan Whitehorn 
4424c8945a0SNathan Whitehorn 	fprintf(rc_file, "\n# %s\n", dlg_color_table[i].comment);
4432a3e3873SBaptiste Daroussin 	for (j = 0; j != i; ++j) {
4442a3e3873SBaptiste Daroussin 	    if (dlg_color_table[i].fg == dlg_color_table[j].fg
4452a3e3873SBaptiste Daroussin 		&& dlg_color_table[i].bg == dlg_color_table[j].bg
4462a3e3873SBaptiste Daroussin 		&& dlg_color_table[i].hilite == dlg_color_table[j].hilite) {
4472a3e3873SBaptiste Daroussin 		fprintf(rc_file, "%s = %s\n",
4482a3e3873SBaptiste Daroussin 			dlg_color_table[i].name,
4492a3e3873SBaptiste Daroussin 			dlg_color_table[j].name);
4502a3e3873SBaptiste Daroussin 		repeat = TRUE;
4512a3e3873SBaptiste Daroussin 		break;
4522a3e3873SBaptiste Daroussin 	    }
4532a3e3873SBaptiste Daroussin 	}
4542a3e3873SBaptiste Daroussin 
4552a3e3873SBaptiste Daroussin 	if (!repeat) {
4564c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %s\n", dlg_color_table[i].name,
4574c8945a0SNathan Whitehorn 		    attr_to_str(buffer,
4584c8945a0SNathan Whitehorn 				dlg_color_table[i].fg,
4594c8945a0SNathan Whitehorn 				dlg_color_table[i].bg,
4604c8945a0SNathan Whitehorn 				dlg_color_table[i].hilite));
4614c8945a0SNathan Whitehorn 	}
4622a3e3873SBaptiste Daroussin     }
4634c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
4644c8945a0SNathan Whitehorn     dlg_dump_keys(rc_file);
4654c8945a0SNathan Whitehorn 
4664c8945a0SNathan Whitehorn     (void) fclose(rc_file);
4674c8945a0SNathan Whitehorn }
4684c8945a0SNathan Whitehorn 
4694c8945a0SNathan Whitehorn /*
4704c8945a0SNathan Whitehorn  * Parse the configuration file and set up variables
4714c8945a0SNathan Whitehorn  */
4724c8945a0SNathan Whitehorn int
4734c8945a0SNathan Whitehorn dlg_parse_rc(void)
4744c8945a0SNathan Whitehorn {
4754c8945a0SNathan Whitehorn     int i;
4764c8945a0SNathan Whitehorn     int l = 1;
4774c8945a0SNathan Whitehorn     PARSE_LINE parse;
4784c8945a0SNathan Whitehorn     char str[MAX_LEN + 1];
4794c8945a0SNathan Whitehorn     char *var;
4804c8945a0SNathan Whitehorn     char *value;
4814c8945a0SNathan Whitehorn     char *tempptr;
4824c8945a0SNathan Whitehorn     int result = 0;
4834c8945a0SNathan Whitehorn     FILE *rc_file = 0;
4844c8945a0SNathan Whitehorn     char *params;
4854c8945a0SNathan Whitehorn 
4864c8945a0SNathan Whitehorn     /*
4874c8945a0SNathan Whitehorn      *  At startup, dialog determines the settings to use as follows:
4884c8945a0SNathan Whitehorn      *
4894c8945a0SNathan Whitehorn      *  a) if the environment variable $DIALOGRC is set, its value determines
4904c8945a0SNathan Whitehorn      *     the name of the configuration file.
4914c8945a0SNathan Whitehorn      *
4924c8945a0SNathan Whitehorn      *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
4934c8945a0SNathan Whitehorn      *     as the configuration file.
4944c8945a0SNathan Whitehorn      *
4954c8945a0SNathan Whitehorn      *  c) if the file in (b) can't be found, try using the GLOBALRC file.
4964c8945a0SNathan Whitehorn      *     Usually this will be /etc/dialogrc.
4974c8945a0SNathan Whitehorn      *
4984c8945a0SNathan Whitehorn      *  d) if the file in (c) cannot be found, use the compiled-in defaults.
4994c8945a0SNathan Whitehorn      */
5004c8945a0SNathan Whitehorn 
5014c8945a0SNathan Whitehorn     /* try step (a) */
5024c8945a0SNathan Whitehorn     if ((tempptr = getenv("DIALOGRC")) != NULL)
5034c8945a0SNathan Whitehorn 	rc_file = fopen(tempptr, "rt");
5044c8945a0SNathan Whitehorn 
5054c8945a0SNathan Whitehorn     if (rc_file == NULL) {	/* step (a) failed? */
5064c8945a0SNathan Whitehorn 	/* try step (b) */
5074c8945a0SNathan Whitehorn 	if ((tempptr = getenv("HOME")) != NULL
5084c8945a0SNathan Whitehorn 	    && strlen(tempptr) < MAX_LEN - (sizeof(DIALOGRC) + 3)) {
5094c8945a0SNathan Whitehorn 	    if (tempptr[0] == '\0' || lastch(tempptr) == '/')
5104c8945a0SNathan Whitehorn 		sprintf(str, "%s%s", tempptr, DIALOGRC);
5114c8945a0SNathan Whitehorn 	    else
5124c8945a0SNathan Whitehorn 		sprintf(str, "%s/%s", tempptr, DIALOGRC);
513682c9e0fSNathan Whitehorn 	    rc_file = fopen(tempptr = str, "rt");
5144c8945a0SNathan Whitehorn 	}
5154c8945a0SNathan Whitehorn     }
5164c8945a0SNathan Whitehorn 
5174c8945a0SNathan Whitehorn     if (rc_file == NULL) {	/* step (b) failed? */
5184c8945a0SNathan Whitehorn 	/* try step (c) */
5194c8945a0SNathan Whitehorn 	strcpy(str, GLOBALRC);
520682c9e0fSNathan Whitehorn 	if ((rc_file = fopen(tempptr = str, "rt")) == NULL)
5214c8945a0SNathan Whitehorn 	    return 0;		/* step (c) failed, use default values */
5224c8945a0SNathan Whitehorn     }
5234c8945a0SNathan Whitehorn 
524*f4f33ea0SBaptiste Daroussin     DLG_TRACE(("# opened rc file \"%s\"\n", tempptr));
5254c8945a0SNathan Whitehorn     /* Scan each line and set variables */
5264c8945a0SNathan Whitehorn     while ((result == 0) && (fgets(str, MAX_LEN, rc_file) != NULL)) {
527*f4f33ea0SBaptiste Daroussin 	DLG_TRACE(("#\t%s", str));
5284c8945a0SNathan Whitehorn 	if (*str == '\0' || lastch(str) != '\n') {
5294c8945a0SNathan Whitehorn 	    /* ignore rest of file if line too long */
5304c8945a0SNathan Whitehorn 	    fprintf(stderr, "\nParse error: line %d of configuration"
5314c8945a0SNathan Whitehorn 		    " file too long.\n", l);
5324c8945a0SNathan Whitehorn 	    result = -1;	/* parse aborted */
5334c8945a0SNathan Whitehorn 	    break;
5344c8945a0SNathan Whitehorn 	}
5354c8945a0SNathan Whitehorn 
5364c8945a0SNathan Whitehorn 	lastch(str) = '\0';
5374c8945a0SNathan Whitehorn 	if (begins_with(str, "bindkey", &params)) {
5382a3e3873SBaptiste Daroussin 	    if (!dlg_parse_bindkey(params)) {
5392a3e3873SBaptiste Daroussin 		fprintf(stderr, "\nParse error: line %d of configuration\n", l);
5402a3e3873SBaptiste Daroussin 		result = -1;
5412a3e3873SBaptiste Daroussin 	    }
5424c8945a0SNathan Whitehorn 	    continue;
5434c8945a0SNathan Whitehorn 	}
5444c8945a0SNathan Whitehorn 	parse = parse_line(str, &var, &value);	/* parse current line */
5454c8945a0SNathan Whitehorn 
5464c8945a0SNathan Whitehorn 	switch (parse) {
5474c8945a0SNathan Whitehorn 	case LINE_EMPTY:	/* ignore blank lines and comments */
5484c8945a0SNathan Whitehorn 	    break;
5494c8945a0SNathan Whitehorn 	case LINE_EQUALS:
5504c8945a0SNathan Whitehorn 	    /* search table for matching config variable name */
5514c8945a0SNathan Whitehorn 	    if ((i = find_vars(var)) >= 0) {
5524c8945a0SNathan Whitehorn 		switch (vars[i].type) {
5534c8945a0SNathan Whitehorn 		case VAL_INT:
5544c8945a0SNathan Whitehorn 		    *((int *) vars[i].var) = atoi(value);
5554c8945a0SNathan Whitehorn 		    break;
5564c8945a0SNathan Whitehorn 		case VAL_STR:
5574c8945a0SNathan Whitehorn 		    if (!isquote(value[0]) || !isquote(lastch(value))
5584c8945a0SNathan Whitehorn 			|| strlen(value) < 2) {
5594c8945a0SNathan Whitehorn 			fprintf(stderr, "\nParse error: string value "
5604c8945a0SNathan Whitehorn 				"expected at line %d of configuration "
5614c8945a0SNathan Whitehorn 				"file.\n", l);
5624c8945a0SNathan Whitehorn 			result = -1;	/* parse aborted */
5634c8945a0SNathan Whitehorn 		    } else {
5644c8945a0SNathan Whitehorn 			/* remove the (") quotes */
5654c8945a0SNathan Whitehorn 			value++;
5664c8945a0SNathan Whitehorn 			lastch(value) = '\0';
5674c8945a0SNathan Whitehorn 			strcpy((char *) vars[i].var, value);
5684c8945a0SNathan Whitehorn 		    }
5694c8945a0SNathan Whitehorn 		    break;
5704c8945a0SNathan Whitehorn 		case VAL_BOOL:
5714c8945a0SNathan Whitehorn 		    if (!dlg_strcmp(value, "ON"))
5724c8945a0SNathan Whitehorn 			*((bool *) vars[i].var) = TRUE;
5734c8945a0SNathan Whitehorn 		    else if (!dlg_strcmp(value, "OFF"))
5744c8945a0SNathan Whitehorn 			*((bool *) vars[i].var) = FALSE;
5754c8945a0SNathan Whitehorn 		    else {
5764c8945a0SNathan Whitehorn 			fprintf(stderr, "\nParse error: boolean value "
5774c8945a0SNathan Whitehorn 				"expected at line %d of configuration "
5784c8945a0SNathan Whitehorn 				"file (found %s).\n", l, value);
5794c8945a0SNathan Whitehorn 			result = -1;	/* parse aborted */
5804c8945a0SNathan Whitehorn 		    }
5814c8945a0SNathan Whitehorn 		    break;
5824c8945a0SNathan Whitehorn 		}
5834c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
5844c8945a0SNathan Whitehorn 	    } else if ((i = find_color(var)) >= 0) {
5854c8945a0SNathan Whitehorn 		int fg = 0;
5864c8945a0SNathan Whitehorn 		int bg = 0;
5874c8945a0SNathan Whitehorn 		int hl = 0;
5884c8945a0SNathan Whitehorn 		if (str_to_attr(value, &fg, &bg, &hl) == -1) {
5894c8945a0SNathan Whitehorn 		    fprintf(stderr, "\nParse error: attribute "
5904c8945a0SNathan Whitehorn 			    "value expected at line %d of configuration "
5914c8945a0SNathan Whitehorn 			    "file.\n", l);
5924c8945a0SNathan Whitehorn 		    result = -1;	/* parse aborted */
5934c8945a0SNathan Whitehorn 		} else {
5944c8945a0SNathan Whitehorn 		    dlg_color_table[i].fg = fg;
5954c8945a0SNathan Whitehorn 		    dlg_color_table[i].bg = bg;
5964c8945a0SNathan Whitehorn 		    dlg_color_table[i].hilite = hl;
5974c8945a0SNathan Whitehorn 		}
5984c8945a0SNathan Whitehorn 	    } else {
5994c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
6004c8945a0SNathan Whitehorn 		fprintf(stderr, "\nParse error: unknown variable "
6014c8945a0SNathan Whitehorn 			"at line %d of configuration file:\n\t%s\n", l, var);
6024c8945a0SNathan Whitehorn 		result = -1;	/* parse aborted */
6034c8945a0SNathan Whitehorn 	    }
6044c8945a0SNathan Whitehorn 	    break;
6054c8945a0SNathan Whitehorn 	case LINE_ERROR:
6064c8945a0SNathan Whitehorn 	    fprintf(stderr, "\nParse error: syntax error at line %d of "
6074c8945a0SNathan Whitehorn 		    "configuration file.\n", l);
6084c8945a0SNathan Whitehorn 	    result = -1;	/* parse aborted */
6094c8945a0SNathan Whitehorn 	    break;
6104c8945a0SNathan Whitehorn 	}
6114c8945a0SNathan Whitehorn 	l++;			/* next line */
6124c8945a0SNathan Whitehorn     }
6134c8945a0SNathan Whitehorn 
6144c8945a0SNathan Whitehorn     (void) fclose(rc_file);
6154c8945a0SNathan Whitehorn     return result;
6164c8945a0SNathan Whitehorn }
617