xref: /freebsd/contrib/dialog/rc.c (revision 2a3e3873a1e4cd958f2b0f85d3b10cfa40575d30)
14c8945a0SNathan Whitehorn /*
2*2a3e3873SBaptiste Daroussin  *  $Id: rc.c,v 1.51 2012/11/30 21:32:39 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  rc.c -- routines for processing the configuration file
54c8945a0SNathan Whitehorn  *
6*2a3e3873SBaptiste Daroussin  *  Copyright 2000-2011,2012	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 white space */
734c8945a0SNathan Whitehorn #define whitespace(c)    (c == ' ' || c == TAB)
744c8945a0SNathan Whitehorn 
754c8945a0SNathan Whitehorn /* check if character is string quoting characters */
764c8945a0SNathan Whitehorn #define isquote(c)       (c == '"' || c == '\'')
774c8945a0SNathan Whitehorn 
784c8945a0SNathan Whitehorn /* get last character of string */
794c8945a0SNathan Whitehorn #define lastch(str)      str[strlen(str)-1]
804c8945a0SNathan Whitehorn 
814c8945a0SNathan Whitehorn /*
824c8945a0SNathan Whitehorn  * Configuration variables
834c8945a0SNathan Whitehorn  */
844c8945a0SNathan Whitehorn typedef struct {
854c8945a0SNathan Whitehorn     const char *name;		/* name of configuration variable as in DIALOGRC */
864c8945a0SNathan Whitehorn     void *var;			/* address of actual variable to change */
874c8945a0SNathan Whitehorn     int type;			/* type of value */
884c8945a0SNathan Whitehorn     const char *comment;	/* comment to put in "rc" file */
894c8945a0SNathan Whitehorn } vars_st;
904c8945a0SNathan Whitehorn 
914c8945a0SNathan Whitehorn /*
924c8945a0SNathan Whitehorn  * This table should contain only references to dialog_state, since dialog_vars
934c8945a0SNathan Whitehorn  * is reset specially in dialog.c before each widget.
944c8945a0SNathan Whitehorn  */
954c8945a0SNathan Whitehorn static const vars_st vars[] =
964c8945a0SNathan Whitehorn {
974c8945a0SNathan Whitehorn     {"aspect",
984c8945a0SNathan Whitehorn      &dialog_state.aspect_ratio,
994c8945a0SNathan Whitehorn      VAL_INT,
1004c8945a0SNathan Whitehorn      "Set aspect-ration."},
1014c8945a0SNathan Whitehorn 
1024c8945a0SNathan Whitehorn     {"separate_widget",
1034c8945a0SNathan Whitehorn      &dialog_state.separate_str,
1044c8945a0SNathan Whitehorn      VAL_STR,
1054c8945a0SNathan Whitehorn      "Set separator (for multiple widgets output)."},
1064c8945a0SNathan Whitehorn 
1074c8945a0SNathan Whitehorn     {"tab_len",
1084c8945a0SNathan Whitehorn      &dialog_state.tab_len,
1094c8945a0SNathan Whitehorn      VAL_INT,
1104c8945a0SNathan Whitehorn      "Set tab-length (for textbox tab-conversion)."},
1114c8945a0SNathan Whitehorn 
1124c8945a0SNathan Whitehorn     {"visit_items",
1134c8945a0SNathan Whitehorn      &dialog_state.visit_items,
1144c8945a0SNathan Whitehorn      VAL_BOOL,
1154c8945a0SNathan Whitehorn      "Make tab-traversal for checklist, etc., include the list."},
1164c8945a0SNathan Whitehorn 
1174c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1184c8945a0SNathan Whitehorn     {"use_shadow",
1194c8945a0SNathan Whitehorn      &dialog_state.use_shadow,
1204c8945a0SNathan Whitehorn      VAL_BOOL,
1214c8945a0SNathan Whitehorn      "Shadow dialog boxes? This also turns on color."},
1224c8945a0SNathan Whitehorn 
1234c8945a0SNathan Whitehorn     {"use_colors",
1244c8945a0SNathan Whitehorn      &dialog_state.use_colors,
1254c8945a0SNathan Whitehorn      VAL_BOOL,
1264c8945a0SNathan Whitehorn      "Turn color support ON or OFF"},
1274c8945a0SNathan Whitehorn #endif				/* HAVE_COLOR */
1284c8945a0SNathan Whitehorn };				/* vars */
1294c8945a0SNathan Whitehorn 
1304c8945a0SNathan Whitehorn static int
1314c8945a0SNathan Whitehorn skip_whitespace(char *str, int n)
1324c8945a0SNathan Whitehorn {
1334c8945a0SNathan Whitehorn     while (whitespace(str[n]) && str[n] != '\0')
1344c8945a0SNathan Whitehorn 	n++;
1354c8945a0SNathan Whitehorn     return n;
1364c8945a0SNathan Whitehorn }
1374c8945a0SNathan Whitehorn 
1384c8945a0SNathan Whitehorn static int
1394c8945a0SNathan Whitehorn skip_keyword(char *str, int n)
1404c8945a0SNathan Whitehorn {
1414c8945a0SNathan Whitehorn     while (isalnum(UCH(str[n])) && str[n] != '\0')
1424c8945a0SNathan Whitehorn 	n++;
1434c8945a0SNathan Whitehorn     return n;
1444c8945a0SNathan Whitehorn }
1454c8945a0SNathan Whitehorn 
1464c8945a0SNathan Whitehorn static int
1474c8945a0SNathan Whitehorn find_vars(char *name)
1484c8945a0SNathan Whitehorn {
1494c8945a0SNathan Whitehorn     int result = -1;
1504c8945a0SNathan Whitehorn     unsigned i;
1514c8945a0SNathan Whitehorn 
1524c8945a0SNathan Whitehorn     for (i = 0; i < VAR_COUNT; i++) {
1534c8945a0SNathan Whitehorn 	if (dlg_strcmp(vars[i].name, name) == 0) {
1544c8945a0SNathan Whitehorn 	    result = (int) i;
1554c8945a0SNathan Whitehorn 	    break;
1564c8945a0SNathan Whitehorn 	}
1574c8945a0SNathan Whitehorn     }
1584c8945a0SNathan Whitehorn     return result;
1594c8945a0SNathan Whitehorn }
1604c8945a0SNathan Whitehorn 
1614c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
1624c8945a0SNathan Whitehorn static int
1634c8945a0SNathan Whitehorn find_color(char *name)
1644c8945a0SNathan Whitehorn {
1654c8945a0SNathan Whitehorn     int result = -1;
1664c8945a0SNathan Whitehorn     int i;
1674c8945a0SNathan Whitehorn     int limit = dlg_color_count();
1684c8945a0SNathan Whitehorn 
1694c8945a0SNathan Whitehorn     for (i = 0; i < limit; i++) {
1704c8945a0SNathan Whitehorn 	if (dlg_strcmp(dlg_color_table[i].name, name) == 0) {
1714c8945a0SNathan Whitehorn 	    result = i;
1724c8945a0SNathan Whitehorn 	    break;
1734c8945a0SNathan Whitehorn 	}
1744c8945a0SNathan Whitehorn     }
1754c8945a0SNathan Whitehorn     return result;
1764c8945a0SNathan Whitehorn }
1774c8945a0SNathan Whitehorn 
1784c8945a0SNathan Whitehorn /*
1794c8945a0SNathan Whitehorn  * Convert an attribute to a string representation like this:
1804c8945a0SNathan Whitehorn  *
1814c8945a0SNathan Whitehorn  * "(foreground,background,highlight)"
1824c8945a0SNathan Whitehorn  */
1834c8945a0SNathan Whitehorn static char *
1844c8945a0SNathan Whitehorn attr_to_str(char *str, int fg, int bg, int hl)
1854c8945a0SNathan Whitehorn {
1864c8945a0SNathan Whitehorn     int i;
1874c8945a0SNathan Whitehorn 
1884c8945a0SNathan Whitehorn     strcpy(str, "(");
1894c8945a0SNathan Whitehorn     /* foreground */
1904c8945a0SNathan Whitehorn     for (i = 0; fg != color_names[i].value; i++) ;
1914c8945a0SNathan Whitehorn     strcat(str, color_names[i].name);
1924c8945a0SNathan Whitehorn     strcat(str, ",");
1934c8945a0SNathan Whitehorn 
1944c8945a0SNathan Whitehorn     /* background */
1954c8945a0SNathan Whitehorn     for (i = 0; bg != color_names[i].value; i++) ;
1964c8945a0SNathan Whitehorn     strcat(str, color_names[i].name);
1974c8945a0SNathan Whitehorn 
1984c8945a0SNathan Whitehorn     /* highlight */
1994c8945a0SNathan Whitehorn     strcat(str, hl ? ",ON)" : ",OFF)");
2004c8945a0SNathan Whitehorn 
2014c8945a0SNathan Whitehorn     return str;
2024c8945a0SNathan Whitehorn }
2034c8945a0SNathan Whitehorn 
2044c8945a0SNathan Whitehorn /*
2054c8945a0SNathan Whitehorn  * Extract the foreground, background and highlight values from an attribute
206*2a3e3873SBaptiste Daroussin  * represented as a string in one of two forms:
2074c8945a0SNathan Whitehorn  *
2084c8945a0SNathan Whitehorn  * "(foreground,background,highlight)"
209*2a3e3873SBaptiste Daroussin  " "xxxx_color"
2104c8945a0SNathan Whitehorn  */
2114c8945a0SNathan Whitehorn static int
2124c8945a0SNathan Whitehorn str_to_attr(char *str, int *fg, int *bg, int *hl)
2134c8945a0SNathan Whitehorn {
2144c8945a0SNathan Whitehorn     int i = 0, get_fg = 1;
2154c8945a0SNathan Whitehorn     unsigned j;
2164c8945a0SNathan Whitehorn     char tempstr[MAX_LEN + 1], *part;
217*2a3e3873SBaptiste Daroussin     size_t have;
2184c8945a0SNathan Whitehorn 
219*2a3e3873SBaptiste Daroussin     if (str[0] != '(' || lastch(str) != ')') {
220*2a3e3873SBaptiste Daroussin 	if ((i = find_color(str)) >= 0) {
221*2a3e3873SBaptiste Daroussin 	    *fg = dlg_color_table[i].fg;
222*2a3e3873SBaptiste Daroussin 	    *bg = dlg_color_table[i].bg;
223*2a3e3873SBaptiste Daroussin 	    *hl = dlg_color_table[i].hilite;
224*2a3e3873SBaptiste Daroussin 	    return 0;
225*2a3e3873SBaptiste Daroussin 	}
2264c8945a0SNathan Whitehorn 	return -1;		/* invalid representation */
227*2a3e3873SBaptiste Daroussin     }
2284c8945a0SNathan Whitehorn 
2294c8945a0SNathan Whitehorn     /* remove the parenthesis */
230*2a3e3873SBaptiste Daroussin     have = strlen(str);
231*2a3e3873SBaptiste Daroussin     if (have > MAX_LEN) {
232*2a3e3873SBaptiste Daroussin 	have = MAX_LEN - 1;
233*2a3e3873SBaptiste Daroussin     } else {
234*2a3e3873SBaptiste Daroussin 	have -= 2;
235*2a3e3873SBaptiste Daroussin     }
236*2a3e3873SBaptiste Daroussin     memcpy(tempstr, str + 1, have);
237*2a3e3873SBaptiste Daroussin     tempstr[have] = '\0';
2384c8945a0SNathan Whitehorn 
2394c8945a0SNathan Whitehorn     /* get foreground and background */
2404c8945a0SNathan Whitehorn 
2414c8945a0SNathan Whitehorn     while (1) {
2424c8945a0SNathan Whitehorn 	/* skip white space before fg/bg string */
2434c8945a0SNathan Whitehorn 	i = skip_whitespace(tempstr, i);
2444c8945a0SNathan Whitehorn 	if (tempstr[i] == '\0')
2454c8945a0SNathan Whitehorn 	    return -1;		/* invalid representation */
2464c8945a0SNathan Whitehorn 	part = tempstr + i;	/* set 'part' to start of fg/bg string */
2474c8945a0SNathan Whitehorn 
2484c8945a0SNathan Whitehorn 	/* find end of fg/bg string */
2494c8945a0SNathan Whitehorn 	while (!whitespace(tempstr[i]) && tempstr[i] != ','
2504c8945a0SNathan Whitehorn 	       && tempstr[i] != '\0')
2514c8945a0SNathan Whitehorn 	    i++;
2524c8945a0SNathan Whitehorn 
2534c8945a0SNathan Whitehorn 	if (tempstr[i] == '\0')
2544c8945a0SNathan Whitehorn 	    return -1;		/* invalid representation */
2554c8945a0SNathan Whitehorn 	else if (whitespace(tempstr[i])) {	/* not yet ',' */
2564c8945a0SNathan Whitehorn 	    tempstr[i++] = '\0';
2574c8945a0SNathan Whitehorn 
2584c8945a0SNathan Whitehorn 	    /* skip white space before ',' */
2594c8945a0SNathan Whitehorn 	    i = skip_whitespace(tempstr, i);
2604c8945a0SNathan Whitehorn 	    if (tempstr[i] != ',')
2614c8945a0SNathan Whitehorn 		return -1;	/* invalid representation */
2624c8945a0SNathan Whitehorn 	}
2634c8945a0SNathan Whitehorn 	tempstr[i++] = '\0';	/* skip the ',' */
2644c8945a0SNathan Whitehorn 	for (j = 0; j < COLOR_COUNT && dlg_strcmp(part, color_names[j].name);
2654c8945a0SNathan Whitehorn 	     j++) ;
2664c8945a0SNathan Whitehorn 	if (j == COLOR_COUNT)	/* invalid color name */
2674c8945a0SNathan Whitehorn 	    return -1;
2684c8945a0SNathan Whitehorn 	if (get_fg) {
2694c8945a0SNathan Whitehorn 	    *fg = color_names[j].value;
2704c8945a0SNathan Whitehorn 	    get_fg = 0;		/* next we have to get the background */
2714c8945a0SNathan Whitehorn 	} else {
2724c8945a0SNathan Whitehorn 	    *bg = color_names[j].value;
2734c8945a0SNathan Whitehorn 	    break;
2744c8945a0SNathan Whitehorn 	}
2754c8945a0SNathan Whitehorn     }				/* got foreground and background */
2764c8945a0SNathan Whitehorn 
2774c8945a0SNathan Whitehorn     /* get highlight */
2784c8945a0SNathan Whitehorn 
2794c8945a0SNathan Whitehorn     /* skip white space before highlight string */
2804c8945a0SNathan Whitehorn     i = skip_whitespace(tempstr, i);
2814c8945a0SNathan Whitehorn     if (tempstr[i] == '\0')
2824c8945a0SNathan Whitehorn 	return -1;		/* invalid representation */
2834c8945a0SNathan Whitehorn     part = tempstr + i;		/* set 'part' to start of highlight string */
2844c8945a0SNathan Whitehorn 
2854c8945a0SNathan Whitehorn     /* trim trailing white space from highlight string */
2864c8945a0SNathan Whitehorn     i = (int) strlen(part) - 1;
2874c8945a0SNathan Whitehorn     while (whitespace(part[i]) && i > 0)
2884c8945a0SNathan Whitehorn 	i--;
2894c8945a0SNathan Whitehorn     part[i + 1] = '\0';
2904c8945a0SNathan Whitehorn 
2914c8945a0SNathan Whitehorn     if (!dlg_strcmp(part, "ON"))
2924c8945a0SNathan Whitehorn 	*hl = TRUE;
2934c8945a0SNathan Whitehorn     else if (!dlg_strcmp(part, "OFF"))
2944c8945a0SNathan Whitehorn 	*hl = FALSE;
2954c8945a0SNathan Whitehorn     else
2964c8945a0SNathan Whitehorn 	return -1;		/* invalid highlight value */
2974c8945a0SNathan Whitehorn 
2984c8945a0SNathan Whitehorn     return 0;
2994c8945a0SNathan Whitehorn }
3004c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
3014c8945a0SNathan Whitehorn 
3024c8945a0SNathan Whitehorn /*
3034c8945a0SNathan Whitehorn  * Check if the line begins with a special keyword; if so, return true while
3044c8945a0SNathan Whitehorn  * pointing params to its parameters.
3054c8945a0SNathan Whitehorn  */
3064c8945a0SNathan Whitehorn static int
3074c8945a0SNathan Whitehorn begins_with(char *line, const char *keyword, char **params)
3084c8945a0SNathan Whitehorn {
3094c8945a0SNathan Whitehorn     int i = skip_whitespace(line, 0);
3104c8945a0SNathan Whitehorn     int j = skip_keyword(line, i);
3114c8945a0SNathan Whitehorn 
3124c8945a0SNathan Whitehorn     if ((j - i) == (int) strlen(keyword)) {
3134c8945a0SNathan Whitehorn 	char save = line[j];
3144c8945a0SNathan Whitehorn 	line[j] = 0;
3154c8945a0SNathan Whitehorn 	if (!dlg_strcmp(keyword, line + i)) {
3164c8945a0SNathan Whitehorn 	    *params = line + skip_whitespace(line, j + 1);
3174c8945a0SNathan Whitehorn 	    return 1;
3184c8945a0SNathan Whitehorn 	}
3194c8945a0SNathan Whitehorn 	line[j] = save;
3204c8945a0SNathan Whitehorn     }
3214c8945a0SNathan Whitehorn 
3224c8945a0SNathan Whitehorn     return 0;
3234c8945a0SNathan Whitehorn }
3244c8945a0SNathan Whitehorn 
3254c8945a0SNathan Whitehorn /*
3264c8945a0SNathan Whitehorn  * Parse a line in the configuration file
3274c8945a0SNathan Whitehorn  *
3284c8945a0SNathan Whitehorn  * Each line is of the form:  "variable = value". On exit, 'var' will contain
3294c8945a0SNathan Whitehorn  * the variable name, and 'value' will contain the value string.
3304c8945a0SNathan Whitehorn  *
3314c8945a0SNathan Whitehorn  * Return values:
3324c8945a0SNathan Whitehorn  *
3334c8945a0SNathan Whitehorn  * LINE_EMPTY   - line is blank or comment
3344c8945a0SNathan Whitehorn  * LINE_EQUALS  - line contains "variable = value"
3354c8945a0SNathan Whitehorn  * LINE_ERROR   - syntax error in line
3364c8945a0SNathan Whitehorn  */
3374c8945a0SNathan Whitehorn static PARSE_LINE
3384c8945a0SNathan Whitehorn parse_line(char *line, char **var, char **value)
3394c8945a0SNathan Whitehorn {
3404c8945a0SNathan Whitehorn     int i = 0;
3414c8945a0SNathan Whitehorn 
3424c8945a0SNathan Whitehorn     /* ignore white space at beginning of line */
3434c8945a0SNathan Whitehorn     i = skip_whitespace(line, i);
3444c8945a0SNathan Whitehorn 
3454c8945a0SNathan Whitehorn     if (line[i] == '\0')	/* line is blank */
3464c8945a0SNathan Whitehorn 	return LINE_EMPTY;
3474c8945a0SNathan Whitehorn     else if (line[i] == '#')	/* line is comment */
3484c8945a0SNathan Whitehorn 	return LINE_EMPTY;
3494c8945a0SNathan Whitehorn     else if (line[i] == '=')	/* variable names cannot start with a '=' */
3504c8945a0SNathan Whitehorn 	return LINE_ERROR;
3514c8945a0SNathan Whitehorn 
3524c8945a0SNathan Whitehorn     /* set 'var' to variable name */
3534c8945a0SNathan Whitehorn     *var = line + i++;		/* skip to next character */
3544c8945a0SNathan Whitehorn 
3554c8945a0SNathan Whitehorn     /* find end of variable name */
3564c8945a0SNathan Whitehorn     while (!whitespace(line[i]) && line[i] != '=' && line[i] != '\0')
3574c8945a0SNathan Whitehorn 	i++;
3584c8945a0SNathan Whitehorn 
3594c8945a0SNathan Whitehorn     if (line[i] == '\0')	/* syntax error */
3604c8945a0SNathan Whitehorn 	return LINE_ERROR;
3614c8945a0SNathan Whitehorn     else if (line[i] == '=')
3624c8945a0SNathan Whitehorn 	line[i++] = '\0';
3634c8945a0SNathan Whitehorn     else {
3644c8945a0SNathan Whitehorn 	line[i++] = '\0';
3654c8945a0SNathan Whitehorn 
3664c8945a0SNathan Whitehorn 	/* skip white space before '=' */
3674c8945a0SNathan Whitehorn 	i = skip_whitespace(line, i);
3684c8945a0SNathan Whitehorn 
3694c8945a0SNathan Whitehorn 	if (line[i] != '=')	/* syntax error */
3704c8945a0SNathan Whitehorn 	    return LINE_ERROR;
3714c8945a0SNathan Whitehorn 	else
3724c8945a0SNathan Whitehorn 	    i++;		/* skip the '=' */
3734c8945a0SNathan Whitehorn     }
3744c8945a0SNathan Whitehorn 
3754c8945a0SNathan Whitehorn     /* skip white space after '=' */
3764c8945a0SNathan Whitehorn     i = skip_whitespace(line, i);
3774c8945a0SNathan Whitehorn 
3784c8945a0SNathan Whitehorn     if (line[i] == '\0')
3794c8945a0SNathan Whitehorn 	return LINE_ERROR;
3804c8945a0SNathan Whitehorn     else
3814c8945a0SNathan Whitehorn 	*value = line + i;	/* set 'value' to value string */
3824c8945a0SNathan Whitehorn 
3834c8945a0SNathan Whitehorn     /* trim trailing white space from 'value' */
3844c8945a0SNathan Whitehorn     i = (int) strlen(*value) - 1;
3854c8945a0SNathan Whitehorn     while (whitespace((*value)[i]) && i > 0)
3864c8945a0SNathan Whitehorn 	i--;
3874c8945a0SNathan Whitehorn     (*value)[i + 1] = '\0';
3884c8945a0SNathan Whitehorn 
3894c8945a0SNathan Whitehorn     return LINE_EQUALS;		/* no syntax error in line */
3904c8945a0SNathan Whitehorn }
3914c8945a0SNathan Whitehorn 
3924c8945a0SNathan Whitehorn /*
3934c8945a0SNathan Whitehorn  * Create the configuration file
3944c8945a0SNathan Whitehorn  */
3954c8945a0SNathan Whitehorn void
3964c8945a0SNathan Whitehorn dlg_create_rc(const char *filename)
3974c8945a0SNathan Whitehorn {
3984c8945a0SNathan Whitehorn     unsigned i;
3994c8945a0SNathan Whitehorn     FILE *rc_file;
4004c8945a0SNathan Whitehorn 
4014c8945a0SNathan Whitehorn     if ((rc_file = fopen(filename, "wt")) == NULL)
4024c8945a0SNathan Whitehorn 	dlg_exiterr("Error opening file for writing in dlg_create_rc().");
4034c8945a0SNathan Whitehorn 
4044c8945a0SNathan Whitehorn     fprintf(rc_file, "#\n\
4054c8945a0SNathan Whitehorn # Run-time configuration file for dialog\n\
4064c8945a0SNathan Whitehorn #\n\
4074c8945a0SNathan Whitehorn # Automatically generated by \"dialog --create-rc <file>\"\n\
4084c8945a0SNathan Whitehorn #\n\
4094c8945a0SNathan Whitehorn #\n\
4104c8945a0SNathan Whitehorn # Types of values:\n\
4114c8945a0SNathan Whitehorn #\n\
4124c8945a0SNathan Whitehorn # Number     -  <number>\n\
4134c8945a0SNathan Whitehorn # String     -  \"string\"\n\
4144c8945a0SNathan Whitehorn # Boolean    -  <ON|OFF>\n"
4154c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4164c8945a0SNathan Whitehorn 	    "\
4174c8945a0SNathan Whitehorn # Attribute  -  (foreground,background,highlight?)\n"
4184c8945a0SNathan Whitehorn #endif
4194c8945a0SNathan Whitehorn 	);
4204c8945a0SNathan Whitehorn 
4214c8945a0SNathan Whitehorn     /* Print an entry for each configuration variable */
4224c8945a0SNathan Whitehorn     for (i = 0; i < VAR_COUNT; i++) {
4234c8945a0SNathan Whitehorn 	fprintf(rc_file, "\n# %s\n", vars[i].comment);
4244c8945a0SNathan Whitehorn 	switch (vars[i].type) {
4254c8945a0SNathan Whitehorn 	case VAL_INT:
4264c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %d\n", vars[i].name,
4274c8945a0SNathan Whitehorn 		    *((int *) vars[i].var));
4284c8945a0SNathan Whitehorn 	    break;
4294c8945a0SNathan Whitehorn 	case VAL_STR:
4304c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = \"%s\"\n", vars[i].name,
4314c8945a0SNathan Whitehorn 		    (char *) vars[i].var);
4324c8945a0SNathan Whitehorn 	    break;
4334c8945a0SNathan Whitehorn 	case VAL_BOOL:
4344c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %s\n", vars[i].name,
4354c8945a0SNathan Whitehorn 		    *((bool *) vars[i].var) ? "ON" : "OFF");
4364c8945a0SNathan Whitehorn 	    break;
4374c8945a0SNathan Whitehorn 	}
4384c8945a0SNathan Whitehorn     }
4394c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
4404c8945a0SNathan Whitehorn     for (i = 0; i < (unsigned) dlg_color_count(); ++i) {
4414c8945a0SNathan Whitehorn 	char buffer[MAX_LEN + 1];
442*2a3e3873SBaptiste Daroussin 	unsigned j;
443*2a3e3873SBaptiste Daroussin 	bool repeat = FALSE;
4444c8945a0SNathan Whitehorn 
4454c8945a0SNathan Whitehorn 	fprintf(rc_file, "\n# %s\n", dlg_color_table[i].comment);
446*2a3e3873SBaptiste Daroussin 	for (j = 0; j != i; ++j) {
447*2a3e3873SBaptiste Daroussin 	    if (dlg_color_table[i].fg == dlg_color_table[j].fg
448*2a3e3873SBaptiste Daroussin 		&& dlg_color_table[i].bg == dlg_color_table[j].bg
449*2a3e3873SBaptiste Daroussin 		&& dlg_color_table[i].hilite == dlg_color_table[j].hilite) {
450*2a3e3873SBaptiste Daroussin 		fprintf(rc_file, "%s = %s\n",
451*2a3e3873SBaptiste Daroussin 			dlg_color_table[i].name,
452*2a3e3873SBaptiste Daroussin 			dlg_color_table[j].name);
453*2a3e3873SBaptiste Daroussin 		repeat = TRUE;
454*2a3e3873SBaptiste Daroussin 		break;
455*2a3e3873SBaptiste Daroussin 	    }
456*2a3e3873SBaptiste Daroussin 	}
457*2a3e3873SBaptiste Daroussin 
458*2a3e3873SBaptiste Daroussin 	if (!repeat) {
4594c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %s\n", dlg_color_table[i].name,
4604c8945a0SNathan Whitehorn 		    attr_to_str(buffer,
4614c8945a0SNathan Whitehorn 				dlg_color_table[i].fg,
4624c8945a0SNathan Whitehorn 				dlg_color_table[i].bg,
4634c8945a0SNathan Whitehorn 				dlg_color_table[i].hilite));
4644c8945a0SNathan Whitehorn 	}
465*2a3e3873SBaptiste Daroussin     }
4664c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
4674c8945a0SNathan Whitehorn     dlg_dump_keys(rc_file);
4684c8945a0SNathan Whitehorn 
4694c8945a0SNathan Whitehorn     (void) fclose(rc_file);
4704c8945a0SNathan Whitehorn }
4714c8945a0SNathan Whitehorn 
4724c8945a0SNathan Whitehorn /*
4734c8945a0SNathan Whitehorn  * Parse the configuration file and set up variables
4744c8945a0SNathan Whitehorn  */
4754c8945a0SNathan Whitehorn int
4764c8945a0SNathan Whitehorn dlg_parse_rc(void)
4774c8945a0SNathan Whitehorn {
4784c8945a0SNathan Whitehorn     int i;
4794c8945a0SNathan Whitehorn     int l = 1;
4804c8945a0SNathan Whitehorn     PARSE_LINE parse;
4814c8945a0SNathan Whitehorn     char str[MAX_LEN + 1];
4824c8945a0SNathan Whitehorn     char *var;
4834c8945a0SNathan Whitehorn     char *value;
4844c8945a0SNathan Whitehorn     char *tempptr;
4854c8945a0SNathan Whitehorn     int result = 0;
4864c8945a0SNathan Whitehorn     FILE *rc_file = 0;
4874c8945a0SNathan Whitehorn     char *params;
4884c8945a0SNathan Whitehorn 
4894c8945a0SNathan Whitehorn     /*
4904c8945a0SNathan Whitehorn      *  At startup, dialog determines the settings to use as follows:
4914c8945a0SNathan Whitehorn      *
4924c8945a0SNathan Whitehorn      *  a) if the environment variable $DIALOGRC is set, its value determines
4934c8945a0SNathan Whitehorn      *     the name of the configuration file.
4944c8945a0SNathan Whitehorn      *
4954c8945a0SNathan Whitehorn      *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
4964c8945a0SNathan Whitehorn      *     as the configuration file.
4974c8945a0SNathan Whitehorn      *
4984c8945a0SNathan Whitehorn      *  c) if the file in (b) can't be found, try using the GLOBALRC file.
4994c8945a0SNathan Whitehorn      *     Usually this will be /etc/dialogrc.
5004c8945a0SNathan Whitehorn      *
5014c8945a0SNathan Whitehorn      *  d) if the file in (c) cannot be found, use the compiled-in defaults.
5024c8945a0SNathan Whitehorn      */
5034c8945a0SNathan Whitehorn 
5044c8945a0SNathan Whitehorn     /* try step (a) */
5054c8945a0SNathan Whitehorn     if ((tempptr = getenv("DIALOGRC")) != NULL)
5064c8945a0SNathan Whitehorn 	rc_file = fopen(tempptr, "rt");
5074c8945a0SNathan Whitehorn 
5084c8945a0SNathan Whitehorn     if (rc_file == NULL) {	/* step (a) failed? */
5094c8945a0SNathan Whitehorn 	/* try step (b) */
5104c8945a0SNathan Whitehorn 	if ((tempptr = getenv("HOME")) != NULL
5114c8945a0SNathan Whitehorn 	    && strlen(tempptr) < MAX_LEN - (sizeof(DIALOGRC) + 3)) {
5124c8945a0SNathan Whitehorn 	    if (tempptr[0] == '\0' || lastch(tempptr) == '/')
5134c8945a0SNathan Whitehorn 		sprintf(str, "%s%s", tempptr, DIALOGRC);
5144c8945a0SNathan Whitehorn 	    else
5154c8945a0SNathan Whitehorn 		sprintf(str, "%s/%s", tempptr, DIALOGRC);
516682c9e0fSNathan Whitehorn 	    rc_file = fopen(tempptr = str, "rt");
5174c8945a0SNathan Whitehorn 	}
5184c8945a0SNathan Whitehorn     }
5194c8945a0SNathan Whitehorn 
5204c8945a0SNathan Whitehorn     if (rc_file == NULL) {	/* step (b) failed? */
5214c8945a0SNathan Whitehorn 	/* try step (c) */
5224c8945a0SNathan Whitehorn 	strcpy(str, GLOBALRC);
523682c9e0fSNathan Whitehorn 	if ((rc_file = fopen(tempptr = str, "rt")) == NULL)
5244c8945a0SNathan Whitehorn 	    return 0;		/* step (c) failed, use default values */
5254c8945a0SNathan Whitehorn     }
5264c8945a0SNathan Whitehorn 
527682c9e0fSNathan Whitehorn     DLG_TRACE(("opened rc file \"%s\"\n", tempptr));
5284c8945a0SNathan Whitehorn     /* Scan each line and set variables */
5294c8945a0SNathan Whitehorn     while ((result == 0) && (fgets(str, MAX_LEN, rc_file) != NULL)) {
530682c9e0fSNathan Whitehorn 	DLG_TRACE(("rc:%s", str));
5314c8945a0SNathan Whitehorn 	if (*str == '\0' || lastch(str) != '\n') {
5324c8945a0SNathan Whitehorn 	    /* ignore rest of file if line too long */
5334c8945a0SNathan Whitehorn 	    fprintf(stderr, "\nParse error: line %d of configuration"
5344c8945a0SNathan Whitehorn 		    " file too long.\n", l);
5354c8945a0SNathan Whitehorn 	    result = -1;	/* parse aborted */
5364c8945a0SNathan Whitehorn 	    break;
5374c8945a0SNathan Whitehorn 	}
5384c8945a0SNathan Whitehorn 
5394c8945a0SNathan Whitehorn 	lastch(str) = '\0';
5404c8945a0SNathan Whitehorn 	if (begins_with(str, "bindkey", &params)) {
541*2a3e3873SBaptiste Daroussin 	    if (!dlg_parse_bindkey(params)) {
542*2a3e3873SBaptiste Daroussin 		fprintf(stderr, "\nParse error: line %d of configuration\n", l);
543*2a3e3873SBaptiste Daroussin 		result = -1;
544*2a3e3873SBaptiste Daroussin 	    }
5454c8945a0SNathan Whitehorn 	    continue;
5464c8945a0SNathan Whitehorn 	}
5474c8945a0SNathan Whitehorn 	parse = parse_line(str, &var, &value);	/* parse current line */
5484c8945a0SNathan Whitehorn 
5494c8945a0SNathan Whitehorn 	switch (parse) {
5504c8945a0SNathan Whitehorn 	case LINE_EMPTY:	/* ignore blank lines and comments */
5514c8945a0SNathan Whitehorn 	    break;
5524c8945a0SNathan Whitehorn 	case LINE_EQUALS:
5534c8945a0SNathan Whitehorn 	    /* search table for matching config variable name */
5544c8945a0SNathan Whitehorn 	    if ((i = find_vars(var)) >= 0) {
5554c8945a0SNathan Whitehorn 		switch (vars[i].type) {
5564c8945a0SNathan Whitehorn 		case VAL_INT:
5574c8945a0SNathan Whitehorn 		    *((int *) vars[i].var) = atoi(value);
5584c8945a0SNathan Whitehorn 		    break;
5594c8945a0SNathan Whitehorn 		case VAL_STR:
5604c8945a0SNathan Whitehorn 		    if (!isquote(value[0]) || !isquote(lastch(value))
5614c8945a0SNathan Whitehorn 			|| strlen(value) < 2) {
5624c8945a0SNathan Whitehorn 			fprintf(stderr, "\nParse error: string value "
5634c8945a0SNathan Whitehorn 				"expected at line %d of configuration "
5644c8945a0SNathan Whitehorn 				"file.\n", l);
5654c8945a0SNathan Whitehorn 			result = -1;	/* parse aborted */
5664c8945a0SNathan Whitehorn 		    } else {
5674c8945a0SNathan Whitehorn 			/* remove the (") quotes */
5684c8945a0SNathan Whitehorn 			value++;
5694c8945a0SNathan Whitehorn 			lastch(value) = '\0';
5704c8945a0SNathan Whitehorn 			strcpy((char *) vars[i].var, value);
5714c8945a0SNathan Whitehorn 		    }
5724c8945a0SNathan Whitehorn 		    break;
5734c8945a0SNathan Whitehorn 		case VAL_BOOL:
5744c8945a0SNathan Whitehorn 		    if (!dlg_strcmp(value, "ON"))
5754c8945a0SNathan Whitehorn 			*((bool *) vars[i].var) = TRUE;
5764c8945a0SNathan Whitehorn 		    else if (!dlg_strcmp(value, "OFF"))
5774c8945a0SNathan Whitehorn 			*((bool *) vars[i].var) = FALSE;
5784c8945a0SNathan Whitehorn 		    else {
5794c8945a0SNathan Whitehorn 			fprintf(stderr, "\nParse error: boolean value "
5804c8945a0SNathan Whitehorn 				"expected at line %d of configuration "
5814c8945a0SNathan Whitehorn 				"file (found %s).\n", l, value);
5824c8945a0SNathan Whitehorn 			result = -1;	/* parse aborted */
5834c8945a0SNathan Whitehorn 		    }
5844c8945a0SNathan Whitehorn 		    break;
5854c8945a0SNathan Whitehorn 		}
5864c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
5874c8945a0SNathan Whitehorn 	    } else if ((i = find_color(var)) >= 0) {
5884c8945a0SNathan Whitehorn 		int fg = 0;
5894c8945a0SNathan Whitehorn 		int bg = 0;
5904c8945a0SNathan Whitehorn 		int hl = 0;
5914c8945a0SNathan Whitehorn 		if (str_to_attr(value, &fg, &bg, &hl) == -1) {
5924c8945a0SNathan Whitehorn 		    fprintf(stderr, "\nParse error: attribute "
5934c8945a0SNathan Whitehorn 			    "value expected at line %d of configuration "
5944c8945a0SNathan Whitehorn 			    "file.\n", l);
5954c8945a0SNathan Whitehorn 		    result = -1;	/* parse aborted */
5964c8945a0SNathan Whitehorn 		} else {
5974c8945a0SNathan Whitehorn 		    dlg_color_table[i].fg = fg;
5984c8945a0SNathan Whitehorn 		    dlg_color_table[i].bg = bg;
5994c8945a0SNathan Whitehorn 		    dlg_color_table[i].hilite = hl;
6004c8945a0SNathan Whitehorn 		}
6014c8945a0SNathan Whitehorn 	    } else {
6024c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
6034c8945a0SNathan Whitehorn 		fprintf(stderr, "\nParse error: unknown variable "
6044c8945a0SNathan Whitehorn 			"at line %d of configuration file:\n\t%s\n", l, var);
6054c8945a0SNathan Whitehorn 		result = -1;	/* parse aborted */
6064c8945a0SNathan Whitehorn 	    }
6074c8945a0SNathan Whitehorn 	    break;
6084c8945a0SNathan Whitehorn 	case LINE_ERROR:
6094c8945a0SNathan Whitehorn 	    fprintf(stderr, "\nParse error: syntax error at line %d of "
6104c8945a0SNathan Whitehorn 		    "configuration file.\n", l);
6114c8945a0SNathan Whitehorn 	    result = -1;	/* parse aborted */
6124c8945a0SNathan Whitehorn 	    break;
6134c8945a0SNathan Whitehorn 	}
6144c8945a0SNathan Whitehorn 	l++;			/* next line */
6154c8945a0SNathan Whitehorn     }
6164c8945a0SNathan Whitehorn 
6174c8945a0SNathan Whitehorn     (void) fclose(rc_file);
6184c8945a0SNathan Whitehorn     return result;
6194c8945a0SNathan Whitehorn }
620