home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / shell / dialog-0.000 / dialog-0 / dialog-0.6c / rc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-13  |  14.4 KB  |  603 lines

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