📄 rc.c
字号:
/* * $Id: rc.c,v 1.19 2003/11/26 16:40:44 tom Exp $ * * rc.c -- routines for processing the configuration file * * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * and: Thomas E. Dickey * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "dialog.h"#ifdef HAVE_COLOR#include "colors.h"/* * For matching color names with color values */static const color_names_st color_names[] ={ {"BLACK", COLOR_BLACK}, {"RED", COLOR_RED}, {"GREEN", COLOR_GREEN}, {"YELLOW", COLOR_YELLOW}, {"BLUE", COLOR_BLUE}, {"MAGENTA", COLOR_MAGENTA}, {"CYAN", COLOR_CYAN}, {"WHITE", COLOR_WHITE},}; /* color names */#define GLOBALRC "/etc/dialogrc"#define DIALOGRC ".dialogrc"/* Types of values */#define VAL_INT 0#define VAL_STR 1#define VAL_BOOL 2/* Type of line in configuration file */#define LINE_BLANK 2#define LINE_COMMENT 1#define LINE_OK 0#define LINE_ERROR -1/* number of configuration variables */#define VAR_COUNT (sizeof(vars) / sizeof(vars_st))/* check if character is white space */#define whitespace(c) (c == ' ' || c == '\t')/* check if character is string quoting characters */#define isquote(c) (c == '"' || c == '\'')/* get last character of string */#define lastch(str) str[strlen(str)-1]/* * Configuration variables */typedef struct { const char *name; /* name of configuration variable as in DIALOGRC */ void *var; /* address of actual variable to change */ int type; /* type of value */ const char *comment; /* comment to put in "rc" file */} vars_st;static const vars_st vars[] ={ {"use_shadow", &dialog_state.use_shadow, VAL_BOOL, "Shadow dialog boxes? This also turns on color."}, {"use_colors", &dialog_state.use_colors, VAL_BOOL, "Turn color support ON or OFF"},}; /* vars *//* * Convert an attribute to a string representation like this: * * "(foreground,background,highlight)" */static char *attr_to_str(char *str, int fg, int bg, int hl){ int i; strcpy(str, "("); /* foreground */ for (i = 0; fg != color_names[i].value; i++) ; strcat(str, color_names[i].name); strcat(str, ","); /* background */ for (i = 0; bg != color_names[i].value; i++) ; strcat(str, color_names[i].name); /* highlight */ strcat(str, hl ? ",ON)" : ",OFF)"); return str;}/* * Extract the foreground, background and highlight values from an attribute * represented as a string in this form: * * "(foreground,background,highlight)" */static intstr_to_attr(char *str, int *fg, int *bg, int *hl){ int i = 0, j, get_fg = 1; char tempstr[MAX_LEN + 1], *part; if (str[0] != '(' || lastch(str) != ')') return -1; /* invalid representation */ /* remove the parenthesis */ strcpy(tempstr, str + 1); lastch(tempstr) = '\0'; /* get foreground and background */ while (1) { /* skip white space before fg/bg string */ while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++; if (tempstr[i] == '\0') return -1; /* invalid representation */ part = tempstr + i; /* set 'part' to start of fg/bg string */ /* find end of fg/bg string */ while (!whitespace(tempstr[i]) && tempstr[i] != ',' && tempstr[i] != '\0') i++; if (tempstr[i] == '\0') return -1; /* invalid representation */ else if (whitespace(tempstr[i])) { /* not yet ',' */ tempstr[i++] = '\0'; /* skip white space before ',' */ while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++; if (tempstr[i] != ',') return -1; /* invalid representation */ } tempstr[i++] = '\0'; /* skip the ',' */ for (j = 0; j < COLOR_COUNT && dlg_strcmp(part, color_names[j].name); j++) ; if (j == COLOR_COUNT) /* invalid color name */ return -1; if (get_fg) { *fg = color_names[j].value; get_fg = 0; /* next we have to get the background */ } else { *bg = color_names[j].value; break; } } /* got foreground and background */ /* get highlight */ /* skip white space before highlight string */ while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++; if (tempstr[i] == '\0') return -1; /* invalid representation */ part = tempstr + i; /* set 'part' to start of highlight string */ /* trim trailing white space from highlight string */ i = strlen(part) - 1; while (whitespace(part[i])) i--; part[i + 1] = '\0'; if (!dlg_strcmp(part, "ON")) *hl = TRUE; else if (!dlg_strcmp(part, "OFF")) *hl = FALSE; else return -1; /* invalid highlight value */ return 0;}/* * Parse a line in the configuration file * * Each line is of the form: "variable = value". On exit, 'var' will contain * the variable name, and 'value' will contain the value string. * * Return values: * * LINE_BLANK - line is blank * LINE_COMMENT - line is comment * LINE_OK - line is ok * LINE_ERROR - syntax error in line */static intparse_line(char *line, char **var, char **value){ int i = 0; /* ignore white space at beginning of line */ while (whitespace(line[i]) && line[i] != '\0') i++; if (line[i] == '\0') /* line is blank */ return LINE_BLANK; else if (line[i] == '#') /* line is comment */ return LINE_COMMENT; else if (line[i] == '=') /* variables names can't start with a '=' */ return LINE_ERROR; /* set 'var' to variable name */ *var = line + i++; /* skip to next character */ /* find end of variable name */ while (!whitespace(line[i]) && line[i] != '=' && line[i] != '\0') i++; if (line[i] == '\0') /* syntax error */ return LINE_ERROR; else if (line[i] == '=') line[i++] = '\0'; else { line[i++] = '\0'; /* skip white space before '=' */ while (whitespace(line[i]) && line[i] != '\0') i++; if (line[i] != '=') /* syntax error */ return LINE_ERROR; else i++; /* skip the '=' */ } /* skip white space after '=' */ while (whitespace(line[i]) && line[i] != '\0') i++; if (line[i] == '\0') return LINE_ERROR; else *value = line + i; /* set 'value' to value string */ /* trim trailing white space from 'value' */ i = strlen(*value) - 1; while (whitespace((*value)[i])) i--; (*value)[i + 1] = '\0'; return LINE_OK; /* no syntax error in line */}#endif/* * Create the configuration file */voiddlg_create_rc(const char *filename){#ifdef HAVE_COLOR char buffer[MAX_LEN + 1]; unsigned i, limit; FILE *rc_file; if ((rc_file = fopen(filename, "wt")) == NULL) dlg_exiterr("Error opening file for writing in dlg_create_rc()."); fprintf(rc_file, "#\\n# Run-time configuration file for dialog\\n#\\n# Automatically generated by \"dialog --create-rc <file>\"\\n#\\n#\\n# Types of values:\\n#\\n# Number - <number>\\n# String - \"string\"\\n# Boolean - <ON|OFF>\\n# Attribute - (foreground,background,highlight?)\\n#\n\n"); /* Print an entry for each configuration variable */ for (i = 0; i < VAR_COUNT; i++) { fprintf(rc_file, "\n# %s\n", vars[i].comment); switch (vars[i].type) { case VAL_INT: fprintf(rc_file, "%s = %d\n", vars[i].name, *((int *) vars[i].var)); break; case VAL_STR: fprintf(rc_file, "%s = \"%s\"\n", vars[i].name, (char *) vars[i].var); break; case VAL_BOOL: fprintf(rc_file, "%s = %s\n", vars[i].name, *((bool *) vars[i].var) ? "ON" : "OFF"); break; } } limit = dlg_color_count(); for (i = 0; i < limit; ++i) { fprintf(rc_file, "\n# %s\n", dlg_color_table[i].comment); fprintf(rc_file, "%s = %s\n", dlg_color_table[i].name, attr_to_str(buffer, dlg_color_table[i].fg, dlg_color_table[i].bg, dlg_color_table[i].hilite)); } (void) fclose(rc_file);#endif}#ifdef HAVE_COLORstatic intfind_vars(char *name){ int result = -1; unsigned i; for (i = 0; i < VAR_COUNT; i++) { if (dlg_strcmp(vars[i].name, name) == 0) { result = i; break; } } return result;}static intfind_color(char *name){ int result = -1; int i; int limit = dlg_color_count(); for (i = 0; i < limit; i++) { if (dlg_strcmp(dlg_color_table[i].name, name) == 0) { result = i; break; } } return result;}#endif/* * Parse the configuration file and set up variables */intdlg_parse_rc(void){#ifdef HAVE_COLOR int i; int l = 1, parse, fg, bg, hl; char str[MAX_LEN + 1], *var, *value, *tempptr; FILE *rc_file = 0; /* * At start, 'dialog' determines the settings to use as follows: * * a) if environment variable DIALOGRC is set, it's value determines the * name of the configuration file. * * b) if the file in (a) can't be found, use the file $HOME/.dialogrc * as the configuration file. * * c) if the file in (b) can't be found, try using the GLOBALRC file. * Usually this will be /etc/dialogrc. * * d) if the file in (c) can't be found, use compiled in defaults. * */ /* try step (a) */ if ((tempptr = getenv("DIALOGRC")) != NULL) rc_file = fopen(tempptr, "rt"); if (tempptr == NULL || rc_file == NULL) { /* step (a) failed? */ /* try step (b) */ if ((tempptr = getenv("HOME")) != NULL) { if (tempptr[0] == '\0' || lastch(tempptr) == '/') sprintf(str, "%s%s", tempptr, DIALOGRC); else sprintf(str, "%s/%s", tempptr, DIALOGRC); rc_file = fopen(str, "rt"); } } if (tempptr == NULL || rc_file == NULL) { /* step (b) failed? */ /* try step (c) */ sprintf(str, "%s", GLOBALRC); if ((rc_file = fopen(str, "rt")) == NULL) return 0; /* step (c) failed, use default values */ } /* Scan each line and set variables */ while (fgets(str, MAX_LEN, rc_file) != NULL) { if (lastch(str) != '\n') { /* ignore rest of file if line too long */ fprintf(stderr, "\nParse error: line %d of configuration" " file too long.\n", l); (void) fclose(rc_file); return -1; /* parse aborted */ } else { lastch(str) = '\0'; parse = parse_line(str, &var, &value); /* parse current line */ switch (parse) { case LINE_BLANK: /* ignore blank lines and comments */ case LINE_COMMENT: break; case LINE_OK: /* search table for matching config variable name */ if ((i = find_vars(var)) >= 0) { switch (vars[i].type) { case VAL_INT: *((int *) vars[i].var) = atoi(value); break; case VAL_STR: if (!isquote(value[0]) || !isquote(lastch(value)) || strlen(value) < 2) { fprintf(stderr, "\nParse error: string value " "expected at line %d of configuration " "file.\n", l); return -1; /* parse aborted */ } else { /* remove the (") quotes */ value++; lastch(value) = '\0'; strcpy((char *) vars[i].var, value); } break; case VAL_BOOL: if (!dlg_strcmp(value, "ON")) *((bool *) vars[i].var) = TRUE; else if (!dlg_strcmp(value, "OFF")) *((bool *) vars[i].var) = FALSE; else { fprintf(stderr, "\nParse error: boolean value " "expected at line %d of configuration " "file (found %s).\n", l, value); return -1; /* parse aborted */ } break; } } else if ((i = find_color(var)) >= 0) { if (str_to_attr(value, &fg, &bg, &hl) == -1) { fprintf(stderr, "\nParse error: attribute " "value expected at line %d of configuration " "file.\n", l); return -1; /* parse aborted */ } dlg_color_table[i].fg = fg; dlg_color_table[i].bg = bg; dlg_color_table[i].hilite = hl; } else { fprintf(stderr, "\nParse error: unknown variable " "at line %d of configuration file:\n\t%s\n", l, var); return -1; /* parse aborted */ } break; case LINE_ERROR: fprintf(stderr, "\nParse error: syntax error at line %d of " "configuration file.\n", l); return -1; /* parse aborted */ } } l++; /* next line */ } (void) fclose(rc_file);#endif return 0; /* parse successful */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -