1217309Snwhitehorn/*
2251843Sbapt *  $Id: rc.c,v 1.51 2012/11/30 21:32:39 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  rc.c -- routines for processing the configuration file
5217309Snwhitehorn *
6251843Sbapt *  Copyright 2000-2011,2012	Thomas E. Dickey
7217309Snwhitehorn *
8217309Snwhitehorn *  This program is free software; you can redistribute it and/or modify
9217309Snwhitehorn *  it under the terms of the GNU Lesser General Public License, version 2.1
10217309Snwhitehorn *  as published by the Free Software Foundation.
11217309Snwhitehorn *
12217309Snwhitehorn *  This program is distributed in the hope that it will be useful, but
13217309Snwhitehorn *  WITHOUT ANY WARRANTY; without even the implied warranty of
14217309Snwhitehorn *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15217309Snwhitehorn *  Lesser General Public License for more details.
16217309Snwhitehorn *
17217309Snwhitehorn *  You should have received a copy of the GNU Lesser General Public
18217309Snwhitehorn *  License along with this program; if not, write to
19217309Snwhitehorn *	Free Software Foundation, Inc.
20217309Snwhitehorn *	51 Franklin St., Fifth Floor
21217309Snwhitehorn *	Boston, MA 02110, USA.
22217309Snwhitehorn *
23217309Snwhitehorn *  An earlier version of this program lists as authors
24217309Snwhitehorn *	Savio Lam (lam836@cs.cuhk.hk)
25217309Snwhitehorn */
26217309Snwhitehorn
27217309Snwhitehorn#include <dialog.h>
28217309Snwhitehorn
29217309Snwhitehorn#include <dlg_keys.h>
30217309Snwhitehorn
31217309Snwhitehorn#ifdef HAVE_COLOR
32217309Snwhitehorn#include <dlg_colors.h>
33217309Snwhitehorn
34217309Snwhitehorn/*
35217309Snwhitehorn * For matching color names with color values
36217309Snwhitehorn */
37217309Snwhitehornstatic const color_names_st color_names[] =
38217309Snwhitehorn{
39217309Snwhitehorn#ifdef HAVE_USE_DEFAULT_COLORS
40217309Snwhitehorn    {"DEFAULT", -1},
41217309Snwhitehorn#endif
42217309Snwhitehorn    {"BLACK", COLOR_BLACK},
43217309Snwhitehorn    {"RED", COLOR_RED},
44217309Snwhitehorn    {"GREEN", COLOR_GREEN},
45217309Snwhitehorn    {"YELLOW", COLOR_YELLOW},
46217309Snwhitehorn    {"BLUE", COLOR_BLUE},
47217309Snwhitehorn    {"MAGENTA", COLOR_MAGENTA},
48217309Snwhitehorn    {"CYAN", COLOR_CYAN},
49217309Snwhitehorn    {"WHITE", COLOR_WHITE},
50217309Snwhitehorn};				/* color names */
51217309Snwhitehorn#define COLOR_COUNT	(sizeof(color_names) / sizeof(color_names[0]))
52217309Snwhitehorn#endif /* HAVE_COLOR */
53217309Snwhitehorn
54217309Snwhitehorn#define GLOBALRC "/etc/dialogrc"
55217309Snwhitehorn#define DIALOGRC ".dialogrc"
56217309Snwhitehorn
57217309Snwhitehorn/* Types of values */
58217309Snwhitehorn#define VAL_INT  0
59217309Snwhitehorn#define VAL_STR  1
60217309Snwhitehorn#define VAL_BOOL 2
61217309Snwhitehorn
62217309Snwhitehorn/* Type of line in configuration file */
63217309Snwhitehorntypedef enum {
64217309Snwhitehorn    LINE_ERROR = -1,
65217309Snwhitehorn    LINE_EQUALS,
66217309Snwhitehorn    LINE_EMPTY
67217309Snwhitehorn} PARSE_LINE;
68217309Snwhitehorn
69217309Snwhitehorn/* number of configuration variables */
70217309Snwhitehorn#define VAR_COUNT        (sizeof(vars) / sizeof(vars_st))
71217309Snwhitehorn
72217309Snwhitehorn/* check if character is white space */
73217309Snwhitehorn#define whitespace(c)    (c == ' ' || c == TAB)
74217309Snwhitehorn
75217309Snwhitehorn/* check if character is string quoting characters */
76217309Snwhitehorn#define isquote(c)       (c == '"' || c == '\'')
77217309Snwhitehorn
78217309Snwhitehorn/* get last character of string */
79217309Snwhitehorn#define lastch(str)      str[strlen(str)-1]
80217309Snwhitehorn
81217309Snwhitehorn/*
82217309Snwhitehorn * Configuration variables
83217309Snwhitehorn */
84217309Snwhitehorntypedef struct {
85217309Snwhitehorn    const char *name;		/* name of configuration variable as in DIALOGRC */
86217309Snwhitehorn    void *var;			/* address of actual variable to change */
87217309Snwhitehorn    int type;			/* type of value */
88217309Snwhitehorn    const char *comment;	/* comment to put in "rc" file */
89217309Snwhitehorn} vars_st;
90217309Snwhitehorn
91217309Snwhitehorn/*
92217309Snwhitehorn * This table should contain only references to dialog_state, since dialog_vars
93217309Snwhitehorn * is reset specially in dialog.c before each widget.
94217309Snwhitehorn */
95217309Snwhitehornstatic const vars_st vars[] =
96217309Snwhitehorn{
97217309Snwhitehorn    {"aspect",
98217309Snwhitehorn     &dialog_state.aspect_ratio,
99217309Snwhitehorn     VAL_INT,
100217309Snwhitehorn     "Set aspect-ration."},
101217309Snwhitehorn
102217309Snwhitehorn    {"separate_widget",
103217309Snwhitehorn     &dialog_state.separate_str,
104217309Snwhitehorn     VAL_STR,
105217309Snwhitehorn     "Set separator (for multiple widgets output)."},
106217309Snwhitehorn
107217309Snwhitehorn    {"tab_len",
108217309Snwhitehorn     &dialog_state.tab_len,
109217309Snwhitehorn     VAL_INT,
110217309Snwhitehorn     "Set tab-length (for textbox tab-conversion)."},
111217309Snwhitehorn
112217309Snwhitehorn    {"visit_items",
113217309Snwhitehorn     &dialog_state.visit_items,
114217309Snwhitehorn     VAL_BOOL,
115217309Snwhitehorn     "Make tab-traversal for checklist, etc., include the list."},
116217309Snwhitehorn
117217309Snwhitehorn#ifdef HAVE_COLOR
118217309Snwhitehorn    {"use_shadow",
119217309Snwhitehorn     &dialog_state.use_shadow,
120217309Snwhitehorn     VAL_BOOL,
121217309Snwhitehorn     "Shadow dialog boxes? This also turns on color."},
122217309Snwhitehorn
123217309Snwhitehorn    {"use_colors",
124217309Snwhitehorn     &dialog_state.use_colors,
125217309Snwhitehorn     VAL_BOOL,
126217309Snwhitehorn     "Turn color support ON or OFF"},
127217309Snwhitehorn#endif				/* HAVE_COLOR */
128217309Snwhitehorn};				/* vars */
129217309Snwhitehorn
130217309Snwhitehornstatic int
131217309Snwhitehornskip_whitespace(char *str, int n)
132217309Snwhitehorn{
133217309Snwhitehorn    while (whitespace(str[n]) && str[n] != '\0')
134217309Snwhitehorn	n++;
135217309Snwhitehorn    return n;
136217309Snwhitehorn}
137217309Snwhitehorn
138217309Snwhitehornstatic int
139217309Snwhitehornskip_keyword(char *str, int n)
140217309Snwhitehorn{
141217309Snwhitehorn    while (isalnum(UCH(str[n])) && str[n] != '\0')
142217309Snwhitehorn	n++;
143217309Snwhitehorn    return n;
144217309Snwhitehorn}
145217309Snwhitehorn
146217309Snwhitehornstatic int
147217309Snwhitehornfind_vars(char *name)
148217309Snwhitehorn{
149217309Snwhitehorn    int result = -1;
150217309Snwhitehorn    unsigned i;
151217309Snwhitehorn
152217309Snwhitehorn    for (i = 0; i < VAR_COUNT; i++) {
153217309Snwhitehorn	if (dlg_strcmp(vars[i].name, name) == 0) {
154217309Snwhitehorn	    result = (int) i;
155217309Snwhitehorn	    break;
156217309Snwhitehorn	}
157217309Snwhitehorn    }
158217309Snwhitehorn    return result;
159217309Snwhitehorn}
160217309Snwhitehorn
161217309Snwhitehorn#ifdef HAVE_COLOR
162217309Snwhitehornstatic int
163217309Snwhitehornfind_color(char *name)
164217309Snwhitehorn{
165217309Snwhitehorn    int result = -1;
166217309Snwhitehorn    int i;
167217309Snwhitehorn    int limit = dlg_color_count();
168217309Snwhitehorn
169217309Snwhitehorn    for (i = 0; i < limit; i++) {
170217309Snwhitehorn	if (dlg_strcmp(dlg_color_table[i].name, name) == 0) {
171217309Snwhitehorn	    result = i;
172217309Snwhitehorn	    break;
173217309Snwhitehorn	}
174217309Snwhitehorn    }
175217309Snwhitehorn    return result;
176217309Snwhitehorn}
177217309Snwhitehorn
178217309Snwhitehorn/*
179217309Snwhitehorn * Convert an attribute to a string representation like this:
180217309Snwhitehorn *
181217309Snwhitehorn * "(foreground,background,highlight)"
182217309Snwhitehorn */
183217309Snwhitehornstatic char *
184217309Snwhitehornattr_to_str(char *str, int fg, int bg, int hl)
185217309Snwhitehorn{
186217309Snwhitehorn    int i;
187217309Snwhitehorn
188217309Snwhitehorn    strcpy(str, "(");
189217309Snwhitehorn    /* foreground */
190217309Snwhitehorn    for (i = 0; fg != color_names[i].value; i++) ;
191217309Snwhitehorn    strcat(str, color_names[i].name);
192217309Snwhitehorn    strcat(str, ",");
193217309Snwhitehorn
194217309Snwhitehorn    /* background */
195217309Snwhitehorn    for (i = 0; bg != color_names[i].value; i++) ;
196217309Snwhitehorn    strcat(str, color_names[i].name);
197217309Snwhitehorn
198217309Snwhitehorn    /* highlight */
199217309Snwhitehorn    strcat(str, hl ? ",ON)" : ",OFF)");
200217309Snwhitehorn
201217309Snwhitehorn    return str;
202217309Snwhitehorn}
203217309Snwhitehorn
204217309Snwhitehorn/*
205217309Snwhitehorn * Extract the foreground, background and highlight values from an attribute
206251843Sbapt * represented as a string in one of two forms:
207217309Snwhitehorn *
208217309Snwhitehorn * "(foreground,background,highlight)"
209251843Sbapt " "xxxx_color"
210217309Snwhitehorn */
211217309Snwhitehornstatic int
212217309Snwhitehornstr_to_attr(char *str, int *fg, int *bg, int *hl)
213217309Snwhitehorn{
214217309Snwhitehorn    int i = 0, get_fg = 1;
215217309Snwhitehorn    unsigned j;
216217309Snwhitehorn    char tempstr[MAX_LEN + 1], *part;
217251843Sbapt    size_t have;
218217309Snwhitehorn
219251843Sbapt    if (str[0] != '(' || lastch(str) != ')') {
220251843Sbapt	if ((i = find_color(str)) >= 0) {
221251843Sbapt	    *fg = dlg_color_table[i].fg;
222251843Sbapt	    *bg = dlg_color_table[i].bg;
223251843Sbapt	    *hl = dlg_color_table[i].hilite;
224251843Sbapt	    return 0;
225251843Sbapt	}
226217309Snwhitehorn	return -1;		/* invalid representation */
227251843Sbapt    }
228217309Snwhitehorn
229217309Snwhitehorn    /* remove the parenthesis */
230251843Sbapt    have = strlen(str);
231251843Sbapt    if (have > MAX_LEN) {
232251843Sbapt	have = MAX_LEN - 1;
233251843Sbapt    } else {
234251843Sbapt	have -= 2;
235251843Sbapt    }
236251843Sbapt    memcpy(tempstr, str + 1, have);
237251843Sbapt    tempstr[have] = '\0';
238217309Snwhitehorn
239217309Snwhitehorn    /* get foreground and background */
240217309Snwhitehorn
241217309Snwhitehorn    while (1) {
242217309Snwhitehorn	/* skip white space before fg/bg string */
243217309Snwhitehorn	i = skip_whitespace(tempstr, i);
244217309Snwhitehorn	if (tempstr[i] == '\0')
245217309Snwhitehorn	    return -1;		/* invalid representation */
246217309Snwhitehorn	part = tempstr + i;	/* set 'part' to start of fg/bg string */
247217309Snwhitehorn
248217309Snwhitehorn	/* find end of fg/bg string */
249217309Snwhitehorn	while (!whitespace(tempstr[i]) && tempstr[i] != ','
250217309Snwhitehorn	       && tempstr[i] != '\0')
251217309Snwhitehorn	    i++;
252217309Snwhitehorn
253217309Snwhitehorn	if (tempstr[i] == '\0')
254217309Snwhitehorn	    return -1;		/* invalid representation */
255217309Snwhitehorn	else if (whitespace(tempstr[i])) {	/* not yet ',' */
256217309Snwhitehorn	    tempstr[i++] = '\0';
257217309Snwhitehorn
258217309Snwhitehorn	    /* skip white space before ',' */
259217309Snwhitehorn	    i = skip_whitespace(tempstr, i);
260217309Snwhitehorn	    if (tempstr[i] != ',')
261217309Snwhitehorn		return -1;	/* invalid representation */
262217309Snwhitehorn	}
263217309Snwhitehorn	tempstr[i++] = '\0';	/* skip the ',' */
264217309Snwhitehorn	for (j = 0; j < COLOR_COUNT && dlg_strcmp(part, color_names[j].name);
265217309Snwhitehorn	     j++) ;
266217309Snwhitehorn	if (j == COLOR_COUNT)	/* invalid color name */
267217309Snwhitehorn	    return -1;
268217309Snwhitehorn	if (get_fg) {
269217309Snwhitehorn	    *fg = color_names[j].value;
270217309Snwhitehorn	    get_fg = 0;		/* next we have to get the background */
271217309Snwhitehorn	} else {
272217309Snwhitehorn	    *bg = color_names[j].value;
273217309Snwhitehorn	    break;
274217309Snwhitehorn	}
275217309Snwhitehorn    }				/* got foreground and background */
276217309Snwhitehorn
277217309Snwhitehorn    /* get highlight */
278217309Snwhitehorn
279217309Snwhitehorn    /* skip white space before highlight string */
280217309Snwhitehorn    i = skip_whitespace(tempstr, i);
281217309Snwhitehorn    if (tempstr[i] == '\0')
282217309Snwhitehorn	return -1;		/* invalid representation */
283217309Snwhitehorn    part = tempstr + i;		/* set 'part' to start of highlight string */
284217309Snwhitehorn
285217309Snwhitehorn    /* trim trailing white space from highlight string */
286217309Snwhitehorn    i = (int) strlen(part) - 1;
287217309Snwhitehorn    while (whitespace(part[i]) && i > 0)
288217309Snwhitehorn	i--;
289217309Snwhitehorn    part[i + 1] = '\0';
290217309Snwhitehorn
291217309Snwhitehorn    if (!dlg_strcmp(part, "ON"))
292217309Snwhitehorn	*hl = TRUE;
293217309Snwhitehorn    else if (!dlg_strcmp(part, "OFF"))
294217309Snwhitehorn	*hl = FALSE;
295217309Snwhitehorn    else
296217309Snwhitehorn	return -1;		/* invalid highlight value */
297217309Snwhitehorn
298217309Snwhitehorn    return 0;
299217309Snwhitehorn}
300217309Snwhitehorn#endif /* HAVE_COLOR */
301217309Snwhitehorn
302217309Snwhitehorn/*
303217309Snwhitehorn * Check if the line begins with a special keyword; if so, return true while
304217309Snwhitehorn * pointing params to its parameters.
305217309Snwhitehorn */
306217309Snwhitehornstatic int
307217309Snwhitehornbegins_with(char *line, const char *keyword, char **params)
308217309Snwhitehorn{
309217309Snwhitehorn    int i = skip_whitespace(line, 0);
310217309Snwhitehorn    int j = skip_keyword(line, i);
311217309Snwhitehorn
312217309Snwhitehorn    if ((j - i) == (int) strlen(keyword)) {
313217309Snwhitehorn	char save = line[j];
314217309Snwhitehorn	line[j] = 0;
315217309Snwhitehorn	if (!dlg_strcmp(keyword, line + i)) {
316217309Snwhitehorn	    *params = line + skip_whitespace(line, j + 1);
317217309Snwhitehorn	    return 1;
318217309Snwhitehorn	}
319217309Snwhitehorn	line[j] = save;
320217309Snwhitehorn    }
321217309Snwhitehorn
322217309Snwhitehorn    return 0;
323217309Snwhitehorn}
324217309Snwhitehorn
325217309Snwhitehorn/*
326217309Snwhitehorn * Parse a line in the configuration file
327217309Snwhitehorn *
328217309Snwhitehorn * Each line is of the form:  "variable = value". On exit, 'var' will contain
329217309Snwhitehorn * the variable name, and 'value' will contain the value string.
330217309Snwhitehorn *
331217309Snwhitehorn * Return values:
332217309Snwhitehorn *
333217309Snwhitehorn * LINE_EMPTY   - line is blank or comment
334217309Snwhitehorn * LINE_EQUALS  - line contains "variable = value"
335217309Snwhitehorn * LINE_ERROR   - syntax error in line
336217309Snwhitehorn */
337217309Snwhitehornstatic PARSE_LINE
338217309Snwhitehornparse_line(char *line, char **var, char **value)
339217309Snwhitehorn{
340217309Snwhitehorn    int i = 0;
341217309Snwhitehorn
342217309Snwhitehorn    /* ignore white space at beginning of line */
343217309Snwhitehorn    i = skip_whitespace(line, i);
344217309Snwhitehorn
345217309Snwhitehorn    if (line[i] == '\0')	/* line is blank */
346217309Snwhitehorn	return LINE_EMPTY;
347217309Snwhitehorn    else if (line[i] == '#')	/* line is comment */
348217309Snwhitehorn	return LINE_EMPTY;
349217309Snwhitehorn    else if (line[i] == '=')	/* variable names cannot start with a '=' */
350217309Snwhitehorn	return LINE_ERROR;
351217309Snwhitehorn
352217309Snwhitehorn    /* set 'var' to variable name */
353217309Snwhitehorn    *var = line + i++;		/* skip to next character */
354217309Snwhitehorn
355217309Snwhitehorn    /* find end of variable name */
356217309Snwhitehorn    while (!whitespace(line[i]) && line[i] != '=' && line[i] != '\0')
357217309Snwhitehorn	i++;
358217309Snwhitehorn
359217309Snwhitehorn    if (line[i] == '\0')	/* syntax error */
360217309Snwhitehorn	return LINE_ERROR;
361217309Snwhitehorn    else if (line[i] == '=')
362217309Snwhitehorn	line[i++] = '\0';
363217309Snwhitehorn    else {
364217309Snwhitehorn	line[i++] = '\0';
365217309Snwhitehorn
366217309Snwhitehorn	/* skip white space before '=' */
367217309Snwhitehorn	i = skip_whitespace(line, i);
368217309Snwhitehorn
369217309Snwhitehorn	if (line[i] != '=')	/* syntax error */
370217309Snwhitehorn	    return LINE_ERROR;
371217309Snwhitehorn	else
372217309Snwhitehorn	    i++;		/* skip the '=' */
373217309Snwhitehorn    }
374217309Snwhitehorn
375217309Snwhitehorn    /* skip white space after '=' */
376217309Snwhitehorn    i = skip_whitespace(line, i);
377217309Snwhitehorn
378217309Snwhitehorn    if (line[i] == '\0')
379217309Snwhitehorn	return LINE_ERROR;
380217309Snwhitehorn    else
381217309Snwhitehorn	*value = line + i;	/* set 'value' to value string */
382217309Snwhitehorn
383217309Snwhitehorn    /* trim trailing white space from 'value' */
384217309Snwhitehorn    i = (int) strlen(*value) - 1;
385217309Snwhitehorn    while (whitespace((*value)[i]) && i > 0)
386217309Snwhitehorn	i--;
387217309Snwhitehorn    (*value)[i + 1] = '\0';
388217309Snwhitehorn
389217309Snwhitehorn    return LINE_EQUALS;		/* no syntax error in line */
390217309Snwhitehorn}
391217309Snwhitehorn
392217309Snwhitehorn/*
393217309Snwhitehorn * Create the configuration file
394217309Snwhitehorn */
395217309Snwhitehornvoid
396217309Snwhitehorndlg_create_rc(const char *filename)
397217309Snwhitehorn{
398217309Snwhitehorn    unsigned i;
399217309Snwhitehorn    FILE *rc_file;
400217309Snwhitehorn
401217309Snwhitehorn    if ((rc_file = fopen(filename, "wt")) == NULL)
402217309Snwhitehorn	dlg_exiterr("Error opening file for writing in dlg_create_rc().");
403217309Snwhitehorn
404217309Snwhitehorn    fprintf(rc_file, "#\n\
405217309Snwhitehorn# Run-time configuration file for dialog\n\
406217309Snwhitehorn#\n\
407217309Snwhitehorn# Automatically generated by \"dialog --create-rc <file>\"\n\
408217309Snwhitehorn#\n\
409217309Snwhitehorn#\n\
410217309Snwhitehorn# Types of values:\n\
411217309Snwhitehorn#\n\
412217309Snwhitehorn# Number     -  <number>\n\
413217309Snwhitehorn# String     -  \"string\"\n\
414217309Snwhitehorn# Boolean    -  <ON|OFF>\n"
415217309Snwhitehorn#ifdef HAVE_COLOR
416217309Snwhitehorn	    "\
417217309Snwhitehorn# Attribute  -  (foreground,background,highlight?)\n"
418217309Snwhitehorn#endif
419217309Snwhitehorn	);
420217309Snwhitehorn
421217309Snwhitehorn    /* Print an entry for each configuration variable */
422217309Snwhitehorn    for (i = 0; i < VAR_COUNT; i++) {
423217309Snwhitehorn	fprintf(rc_file, "\n# %s\n", vars[i].comment);
424217309Snwhitehorn	switch (vars[i].type) {
425217309Snwhitehorn	case VAL_INT:
426217309Snwhitehorn	    fprintf(rc_file, "%s = %d\n", vars[i].name,
427217309Snwhitehorn		    *((int *) vars[i].var));
428217309Snwhitehorn	    break;
429217309Snwhitehorn	case VAL_STR:
430217309Snwhitehorn	    fprintf(rc_file, "%s = \"%s\"\n", vars[i].name,
431217309Snwhitehorn		    (char *) vars[i].var);
432217309Snwhitehorn	    break;
433217309Snwhitehorn	case VAL_BOOL:
434217309Snwhitehorn	    fprintf(rc_file, "%s = %s\n", vars[i].name,
435217309Snwhitehorn		    *((bool *) vars[i].var) ? "ON" : "OFF");
436217309Snwhitehorn	    break;
437217309Snwhitehorn	}
438217309Snwhitehorn    }
439217309Snwhitehorn#ifdef HAVE_COLOR
440217309Snwhitehorn    for (i = 0; i < (unsigned) dlg_color_count(); ++i) {
441217309Snwhitehorn	char buffer[MAX_LEN + 1];
442251843Sbapt	unsigned j;
443251843Sbapt	bool repeat = FALSE;
444217309Snwhitehorn
445217309Snwhitehorn	fprintf(rc_file, "\n# %s\n", dlg_color_table[i].comment);
446251843Sbapt	for (j = 0; j != i; ++j) {
447251843Sbapt	    if (dlg_color_table[i].fg == dlg_color_table[j].fg
448251843Sbapt		&& dlg_color_table[i].bg == dlg_color_table[j].bg
449251843Sbapt		&& dlg_color_table[i].hilite == dlg_color_table[j].hilite) {
450251843Sbapt		fprintf(rc_file, "%s = %s\n",
451251843Sbapt			dlg_color_table[i].name,
452251843Sbapt			dlg_color_table[j].name);
453251843Sbapt		repeat = TRUE;
454251843Sbapt		break;
455251843Sbapt	    }
456251843Sbapt	}
457251843Sbapt
458251843Sbapt	if (!repeat) {
459251843Sbapt	    fprintf(rc_file, "%s = %s\n", dlg_color_table[i].name,
460251843Sbapt		    attr_to_str(buffer,
461251843Sbapt				dlg_color_table[i].fg,
462251843Sbapt				dlg_color_table[i].bg,
463251843Sbapt				dlg_color_table[i].hilite));
464251843Sbapt	}
465217309Snwhitehorn    }
466217309Snwhitehorn#endif /* HAVE_COLOR */
467217309Snwhitehorn    dlg_dump_keys(rc_file);
468217309Snwhitehorn
469217309Snwhitehorn    (void) fclose(rc_file);
470217309Snwhitehorn}
471217309Snwhitehorn
472217309Snwhitehorn/*
473217309Snwhitehorn * Parse the configuration file and set up variables
474217309Snwhitehorn */
475217309Snwhitehornint
476217309Snwhitehorndlg_parse_rc(void)
477217309Snwhitehorn{
478217309Snwhitehorn    int i;
479217309Snwhitehorn    int l = 1;
480217309Snwhitehorn    PARSE_LINE parse;
481217309Snwhitehorn    char str[MAX_LEN + 1];
482217309Snwhitehorn    char *var;
483217309Snwhitehorn    char *value;
484217309Snwhitehorn    char *tempptr;
485217309Snwhitehorn    int result = 0;
486217309Snwhitehorn    FILE *rc_file = 0;
487217309Snwhitehorn    char *params;
488217309Snwhitehorn
489217309Snwhitehorn    /*
490217309Snwhitehorn     *  At startup, dialog determines the settings to use as follows:
491217309Snwhitehorn     *
492217309Snwhitehorn     *  a) if the environment variable $DIALOGRC is set, its value determines
493217309Snwhitehorn     *     the name of the configuration file.
494217309Snwhitehorn     *
495217309Snwhitehorn     *  b) if the file in (a) can't be found, use the file $HOME/.dialogrc
496217309Snwhitehorn     *     as the configuration file.
497217309Snwhitehorn     *
498217309Snwhitehorn     *  c) if the file in (b) can't be found, try using the GLOBALRC file.
499217309Snwhitehorn     *     Usually this will be /etc/dialogrc.
500217309Snwhitehorn     *
501217309Snwhitehorn     *  d) if the file in (c) cannot be found, use the compiled-in defaults.
502217309Snwhitehorn     */
503217309Snwhitehorn
504217309Snwhitehorn    /* try step (a) */
505217309Snwhitehorn    if ((tempptr = getenv("DIALOGRC")) != NULL)
506217309Snwhitehorn	rc_file = fopen(tempptr, "rt");
507217309Snwhitehorn
508217309Snwhitehorn    if (rc_file == NULL) {	/* step (a) failed? */
509217309Snwhitehorn	/* try step (b) */
510217309Snwhitehorn	if ((tempptr = getenv("HOME")) != NULL
511217309Snwhitehorn	    && strlen(tempptr) < MAX_LEN - (sizeof(DIALOGRC) + 3)) {
512217309Snwhitehorn	    if (tempptr[0] == '\0' || lastch(tempptr) == '/')
513217309Snwhitehorn		sprintf(str, "%s%s", tempptr, DIALOGRC);
514217309Snwhitehorn	    else
515217309Snwhitehorn		sprintf(str, "%s/%s", tempptr, DIALOGRC);
516224014Snwhitehorn	    rc_file = fopen(tempptr = str, "rt");
517217309Snwhitehorn	}
518217309Snwhitehorn    }
519217309Snwhitehorn
520217309Snwhitehorn    if (rc_file == NULL) {	/* step (b) failed? */
521217309Snwhitehorn	/* try step (c) */
522217309Snwhitehorn	strcpy(str, GLOBALRC);
523224014Snwhitehorn	if ((rc_file = fopen(tempptr = str, "rt")) == NULL)
524217309Snwhitehorn	    return 0;		/* step (c) failed, use default values */
525217309Snwhitehorn    }
526217309Snwhitehorn
527224014Snwhitehorn    DLG_TRACE(("opened rc file \"%s\"\n", tempptr));
528217309Snwhitehorn    /* Scan each line and set variables */
529217309Snwhitehorn    while ((result == 0) && (fgets(str, MAX_LEN, rc_file) != NULL)) {
530224014Snwhitehorn	DLG_TRACE(("rc:%s", str));
531217309Snwhitehorn	if (*str == '\0' || lastch(str) != '\n') {
532217309Snwhitehorn	    /* ignore rest of file if line too long */
533217309Snwhitehorn	    fprintf(stderr, "\nParse error: line %d of configuration"
534217309Snwhitehorn		    " file too long.\n", l);
535217309Snwhitehorn	    result = -1;	/* parse aborted */
536217309Snwhitehorn	    break;
537217309Snwhitehorn	}
538217309Snwhitehorn
539217309Snwhitehorn	lastch(str) = '\0';
540217309Snwhitehorn	if (begins_with(str, "bindkey", &params)) {
541251843Sbapt	    if (!dlg_parse_bindkey(params)) {
542251843Sbapt		fprintf(stderr, "\nParse error: line %d of configuration\n", l);
543251843Sbapt		result = -1;
544251843Sbapt	    }
545217309Snwhitehorn	    continue;
546217309Snwhitehorn	}
547217309Snwhitehorn	parse = parse_line(str, &var, &value);	/* parse current line */
548217309Snwhitehorn
549217309Snwhitehorn	switch (parse) {
550217309Snwhitehorn	case LINE_EMPTY:	/* ignore blank lines and comments */
551217309Snwhitehorn	    break;
552217309Snwhitehorn	case LINE_EQUALS:
553217309Snwhitehorn	    /* search table for matching config variable name */
554217309Snwhitehorn	    if ((i = find_vars(var)) >= 0) {
555217309Snwhitehorn		switch (vars[i].type) {
556217309Snwhitehorn		case VAL_INT:
557217309Snwhitehorn		    *((int *) vars[i].var) = atoi(value);
558217309Snwhitehorn		    break;
559217309Snwhitehorn		case VAL_STR:
560217309Snwhitehorn		    if (!isquote(value[0]) || !isquote(lastch(value))
561217309Snwhitehorn			|| strlen(value) < 2) {
562217309Snwhitehorn			fprintf(stderr, "\nParse error: string value "
563217309Snwhitehorn				"expected at line %d of configuration "
564217309Snwhitehorn				"file.\n", l);
565217309Snwhitehorn			result = -1;	/* parse aborted */
566217309Snwhitehorn		    } else {
567217309Snwhitehorn			/* remove the (") quotes */
568217309Snwhitehorn			value++;
569217309Snwhitehorn			lastch(value) = '\0';
570217309Snwhitehorn			strcpy((char *) vars[i].var, value);
571217309Snwhitehorn		    }
572217309Snwhitehorn		    break;
573217309Snwhitehorn		case VAL_BOOL:
574217309Snwhitehorn		    if (!dlg_strcmp(value, "ON"))
575217309Snwhitehorn			*((bool *) vars[i].var) = TRUE;
576217309Snwhitehorn		    else if (!dlg_strcmp(value, "OFF"))
577217309Snwhitehorn			*((bool *) vars[i].var) = FALSE;
578217309Snwhitehorn		    else {
579217309Snwhitehorn			fprintf(stderr, "\nParse error: boolean value "
580217309Snwhitehorn				"expected at line %d of configuration "
581217309Snwhitehorn				"file (found %s).\n", l, value);
582217309Snwhitehorn			result = -1;	/* parse aborted */
583217309Snwhitehorn		    }
584217309Snwhitehorn		    break;
585217309Snwhitehorn		}
586217309Snwhitehorn#ifdef HAVE_COLOR
587217309Snwhitehorn	    } else if ((i = find_color(var)) >= 0) {
588217309Snwhitehorn		int fg = 0;
589217309Snwhitehorn		int bg = 0;
590217309Snwhitehorn		int hl = 0;
591217309Snwhitehorn		if (str_to_attr(value, &fg, &bg, &hl) == -1) {
592217309Snwhitehorn		    fprintf(stderr, "\nParse error: attribute "
593217309Snwhitehorn			    "value expected at line %d of configuration "
594217309Snwhitehorn			    "file.\n", l);
595217309Snwhitehorn		    result = -1;	/* parse aborted */
596217309Snwhitehorn		} else {
597217309Snwhitehorn		    dlg_color_table[i].fg = fg;
598217309Snwhitehorn		    dlg_color_table[i].bg = bg;
599217309Snwhitehorn		    dlg_color_table[i].hilite = hl;
600217309Snwhitehorn		}
601217309Snwhitehorn	    } else {
602217309Snwhitehorn#endif /* HAVE_COLOR */
603217309Snwhitehorn		fprintf(stderr, "\nParse error: unknown variable "
604217309Snwhitehorn			"at line %d of configuration file:\n\t%s\n", l, var);
605217309Snwhitehorn		result = -1;	/* parse aborted */
606217309Snwhitehorn	    }
607217309Snwhitehorn	    break;
608217309Snwhitehorn	case LINE_ERROR:
609217309Snwhitehorn	    fprintf(stderr, "\nParse error: syntax error at line %d of "
610217309Snwhitehorn		    "configuration file.\n", l);
611217309Snwhitehorn	    result = -1;	/* parse aborted */
612217309Snwhitehorn	    break;
613217309Snwhitehorn	}
614217309Snwhitehorn	l++;			/* next line */
615217309Snwhitehorn    }
616217309Snwhitehorn
617217309Snwhitehorn    (void) fclose(rc_file);
618217309Snwhitehorn    return result;
619217309Snwhitehorn}
620