Logo Search packages:      
Sourcecode: eagle-usb version File versions  Download package

rc.c

/*
 *  $Id: rc.c,v 1.1 2004/02/15 13:21:43 Tux 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",
     &use_shadow,
     VAL_BOOL,
     "Shadow dialog boxes? This also turns on color."},

    {"use_colors",
     &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 int
str_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 int
parse_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
 */
void
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)
      exiterr("Error opening file for writing in 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", color_table[i].comment);
      fprintf(rc_file, "%s = %s\n", color_table[i].name,
            attr_to_str(buffer,
                      color_table[i].fg,
                      color_table[i].bg,
                      color_table[i].hilite));
    }

    (void) fclose(rc_file);
#endif
}

#ifdef HAVE_COLOR
static int
find_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 int
find_color(char *name)
{
    int result = -1;
    int i;
    int limit = dlg_color_count();

    for (i = 0; i < limit; i++) {
      if (dlg_strcmp(color_table[i].name, name) == 0) {
          result = i;
          break;
      }
    }
    return result;
}
#endif

/*
 * Parse the configuration file and set up variables
 */
int
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 */
                }
                color_table[i].fg = fg;
                color_table[i].bg = bg;
                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 */
}

Generated by  Doxygen 1.6.0   Back to index