xref: /freebsd/contrib/dialog/rc.c (revision 4c8945a06b01a5c8122cdeb402af36bb46a06acc)
1*4c8945a0SNathan Whitehorn /*
2*4c8945a0SNathan Whitehorn  *  $Id: rc.c,v 1.45 2010/01/18 10:28:16 tom Exp $
3*4c8945a0SNathan Whitehorn  *
4*4c8945a0SNathan Whitehorn  *  rc.c -- routines for processing the configuration file
5*4c8945a0SNathan Whitehorn  *
6*4c8945a0SNathan Whitehorn  *  Copyright 2000-2008,2010	Thomas E. Dickey
7*4c8945a0SNathan Whitehorn  *
8*4c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
9*4c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
10*4c8945a0SNathan Whitehorn  *  as published by the Free Software Foundation.
11*4c8945a0SNathan Whitehorn  *
12*4c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
13*4c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
14*4c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*4c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
16*4c8945a0SNathan Whitehorn  *
17*4c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
18*4c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
19*4c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
20*4c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
21*4c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
22*4c8945a0SNathan Whitehorn  *
23*4c8945a0SNathan Whitehorn  *  An earlier version of this program lists as authors
24*4c8945a0SNathan Whitehorn  *	Savio Lam (lam836@cs.cuhk.hk)
25*4c8945a0SNathan Whitehorn  */
26*4c8945a0SNathan Whitehorn 
27*4c8945a0SNathan Whitehorn #include <dialog.h>
28*4c8945a0SNathan Whitehorn 
29*4c8945a0SNathan Whitehorn #include <dlg_keys.h>
30*4c8945a0SNathan Whitehorn 
31*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
32*4c8945a0SNathan Whitehorn #include <dlg_colors.h>
33*4c8945a0SNathan Whitehorn 
34*4c8945a0SNathan Whitehorn /*
35*4c8945a0SNathan Whitehorn  * For matching color names with color values
36*4c8945a0SNathan Whitehorn  */
37*4c8945a0SNathan Whitehorn static const color_names_st color_names[] =
38*4c8945a0SNathan Whitehorn {
39*4c8945a0SNathan Whitehorn #ifdef HAVE_USE_DEFAULT_COLORS
40*4c8945a0SNathan Whitehorn     {"DEFAULT", -1},
41*4c8945a0SNathan Whitehorn #endif
42*4c8945a0SNathan Whitehorn     {"BLACK", COLOR_BLACK},
43*4c8945a0SNathan Whitehorn     {"RED", COLOR_RED},
44*4c8945a0SNathan Whitehorn     {"GREEN", COLOR_GREEN},
45*4c8945a0SNathan Whitehorn     {"YELLOW", COLOR_YELLOW},
46*4c8945a0SNathan Whitehorn     {"BLUE", COLOR_BLUE},
47*4c8945a0SNathan Whitehorn     {"MAGENTA", COLOR_MAGENTA},
48*4c8945a0SNathan Whitehorn     {"CYAN", COLOR_CYAN},
49*4c8945a0SNathan Whitehorn     {"WHITE", COLOR_WHITE},
50*4c8945a0SNathan Whitehorn };				/* color names */
51*4c8945a0SNathan Whitehorn #define COLOR_COUNT	(sizeof(color_names) / sizeof(color_names[0]))
52*4c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
53*4c8945a0SNathan Whitehorn 
54*4c8945a0SNathan Whitehorn #define GLOBALRC "/etc/dialogrc"
55*4c8945a0SNathan Whitehorn #define DIALOGRC ".dialogrc"
56*4c8945a0SNathan Whitehorn 
57*4c8945a0SNathan Whitehorn /* Types of values */
58*4c8945a0SNathan Whitehorn #define VAL_INT  0
59*4c8945a0SNathan Whitehorn #define VAL_STR  1
60*4c8945a0SNathan Whitehorn #define VAL_BOOL 2
61*4c8945a0SNathan Whitehorn 
62*4c8945a0SNathan Whitehorn /* Type of line in configuration file */
63*4c8945a0SNathan Whitehorn typedef enum {
64*4c8945a0SNathan Whitehorn     LINE_ERROR = -1,
65*4c8945a0SNathan Whitehorn     LINE_EQUALS,
66*4c8945a0SNathan Whitehorn     LINE_EMPTY
67*4c8945a0SNathan Whitehorn } PARSE_LINE;
68*4c8945a0SNathan Whitehorn 
69*4c8945a0SNathan Whitehorn /* number of configuration variables */
70*4c8945a0SNathan Whitehorn #define VAR_COUNT        (sizeof(vars) / sizeof(vars_st))
71*4c8945a0SNathan Whitehorn 
72*4c8945a0SNathan Whitehorn /* check if character is white space */
73*4c8945a0SNathan Whitehorn #define whitespace(c)    (c == ' ' || c == TAB)
74*4c8945a0SNathan Whitehorn 
75*4c8945a0SNathan Whitehorn /* check if character is string quoting characters */
76*4c8945a0SNathan Whitehorn #define isquote(c)       (c == '"' || c == '\'')
77*4c8945a0SNathan Whitehorn 
78*4c8945a0SNathan Whitehorn /* get last character of string */
79*4c8945a0SNathan Whitehorn #define lastch(str)      str[strlen(str)-1]
80*4c8945a0SNathan Whitehorn 
81*4c8945a0SNathan Whitehorn /*
82*4c8945a0SNathan Whitehorn  * Configuration variables
83*4c8945a0SNathan Whitehorn  */
84*4c8945a0SNathan Whitehorn typedef struct {
85*4c8945a0SNathan Whitehorn     const char *name;		/* name of configuration variable as in DIALOGRC */
86*4c8945a0SNathan Whitehorn     void *var;			/* address of actual variable to change */
87*4c8945a0SNathan Whitehorn     int type;			/* type of value */
88*4c8945a0SNathan Whitehorn     const char *comment;	/* comment to put in "rc" file */
89*4c8945a0SNathan Whitehorn } vars_st;
90*4c8945a0SNathan Whitehorn 
91*4c8945a0SNathan Whitehorn /*
92*4c8945a0SNathan Whitehorn  * This table should contain only references to dialog_state, since dialog_vars
93*4c8945a0SNathan Whitehorn  * is reset specially in dialog.c before each widget.
94*4c8945a0SNathan Whitehorn  */
95*4c8945a0SNathan Whitehorn static const vars_st vars[] =
96*4c8945a0SNathan Whitehorn {
97*4c8945a0SNathan Whitehorn     {"aspect",
98*4c8945a0SNathan Whitehorn      &dialog_state.aspect_ratio,
99*4c8945a0SNathan Whitehorn      VAL_INT,
100*4c8945a0SNathan Whitehorn      "Set aspect-ration."},
101*4c8945a0SNathan Whitehorn 
102*4c8945a0SNathan Whitehorn     {"separate_widget",
103*4c8945a0SNathan Whitehorn      &dialog_state.separate_str,
104*4c8945a0SNathan Whitehorn      VAL_STR,
105*4c8945a0SNathan Whitehorn      "Set separator (for multiple widgets output)."},
106*4c8945a0SNathan Whitehorn 
107*4c8945a0SNathan Whitehorn     {"tab_len",
108*4c8945a0SNathan Whitehorn      &dialog_state.tab_len,
109*4c8945a0SNathan Whitehorn      VAL_INT,
110*4c8945a0SNathan Whitehorn      "Set tab-length (for textbox tab-conversion)."},
111*4c8945a0SNathan Whitehorn 
112*4c8945a0SNathan Whitehorn     {"visit_items",
113*4c8945a0SNathan Whitehorn      &dialog_state.visit_items,
114*4c8945a0SNathan Whitehorn      VAL_BOOL,
115*4c8945a0SNathan Whitehorn      "Make tab-traversal for checklist, etc., include the list."},
116*4c8945a0SNathan Whitehorn 
117*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
118*4c8945a0SNathan Whitehorn     {"use_shadow",
119*4c8945a0SNathan Whitehorn      &dialog_state.use_shadow,
120*4c8945a0SNathan Whitehorn      VAL_BOOL,
121*4c8945a0SNathan Whitehorn      "Shadow dialog boxes? This also turns on color."},
122*4c8945a0SNathan Whitehorn 
123*4c8945a0SNathan Whitehorn     {"use_colors",
124*4c8945a0SNathan Whitehorn      &dialog_state.use_colors,
125*4c8945a0SNathan Whitehorn      VAL_BOOL,
126*4c8945a0SNathan Whitehorn      "Turn color support ON or OFF"},
127*4c8945a0SNathan Whitehorn #endif				/* HAVE_COLOR */
128*4c8945a0SNathan Whitehorn };				/* vars */
129*4c8945a0SNathan Whitehorn 
130*4c8945a0SNathan Whitehorn static int
131*4c8945a0SNathan Whitehorn skip_whitespace(char *str, int n)
132*4c8945a0SNathan Whitehorn {
133*4c8945a0SNathan Whitehorn     while (whitespace(str[n]) && str[n] != '\0')
134*4c8945a0SNathan Whitehorn 	n++;
135*4c8945a0SNathan Whitehorn     return n;
136*4c8945a0SNathan Whitehorn }
137*4c8945a0SNathan Whitehorn 
138*4c8945a0SNathan Whitehorn static int
139*4c8945a0SNathan Whitehorn skip_keyword(char *str, int n)
140*4c8945a0SNathan Whitehorn {
141*4c8945a0SNathan Whitehorn     while (isalnum(UCH(str[n])) && str[n] != '\0')
142*4c8945a0SNathan Whitehorn 	n++;
143*4c8945a0SNathan Whitehorn     return n;
144*4c8945a0SNathan Whitehorn }
145*4c8945a0SNathan Whitehorn 
146*4c8945a0SNathan Whitehorn static int
147*4c8945a0SNathan Whitehorn find_vars(char *name)
148*4c8945a0SNathan Whitehorn {
149*4c8945a0SNathan Whitehorn     int result = -1;
150*4c8945a0SNathan Whitehorn     unsigned i;
151*4c8945a0SNathan Whitehorn 
152*4c8945a0SNathan Whitehorn     for (i = 0; i < VAR_COUNT; i++) {
153*4c8945a0SNathan Whitehorn 	if (dlg_strcmp(vars[i].name, name) == 0) {
154*4c8945a0SNathan Whitehorn 	    result = (int) i;
155*4c8945a0SNathan Whitehorn 	    break;
156*4c8945a0SNathan Whitehorn 	}
157*4c8945a0SNathan Whitehorn     }
158*4c8945a0SNathan Whitehorn     return result;
159*4c8945a0SNathan Whitehorn }
160*4c8945a0SNathan Whitehorn 
161*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
162*4c8945a0SNathan Whitehorn static int
163*4c8945a0SNathan Whitehorn find_color(char *name)
164*4c8945a0SNathan Whitehorn {
165*4c8945a0SNathan Whitehorn     int result = -1;
166*4c8945a0SNathan Whitehorn     int i;
167*4c8945a0SNathan Whitehorn     int limit = dlg_color_count();
168*4c8945a0SNathan Whitehorn 
169*4c8945a0SNathan Whitehorn     for (i = 0; i < limit; i++) {
170*4c8945a0SNathan Whitehorn 	if (dlg_strcmp(dlg_color_table[i].name, name) == 0) {
171*4c8945a0SNathan Whitehorn 	    result = i;
172*4c8945a0SNathan Whitehorn 	    break;
173*4c8945a0SNathan Whitehorn 	}
174*4c8945a0SNathan Whitehorn     }
175*4c8945a0SNathan Whitehorn     return result;
176*4c8945a0SNathan Whitehorn }
177*4c8945a0SNathan Whitehorn 
178*4c8945a0SNathan Whitehorn /*
179*4c8945a0SNathan Whitehorn  * Convert an attribute to a string representation like this:
180*4c8945a0SNathan Whitehorn  *
181*4c8945a0SNathan Whitehorn  * "(foreground,background,highlight)"
182*4c8945a0SNathan Whitehorn  */
183*4c8945a0SNathan Whitehorn static char *
184*4c8945a0SNathan Whitehorn attr_to_str(char *str, int fg, int bg, int hl)
185*4c8945a0SNathan Whitehorn {
186*4c8945a0SNathan Whitehorn     int i;
187*4c8945a0SNathan Whitehorn 
188*4c8945a0SNathan Whitehorn     strcpy(str, "(");
189*4c8945a0SNathan Whitehorn     /* foreground */
190*4c8945a0SNathan Whitehorn     for (i = 0; fg != color_names[i].value; i++) ;
191*4c8945a0SNathan Whitehorn     strcat(str, color_names[i].name);
192*4c8945a0SNathan Whitehorn     strcat(str, ",");
193*4c8945a0SNathan Whitehorn 
194*4c8945a0SNathan Whitehorn     /* background */
195*4c8945a0SNathan Whitehorn     for (i = 0; bg != color_names[i].value; i++) ;
196*4c8945a0SNathan Whitehorn     strcat(str, color_names[i].name);
197*4c8945a0SNathan Whitehorn 
198*4c8945a0SNathan Whitehorn     /* highlight */
199*4c8945a0SNathan Whitehorn     strcat(str, hl ? ",ON)" : ",OFF)");
200*4c8945a0SNathan Whitehorn 
201*4c8945a0SNathan Whitehorn     return str;
202*4c8945a0SNathan Whitehorn }
203*4c8945a0SNathan Whitehorn 
204*4c8945a0SNathan Whitehorn /*
205*4c8945a0SNathan Whitehorn  * Extract the foreground, background and highlight values from an attribute
206*4c8945a0SNathan Whitehorn  * represented as a string in this form:
207*4c8945a0SNathan Whitehorn  *
208*4c8945a0SNathan Whitehorn  * "(foreground,background,highlight)"
209*4c8945a0SNathan Whitehorn  */
210*4c8945a0SNathan Whitehorn static int
211*4c8945a0SNathan Whitehorn str_to_attr(char *str, int *fg, int *bg, int *hl)
212*4c8945a0SNathan Whitehorn {
213*4c8945a0SNathan Whitehorn     int i = 0, get_fg = 1;
214*4c8945a0SNathan Whitehorn     unsigned j;
215*4c8945a0SNathan Whitehorn     char tempstr[MAX_LEN + 1], *part;
216*4c8945a0SNathan Whitehorn 
217*4c8945a0SNathan Whitehorn     if (str[0] != '(' || lastch(str) != ')')
218*4c8945a0SNathan Whitehorn 	return -1;		/* invalid representation */
219*4c8945a0SNathan Whitehorn 
220*4c8945a0SNathan Whitehorn     /* remove the parenthesis */
221*4c8945a0SNathan Whitehorn     strcpy(tempstr, str + 1);
222*4c8945a0SNathan Whitehorn     lastch(tempstr) = '\0';
223*4c8945a0SNathan Whitehorn 
224*4c8945a0SNathan Whitehorn     /* get foreground and background */
225*4c8945a0SNathan Whitehorn 
226*4c8945a0SNathan Whitehorn     while (1) {
227*4c8945a0SNathan Whitehorn 	/* skip white space before fg/bg string */
228*4c8945a0SNathan Whitehorn 	i = skip_whitespace(tempstr, i);
229*4c8945a0SNathan Whitehorn 	if (tempstr[i] == '\0')
230*4c8945a0SNathan Whitehorn 	    return -1;		/* invalid representation */
231*4c8945a0SNathan Whitehorn 	part = tempstr + i;	/* set 'part' to start of fg/bg string */
232*4c8945a0SNathan Whitehorn 
233*4c8945a0SNathan Whitehorn 	/* find end of fg/bg string */
234*4c8945a0SNathan Whitehorn 	while (!whitespace(tempstr[i]) && tempstr[i] != ','
235*4c8945a0SNathan Whitehorn 	       && tempstr[i] != '\0')
236*4c8945a0SNathan Whitehorn 	    i++;
237*4c8945a0SNathan Whitehorn 
238*4c8945a0SNathan Whitehorn 	if (tempstr[i] == '\0')
239*4c8945a0SNathan Whitehorn 	    return -1;		/* invalid representation */
240*4c8945a0SNathan Whitehorn 	else if (whitespace(tempstr[i])) {	/* not yet ',' */
241*4c8945a0SNathan Whitehorn 	    tempstr[i++] = '\0';
242*4c8945a0SNathan Whitehorn 
243*4c8945a0SNathan Whitehorn 	    /* skip white space before ',' */
244*4c8945a0SNathan Whitehorn 	    i = skip_whitespace(tempstr, i);
245*4c8945a0SNathan Whitehorn 	    if (tempstr[i] != ',')
246*4c8945a0SNathan Whitehorn 		return -1;	/* invalid representation */
247*4c8945a0SNathan Whitehorn 	}
248*4c8945a0SNathan Whitehorn 	tempstr[i++] = '\0';	/* skip the ',' */
249*4c8945a0SNathan Whitehorn 	for (j = 0; j < COLOR_COUNT && dlg_strcmp(part, color_names[j].name);
250*4c8945a0SNathan Whitehorn 	     j++) ;
251*4c8945a0SNathan Whitehorn 	if (j == COLOR_COUNT)	/* invalid color name */
252*4c8945a0SNathan Whitehorn 	    return -1;
253*4c8945a0SNathan Whitehorn 	if (get_fg) {
254*4c8945a0SNathan Whitehorn 	    *fg = color_names[j].value;
255*4c8945a0SNathan Whitehorn 	    get_fg = 0;		/* next we have to get the background */
256*4c8945a0SNathan Whitehorn 	} else {
257*4c8945a0SNathan Whitehorn 	    *bg = color_names[j].value;
258*4c8945a0SNathan Whitehorn 	    break;
259*4c8945a0SNathan Whitehorn 	}
260*4c8945a0SNathan Whitehorn     }				/* got foreground and background */
261*4c8945a0SNathan Whitehorn 
262*4c8945a0SNathan Whitehorn     /* get highlight */
263*4c8945a0SNathan Whitehorn 
264*4c8945a0SNathan Whitehorn     /* skip white space before highlight string */
265*4c8945a0SNathan Whitehorn     i = skip_whitespace(tempstr, i);
266*4c8945a0SNathan Whitehorn     if (tempstr[i] == '\0')
267*4c8945a0SNathan Whitehorn 	return -1;		/* invalid representation */
268*4c8945a0SNathan Whitehorn     part = tempstr + i;		/* set 'part' to start of highlight string */
269*4c8945a0SNathan Whitehorn 
270*4c8945a0SNathan Whitehorn     /* trim trailing white space from highlight string */
271*4c8945a0SNathan Whitehorn     i = (int) strlen(part) - 1;
272*4c8945a0SNathan Whitehorn     while (whitespace(part[i]) && i > 0)
273*4c8945a0SNathan Whitehorn 	i--;
274*4c8945a0SNathan Whitehorn     part[i + 1] = '\0';
275*4c8945a0SNathan Whitehorn 
276*4c8945a0SNathan Whitehorn     if (!dlg_strcmp(part, "ON"))
277*4c8945a0SNathan Whitehorn 	*hl = TRUE;
278*4c8945a0SNathan Whitehorn     else if (!dlg_strcmp(part, "OFF"))
279*4c8945a0SNathan Whitehorn 	*hl = FALSE;
280*4c8945a0SNathan Whitehorn     else
281*4c8945a0SNathan Whitehorn 	return -1;		/* invalid highlight value */
282*4c8945a0SNathan Whitehorn 
283*4c8945a0SNathan Whitehorn     return 0;
284*4c8945a0SNathan Whitehorn }
285*4c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
286*4c8945a0SNathan Whitehorn 
287*4c8945a0SNathan Whitehorn /*
288*4c8945a0SNathan Whitehorn  * Check if the line begins with a special keyword; if so, return true while
289*4c8945a0SNathan Whitehorn  * pointing params to its parameters.
290*4c8945a0SNathan Whitehorn  */
291*4c8945a0SNathan Whitehorn static int
292*4c8945a0SNathan Whitehorn begins_with(char *line, const char *keyword, char **params)
293*4c8945a0SNathan Whitehorn {
294*4c8945a0SNathan Whitehorn     int i = skip_whitespace(line, 0);
295*4c8945a0SNathan Whitehorn     int j = skip_keyword(line, i);
296*4c8945a0SNathan Whitehorn 
297*4c8945a0SNathan Whitehorn     if ((j - i) == (int) strlen(keyword)) {
298*4c8945a0SNathan Whitehorn 	char save = line[j];
299*4c8945a0SNathan Whitehorn 	line[j] = 0;
300*4c8945a0SNathan Whitehorn 	if (!dlg_strcmp(keyword, line + i)) {
301*4c8945a0SNathan Whitehorn 	    *params = line + skip_whitespace(line, j + 1);
302*4c8945a0SNathan Whitehorn 	    return 1;
303*4c8945a0SNathan Whitehorn 	}
304*4c8945a0SNathan Whitehorn 	line[j] = save;
305*4c8945a0SNathan Whitehorn     }
306*4c8945a0SNathan Whitehorn 
307*4c8945a0SNathan Whitehorn     return 0;
308*4c8945a0SNathan Whitehorn }
309*4c8945a0SNathan Whitehorn 
310*4c8945a0SNathan Whitehorn /*
311*4c8945a0SNathan Whitehorn  * Parse a line in the configuration file
312*4c8945a0SNathan Whitehorn  *
313*4c8945a0SNathan Whitehorn  * Each line is of the form:  "variable = value". On exit, 'var' will contain
314*4c8945a0SNathan Whitehorn  * the variable name, and 'value' will contain the value string.
315*4c8945a0SNathan Whitehorn  *
316*4c8945a0SNathan Whitehorn  * Return values:
317*4c8945a0SNathan Whitehorn  *
318*4c8945a0SNathan Whitehorn  * LINE_EMPTY   - line is blank or comment
319*4c8945a0SNathan Whitehorn  * LINE_EQUALS  - line contains "variable = value"
320*4c8945a0SNathan Whitehorn  * LINE_ERROR   - syntax error in line
321*4c8945a0SNathan Whitehorn  */
322*4c8945a0SNathan Whitehorn static PARSE_LINE
323*4c8945a0SNathan Whitehorn parse_line(char *line, char **var, char **value)
324*4c8945a0SNathan Whitehorn {
325*4c8945a0SNathan Whitehorn     int i = 0;
326*4c8945a0SNathan Whitehorn 
327*4c8945a0SNathan Whitehorn     /* ignore white space at beginning of line */
328*4c8945a0SNathan Whitehorn     i = skip_whitespace(line, i);
329*4c8945a0SNathan Whitehorn 
330*4c8945a0SNathan Whitehorn     if (line[i] == '\0')	/* line is blank */
331*4c8945a0SNathan Whitehorn 	return LINE_EMPTY;
332*4c8945a0SNathan Whitehorn     else if (line[i] == '#')	/* line is comment */
333*4c8945a0SNathan Whitehorn 	return LINE_EMPTY;
334*4c8945a0SNathan Whitehorn     else if (line[i] == '=')	/* variable names cannot start with a '=' */
335*4c8945a0SNathan Whitehorn 	return LINE_ERROR;
336*4c8945a0SNathan Whitehorn 
337*4c8945a0SNathan Whitehorn     /* set 'var' to variable name */
338*4c8945a0SNathan Whitehorn     *var = line + i++;		/* skip to next character */
339*4c8945a0SNathan Whitehorn 
340*4c8945a0SNathan Whitehorn     /* find end of variable name */
341*4c8945a0SNathan Whitehorn     while (!whitespace(line[i]) && line[i] != '=' && line[i] != '\0')
342*4c8945a0SNathan Whitehorn 	i++;
343*4c8945a0SNathan Whitehorn 
344*4c8945a0SNathan Whitehorn     if (line[i] == '\0')	/* syntax error */
345*4c8945a0SNathan Whitehorn 	return LINE_ERROR;
346*4c8945a0SNathan Whitehorn     else if (line[i] == '=')
347*4c8945a0SNathan Whitehorn 	line[i++] = '\0';
348*4c8945a0SNathan Whitehorn     else {
349*4c8945a0SNathan Whitehorn 	line[i++] = '\0';
350*4c8945a0SNathan Whitehorn 
351*4c8945a0SNathan Whitehorn 	/* skip white space before '=' */
352*4c8945a0SNathan Whitehorn 	i = skip_whitespace(line, i);
353*4c8945a0SNathan Whitehorn 
354*4c8945a0SNathan Whitehorn 	if (line[i] != '=')	/* syntax error */
355*4c8945a0SNathan Whitehorn 	    return LINE_ERROR;
356*4c8945a0SNathan Whitehorn 	else
357*4c8945a0SNathan Whitehorn 	    i++;		/* skip the '=' */
358*4c8945a0SNathan Whitehorn     }
359*4c8945a0SNathan Whitehorn 
360*4c8945a0SNathan Whitehorn     /* skip white space after '=' */
361*4c8945a0SNathan Whitehorn     i = skip_whitespace(line, i);
362*4c8945a0SNathan Whitehorn 
363*4c8945a0SNathan Whitehorn     if (line[i] == '\0')
364*4c8945a0SNathan Whitehorn 	return LINE_ERROR;
365*4c8945a0SNathan Whitehorn     else
366*4c8945a0SNathan Whitehorn 	*value = line + i;	/* set 'value' to value string */
367*4c8945a0SNathan Whitehorn 
368*4c8945a0SNathan Whitehorn     /* trim trailing white space from 'value' */
369*4c8945a0SNathan Whitehorn     i = (int) strlen(*value) - 1;
370*4c8945a0SNathan Whitehorn     while (whitespace((*value)[i]) && i > 0)
371*4c8945a0SNathan Whitehorn 	i--;
372*4c8945a0SNathan Whitehorn     (*value)[i + 1] = '\0';
373*4c8945a0SNathan Whitehorn 
374*4c8945a0SNathan Whitehorn     return LINE_EQUALS;		/* no syntax error in line */
375*4c8945a0SNathan Whitehorn }
376*4c8945a0SNathan Whitehorn 
377*4c8945a0SNathan Whitehorn /*
378*4c8945a0SNathan Whitehorn  * Create the configuration file
379*4c8945a0SNathan Whitehorn  */
380*4c8945a0SNathan Whitehorn void
381*4c8945a0SNathan Whitehorn dlg_create_rc(const char *filename)
382*4c8945a0SNathan Whitehorn {
383*4c8945a0SNathan Whitehorn     unsigned i;
384*4c8945a0SNathan Whitehorn     FILE *rc_file;
385*4c8945a0SNathan Whitehorn 
386*4c8945a0SNathan Whitehorn     if ((rc_file = fopen(filename, "wt")) == NULL)
387*4c8945a0SNathan Whitehorn 	dlg_exiterr("Error opening file for writing in dlg_create_rc().");
388*4c8945a0SNathan Whitehorn 
389*4c8945a0SNathan Whitehorn     fprintf(rc_file, "#\n\
390*4c8945a0SNathan Whitehorn # Run-time configuration file for dialog\n\
391*4c8945a0SNathan Whitehorn #\n\
392*4c8945a0SNathan Whitehorn # Automatically generated by \"dialog --create-rc <file>\"\n\
393*4c8945a0SNathan Whitehorn #\n\
394*4c8945a0SNathan Whitehorn #\n\
395*4c8945a0SNathan Whitehorn # Types of values:\n\
396*4c8945a0SNathan Whitehorn #\n\
397*4c8945a0SNathan Whitehorn # Number     -  <number>\n\
398*4c8945a0SNathan Whitehorn # String     -  \"string\"\n\
399*4c8945a0SNathan Whitehorn # Boolean    -  <ON|OFF>\n"
400*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
401*4c8945a0SNathan Whitehorn 	    "\
402*4c8945a0SNathan Whitehorn # Attribute  -  (foreground,background,highlight?)\n"
403*4c8945a0SNathan Whitehorn #endif
404*4c8945a0SNathan Whitehorn 	);
405*4c8945a0SNathan Whitehorn 
406*4c8945a0SNathan Whitehorn     /* Print an entry for each configuration variable */
407*4c8945a0SNathan Whitehorn     for (i = 0; i < VAR_COUNT; i++) {
408*4c8945a0SNathan Whitehorn 	fprintf(rc_file, "\n# %s\n", vars[i].comment);
409*4c8945a0SNathan Whitehorn 	switch (vars[i].type) {
410*4c8945a0SNathan Whitehorn 	case VAL_INT:
411*4c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %d\n", vars[i].name,
412*4c8945a0SNathan Whitehorn 		    *((int *) vars[i].var));
413*4c8945a0SNathan Whitehorn 	    break;
414*4c8945a0SNathan Whitehorn 	case VAL_STR:
415*4c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = \"%s\"\n", vars[i].name,
416*4c8945a0SNathan Whitehorn 		    (char *) vars[i].var);
417*4c8945a0SNathan Whitehorn 	    break;
418*4c8945a0SNathan Whitehorn 	case VAL_BOOL:
419*4c8945a0SNathan Whitehorn 	    fprintf(rc_file, "%s = %s\n", vars[i].name,
420*4c8945a0SNathan Whitehorn 		    *((bool *) vars[i].var) ? "ON" : "OFF");
421*4c8945a0SNathan Whitehorn 	    break;
422*4c8945a0SNathan Whitehorn 	}
423*4c8945a0SNathan Whitehorn     }
424*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
425*4c8945a0SNathan Whitehorn     for (i = 0; i < (unsigned) dlg_color_count(); ++i) {
426*4c8945a0SNathan Whitehorn 	char buffer[MAX_LEN + 1];
427*4c8945a0SNathan Whitehorn 
428*4c8945a0SNathan Whitehorn 	fprintf(rc_file, "\n# %s\n", dlg_color_table[i].comment);
429*4c8945a0SNathan Whitehorn 	fprintf(rc_file, "%s = %s\n", dlg_color_table[i].name,
430*4c8945a0SNathan Whitehorn 		attr_to_str(buffer,
431*4c8945a0SNathan Whitehorn 			    dlg_color_table[i].fg,
432*4c8945a0SNathan Whitehorn 			    dlg_color_table[i].bg,
433*4c8945a0SNathan Whitehorn 			    dlg_color_table[i].hilite));
434*4c8945a0SNathan Whitehorn     }
435*4c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
436*4c8945a0SNathan Whitehorn #if 1
437*4c8945a0SNathan Whitehorn     dlg_dump_keys(rc_file);
438*4c8945a0SNathan Whitehorn #endif
439*4c8945a0SNathan Whitehorn 
440*4c8945a0SNathan Whitehorn     (void) fclose(rc_file);
441*4c8945a0SNathan Whitehorn }
442*4c8945a0SNathan Whitehorn 
443*4c8945a0SNathan Whitehorn /*
444*4c8945a0SNathan Whitehorn  * Parse the configuration file and set up variables
445*4c8945a0SNathan Whitehorn  */
446*4c8945a0SNathan Whitehorn int
447*4c8945a0SNathan Whitehorn dlg_parse_rc(void)
448*4c8945a0SNathan Whitehorn {
449*4c8945a0SNathan Whitehorn     int i;
450*4c8945a0SNathan Whitehorn     int l = 1;
451*4c8945a0SNathan Whitehorn     PARSE_LINE parse;
452*4c8945a0SNathan Whitehorn     char str[MAX_LEN + 1];
453*4c8945a0SNathan Whitehorn     char *var;
454*4c8945a0SNathan Whitehorn     char *value;
455*4c8945a0SNathan Whitehorn     char *tempptr;
456*4c8945a0SNathan Whitehorn     int result = 0;
457*4c8945a0SNathan Whitehorn     FILE *rc_file = 0;
458*4c8945a0SNathan Whitehorn #if 1
459*4c8945a0SNathan Whitehorn     char *params;
460*4c8945a0SNathan Whitehorn #endif
461*4c8945a0SNathan Whitehorn 
462*4c8945a0SNathan Whitehorn     /*
463*4c8945a0SNathan Whitehorn      *  At startup, dialog determines the settings to use as follows:
464*4c8945a0SNathan Whitehorn      *
465*4c8945a0SNathan Whitehorn      *  a) if the environment variable $DIALOGRC is set, its value determines
466*4c8945a0SNathan Whitehorn      *     the name of the configuration file.
467*4c8945a0SNathan Whitehorn      *
468*4c8945a0SNathan Whitehorn      *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
469*4c8945a0SNathan Whitehorn      *     as the configuration file.
470*4c8945a0SNathan Whitehorn      *
471*4c8945a0SNathan Whitehorn      *  c) if the file in (b) can't be found, try using the GLOBALRC file.
472*4c8945a0SNathan Whitehorn      *     Usually this will be /etc/dialogrc.
473*4c8945a0SNathan Whitehorn      *
474*4c8945a0SNathan Whitehorn      *  d) if the file in (c) cannot be found, use the compiled-in defaults.
475*4c8945a0SNathan Whitehorn      */
476*4c8945a0SNathan Whitehorn 
477*4c8945a0SNathan Whitehorn     /* try step (a) */
478*4c8945a0SNathan Whitehorn     if ((tempptr = getenv("DIALOGRC")) != NULL)
479*4c8945a0SNathan Whitehorn 	rc_file = fopen(tempptr, "rt");
480*4c8945a0SNathan Whitehorn 
481*4c8945a0SNathan Whitehorn     if (rc_file == NULL) {	/* step (a) failed? */
482*4c8945a0SNathan Whitehorn 	/* try step (b) */
483*4c8945a0SNathan Whitehorn 	if ((tempptr = getenv("HOME")) != NULL
484*4c8945a0SNathan Whitehorn 	    && strlen(tempptr) < MAX_LEN - (sizeof(DIALOGRC) + 3)) {
485*4c8945a0SNathan Whitehorn 	    if (tempptr[0] == '\0' || lastch(tempptr) == '/')
486*4c8945a0SNathan Whitehorn 		sprintf(str, "%s%s", tempptr, DIALOGRC);
487*4c8945a0SNathan Whitehorn 	    else
488*4c8945a0SNathan Whitehorn 		sprintf(str, "%s/%s", tempptr, DIALOGRC);
489*4c8945a0SNathan Whitehorn 	    rc_file = fopen(str, "rt");
490*4c8945a0SNathan Whitehorn 	}
491*4c8945a0SNathan Whitehorn     }
492*4c8945a0SNathan Whitehorn 
493*4c8945a0SNathan Whitehorn     if (rc_file == NULL) {	/* step (b) failed? */
494*4c8945a0SNathan Whitehorn 	/* try step (c) */
495*4c8945a0SNathan Whitehorn 	strcpy(str, GLOBALRC);
496*4c8945a0SNathan Whitehorn 	if ((rc_file = fopen(str, "rt")) == NULL)
497*4c8945a0SNathan Whitehorn 	    return 0;		/* step (c) failed, use default values */
498*4c8945a0SNathan Whitehorn     }
499*4c8945a0SNathan Whitehorn 
500*4c8945a0SNathan Whitehorn     /* Scan each line and set variables */
501*4c8945a0SNathan Whitehorn     while ((result == 0) && (fgets(str, MAX_LEN, rc_file) != NULL)) {
502*4c8945a0SNathan Whitehorn 	dlg_trace_msg("rc:%s\n", str);
503*4c8945a0SNathan Whitehorn 	if (*str == '\0' || lastch(str) != '\n') {
504*4c8945a0SNathan Whitehorn 	    /* ignore rest of file if line too long */
505*4c8945a0SNathan Whitehorn 	    fprintf(stderr, "\nParse error: line %d of configuration"
506*4c8945a0SNathan Whitehorn 		    " file too long.\n", l);
507*4c8945a0SNathan Whitehorn 	    result = -1;	/* parse aborted */
508*4c8945a0SNathan Whitehorn 	    break;
509*4c8945a0SNathan Whitehorn 	}
510*4c8945a0SNathan Whitehorn 
511*4c8945a0SNathan Whitehorn 	lastch(str) = '\0';
512*4c8945a0SNathan Whitehorn 	if (begins_with(str, "bindkey", &params)) {
513*4c8945a0SNathan Whitehorn 	    dlg_parse_bindkey(params);
514*4c8945a0SNathan Whitehorn 	    continue;
515*4c8945a0SNathan Whitehorn 	}
516*4c8945a0SNathan Whitehorn 	parse = parse_line(str, &var, &value);	/* parse current line */
517*4c8945a0SNathan Whitehorn 
518*4c8945a0SNathan Whitehorn 	switch (parse) {
519*4c8945a0SNathan Whitehorn 	case LINE_EMPTY:	/* ignore blank lines and comments */
520*4c8945a0SNathan Whitehorn 	    break;
521*4c8945a0SNathan Whitehorn 	case LINE_EQUALS:
522*4c8945a0SNathan Whitehorn 	    /* search table for matching config variable name */
523*4c8945a0SNathan Whitehorn 	    if ((i = find_vars(var)) >= 0) {
524*4c8945a0SNathan Whitehorn 		switch (vars[i].type) {
525*4c8945a0SNathan Whitehorn 		case VAL_INT:
526*4c8945a0SNathan Whitehorn 		    *((int *) vars[i].var) = atoi(value);
527*4c8945a0SNathan Whitehorn 		    break;
528*4c8945a0SNathan Whitehorn 		case VAL_STR:
529*4c8945a0SNathan Whitehorn 		    if (!isquote(value[0]) || !isquote(lastch(value))
530*4c8945a0SNathan Whitehorn 			|| strlen(value) < 2) {
531*4c8945a0SNathan Whitehorn 			fprintf(stderr, "\nParse error: string value "
532*4c8945a0SNathan Whitehorn 				"expected at line %d of configuration "
533*4c8945a0SNathan Whitehorn 				"file.\n", l);
534*4c8945a0SNathan Whitehorn 			result = -1;	/* parse aborted */
535*4c8945a0SNathan Whitehorn 		    } else {
536*4c8945a0SNathan Whitehorn 			/* remove the (") quotes */
537*4c8945a0SNathan Whitehorn 			value++;
538*4c8945a0SNathan Whitehorn 			lastch(value) = '\0';
539*4c8945a0SNathan Whitehorn 			strcpy((char *) vars[i].var, value);
540*4c8945a0SNathan Whitehorn 		    }
541*4c8945a0SNathan Whitehorn 		    break;
542*4c8945a0SNathan Whitehorn 		case VAL_BOOL:
543*4c8945a0SNathan Whitehorn 		    if (!dlg_strcmp(value, "ON"))
544*4c8945a0SNathan Whitehorn 			*((bool *) vars[i].var) = TRUE;
545*4c8945a0SNathan Whitehorn 		    else if (!dlg_strcmp(value, "OFF"))
546*4c8945a0SNathan Whitehorn 			*((bool *) vars[i].var) = FALSE;
547*4c8945a0SNathan Whitehorn 		    else {
548*4c8945a0SNathan Whitehorn 			fprintf(stderr, "\nParse error: boolean value "
549*4c8945a0SNathan Whitehorn 				"expected at line %d of configuration "
550*4c8945a0SNathan Whitehorn 				"file (found %s).\n", l, value);
551*4c8945a0SNathan Whitehorn 			result = -1;	/* parse aborted */
552*4c8945a0SNathan Whitehorn 		    }
553*4c8945a0SNathan Whitehorn 		    break;
554*4c8945a0SNathan Whitehorn 		}
555*4c8945a0SNathan Whitehorn #ifdef HAVE_COLOR
556*4c8945a0SNathan Whitehorn 	    } else if ((i = find_color(var)) >= 0) {
557*4c8945a0SNathan Whitehorn 		int fg = 0;
558*4c8945a0SNathan Whitehorn 		int bg = 0;
559*4c8945a0SNathan Whitehorn 		int hl = 0;
560*4c8945a0SNathan Whitehorn 		if (str_to_attr(value, &fg, &bg, &hl) == -1) {
561*4c8945a0SNathan Whitehorn 		    fprintf(stderr, "\nParse error: attribute "
562*4c8945a0SNathan Whitehorn 			    "value expected at line %d of configuration "
563*4c8945a0SNathan Whitehorn 			    "file.\n", l);
564*4c8945a0SNathan Whitehorn 		    result = -1;	/* parse aborted */
565*4c8945a0SNathan Whitehorn 		} else {
566*4c8945a0SNathan Whitehorn 		    dlg_color_table[i].fg = fg;
567*4c8945a0SNathan Whitehorn 		    dlg_color_table[i].bg = bg;
568*4c8945a0SNathan Whitehorn 		    dlg_color_table[i].hilite = hl;
569*4c8945a0SNathan Whitehorn 		}
570*4c8945a0SNathan Whitehorn 	    } else {
571*4c8945a0SNathan Whitehorn #endif /* HAVE_COLOR */
572*4c8945a0SNathan Whitehorn 		fprintf(stderr, "\nParse error: unknown variable "
573*4c8945a0SNathan Whitehorn 			"at line %d of configuration file:\n\t%s\n", l, var);
574*4c8945a0SNathan Whitehorn 		result = -1;	/* parse aborted */
575*4c8945a0SNathan Whitehorn 	    }
576*4c8945a0SNathan Whitehorn 	    break;
577*4c8945a0SNathan Whitehorn 	case LINE_ERROR:
578*4c8945a0SNathan Whitehorn 	    fprintf(stderr, "\nParse error: syntax error at line %d of "
579*4c8945a0SNathan Whitehorn 		    "configuration file.\n", l);
580*4c8945a0SNathan Whitehorn 	    result = -1;	/* parse aborted */
581*4c8945a0SNathan Whitehorn 	    break;
582*4c8945a0SNathan Whitehorn 	}
583*4c8945a0SNathan Whitehorn 	l++;			/* next line */
584*4c8945a0SNathan Whitehorn     }
585*4c8945a0SNathan Whitehorn 
586*4c8945a0SNathan Whitehorn     (void) fclose(rc_file);
587*4c8945a0SNathan Whitehorn     return result;
588*4c8945a0SNathan Whitehorn }
589