Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
  3.  * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
  4.  * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
  5.  * Copyright 2005 Richard Wilson <info@tinct.net>
  6.  *
  7.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  8.  *
  9.  * NetSurf is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; version 2 of the License.
  12.  *
  13.  * NetSurf is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20.  */
  21.  
  22. /** \file
  23.  * Option reading and saving (implementation).
  24.  *
  25.  * Options are stored in the format key:value, one per line. For bool options,
  26.  * value is "0" or "1".
  27.  */
  28.  
  29. #include <assert.h>
  30. #include <stdbool.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <strings.h>
  34.  
  35. #include "css/css.h"
  36. #include "desktop/plot_style.h"
  37. #include "utils/log.h"
  38. #include "utils/utils.h"
  39. #include "desktop/options.h"
  40.  
  41. struct ns_options nsoptions = {
  42.         NSOPTION_MAIN_DEFAULTS,
  43.         NSOPTION_SYS_COLOUR_DEFAULTS,
  44.         NSOPTION_EXTRA_DEFAULTS
  45. };
  46.  
  47. enum option_type_e {
  48.         OPTION_BOOL,
  49.         OPTION_INTEGER,
  50.         OPTION_STRING,
  51.         OPTION_COLOUR
  52. } ;
  53.  
  54. struct option_entry_s {
  55.         const char *key;
  56.         enum option_type_e type;
  57.         void *p;
  58. };
  59.  
  60. struct option_entry_s option_table[] = {
  61.         NSOPTION_MAIN_TABLE,
  62.         NSOPTION_EXTRA_TABLE
  63. };
  64.  
  65. #define option_table_entries (sizeof option_table / sizeof option_table[0])
  66.  
  67. /**
  68.  * Set an option value based on a string
  69.  */
  70. static bool
  71. strtooption(const char *value, struct option_entry_s *option_entry)
  72. {
  73.         bool ret = false;
  74.         colour rgbcolour; /* RRGGBB */
  75.  
  76.         switch (option_entry->type) {
  77.         case OPTION_BOOL:
  78.                 *((bool *)option_entry->p) = value[0] == '1';
  79.                 ret = true;
  80.                 break;
  81.  
  82.         case OPTION_INTEGER:
  83.                 *((int *)option_entry->p) = atoi(value);
  84.                 ret = true;
  85.                 break;
  86.  
  87.         case OPTION_COLOUR:
  88.                 sscanf(value, "%x", &rgbcolour);
  89.                 *((colour *)option_entry->p) =
  90.                         ((0x000000FF & rgbcolour) << 16) |
  91.                         ((0x0000FF00 & rgbcolour) << 0) |
  92.                         ((0x00FF0000 & rgbcolour) >> 16);
  93.                 ret = true;
  94.                 break;
  95.  
  96.         case OPTION_STRING:
  97.                 free(*((char **)option_entry->p));
  98.                 if (*value == 0) {
  99.                         /* do not allow empty strings in text options */
  100.                         *((char **)option_entry->p) = NULL;
  101.                 } else {
  102.                         *((char **)option_entry->p) = strdup(value);
  103.                 }
  104.                 ret = true;
  105.                 break;
  106.         }
  107.  
  108.         return ret;
  109. }
  110.  
  111. static void nsoptions_validate(struct ns_options *opts)
  112. {
  113.         if (opts->font_size < 50)
  114.                 opts->font_size = 50;
  115.  
  116.         if (1000 < opts->font_size)
  117.                 opts->font_size = 1000;
  118.  
  119.         if (opts->font_min_size < 10)
  120.                 opts->font_min_size = 10;
  121.  
  122.         if (500 < opts->font_min_size)
  123.                 opts->font_min_size = 500;
  124.  
  125.         if (opts->memory_cache_size < 0)
  126.                 opts->memory_cache_size = 0;
  127.  
  128. }
  129.  
  130. /* exported interface documented in options.h */
  131. void nsoption_read(const char *path)
  132. {
  133.         char s[100];
  134.         FILE *fp;
  135.  
  136.         if (path == NULL) {
  137.                 LOG(("No options loaded"));
  138.                 return;
  139.         }
  140.  
  141.         fp = fopen(path, "r");
  142.         if (!fp) {
  143.                 LOG(("failed to open file '%s'", path));
  144.                 return;
  145.         }
  146.  
  147.         while (fgets(s, 100, fp)) {
  148.                 char *colon, *value;
  149.                 unsigned int i;
  150.  
  151.                 if (s[0] == 0 || s[0] == '#')
  152.                         continue;
  153.                 colon = strchr(s, ':');
  154.                 if (colon == 0)
  155.                         continue;
  156.                 s[strlen(s) - 1] = 0;  /* remove \n at end */
  157.                 *colon = 0;  /* terminate key */
  158.                 value = colon + 1;
  159.  
  160.                 for (i = 0; i != option_table_entries; i++) {
  161.                         if (strcasecmp(s, option_table[i].key) != 0)
  162.                                 continue;
  163.  
  164.                         strtooption(value, option_table + i);
  165.                         break;
  166.                 }
  167.         }
  168.  
  169.         fclose(fp);
  170.  
  171.         nsoptions_validate(&nsoptions);
  172. }
  173.  
  174.  
  175. /* exported interface documented in options.h */
  176. void nsoption_write(const char *path)
  177. {
  178.         unsigned int entry;
  179.         FILE *fp;
  180.         colour rgbcolour; /* RRGGBB */
  181.  
  182.         fp = fopen(path, "w");
  183.         if (!fp) {
  184.                 LOG(("failed to open file '%s' for writing", path));
  185.                 return;
  186.         }
  187.  
  188.         for (entry = 0; entry != option_table_entries; entry++) {
  189.                 switch (option_table[entry].type) {
  190.                 case OPTION_BOOL:
  191.                         fprintf(fp, "%s:%c\n", option_table[entry].key,
  192.                                 *((bool *) option_table[entry].p) ? '1' : '0');
  193.                         break;
  194.  
  195.                 case OPTION_INTEGER:
  196.                         fprintf(fp, "%s:%i\n", option_table[entry].key,
  197.                                 *((int *) option_table[entry].p));
  198.                         break;
  199.  
  200.                 case OPTION_COLOUR:
  201.                         rgbcolour = ((0x000000FF & *((colour *)
  202.                                         option_table[entry].p)) << 16) |
  203.                                 ((0x0000FF00 & *((colour *)
  204.                                         option_table[entry].p)) << 0) |
  205.                                 ((0x00FF0000 & *((colour *)
  206.                                         option_table[entry].p)) >> 16);
  207.                         fprintf(fp, "%s:%06x\n", option_table[entry].key,
  208.                                 rgbcolour);
  209.                         break;
  210.  
  211.                 case OPTION_STRING:
  212.                         if (((*((char **) option_table[entry].p)) != NULL) &&
  213.                             (*(*((char **) option_table[entry].p)) != 0)) {
  214.                                 fprintf(fp, "%s:%s\n", option_table[entry].key,
  215.                                         *((char **) option_table[entry].p));
  216.                         }
  217.                         break;
  218.                 }
  219.         }
  220.  
  221.         fclose(fp);
  222. }
  223.  
  224.  
  225. /**
  226.  * Output an option value into a string, in HTML format.
  227.  *
  228.  * \param option  The option to output the value of.
  229.  * \param size    The size of the string buffer.
  230.  * \param pos     The current position in string
  231.  * \param string  The string in which to output the value.
  232.  * \return The number of bytes written to string or -1 on error
  233.  */
  234. static size_t
  235. nsoption_output_value_html(struct option_entry_s *option,
  236.                 size_t size, size_t pos, char *string)
  237. {
  238.         size_t slen = 0; /* length added to string */
  239.         colour rgbcolour; /* RRGGBB */
  240.  
  241.         switch (option->type) {
  242.         case OPTION_BOOL:
  243.                 slen = snprintf(string + pos, size - pos, "%s",
  244.                                 *((bool *)option->p) ? "true" : "false");
  245.                 break;
  246.  
  247.         case OPTION_INTEGER:
  248.                 slen = snprintf(string + pos, size - pos, "%i",
  249.                                 *((int *)option->p));
  250.                 break;
  251.  
  252.         case OPTION_COLOUR:
  253.                 rgbcolour = ((0x000000FF & *((colour *) option->p)) << 16) |
  254.                                 ((0x0000FF00 & *((colour *) option->p)) << 0) |
  255.                                 ((0x00FF0000 & *((colour *) option->p)) >> 16);
  256.                 slen = snprintf(string + pos, size - pos,
  257.                                 "<span style=\"background-color: #%06x; "
  258.                                 "color: #%06x;\">#%06x</span>", rgbcolour,
  259.                                 (~rgbcolour) & 0xffffff, rgbcolour);
  260.                 break;
  261.  
  262.         case OPTION_STRING:
  263.                 if (*((char **)option->p) != NULL) {
  264.                         slen = snprintf(string + pos, size - pos, "%s",
  265.                                         *((char **)option->p));
  266.                 } else {
  267.                         slen = snprintf(string + pos, size - pos,
  268.                                         "<span class=\"null-content\">NULL"
  269.                                         "</span>");
  270.                 }
  271.                 break;
  272.         }
  273.  
  274.         return slen;
  275. }
  276.  
  277.  
  278. /**
  279.  * Output an option value into a string, in plain text format.
  280.  *
  281.  * \param option  The option to output the value of.
  282.  * \param size    The size of the string buffer.
  283.  * \param pos     The current position in string
  284.  * \param string  The string in which to output the value.
  285.  * \return The number of bytes written to string or -1 on error
  286.  */
  287. static size_t
  288. nsoption_output_value_text(struct option_entry_s *option,
  289.                 size_t size, size_t pos, char *string)
  290. {
  291.         size_t slen = 0; /* length added to string */
  292.         colour rgbcolour; /* RRGGBB */
  293.  
  294.         switch (option->type) {
  295.         case OPTION_BOOL:
  296.                 slen = snprintf(string + pos, size - pos, "%c",
  297.                                 *((bool *)option->p) ? '1' : '0');
  298.                 break;
  299.  
  300.         case OPTION_INTEGER:
  301.                 slen = snprintf(string + pos, size - pos, "%i",
  302.                                 *((int *)option->p));
  303.                 break;
  304.  
  305.         case OPTION_COLOUR:
  306.                 rgbcolour = ((0x000000FF & *((colour *) option->p)) << 16) |
  307.                                 ((0x0000FF00 & *((colour *) option->p)) << 0) |
  308.                                 ((0x00FF0000 & *((colour *) option->p)) >> 16);
  309.                 slen = snprintf(string + pos, size - pos, "%06x", rgbcolour);
  310.                 break;
  311.  
  312.         case OPTION_STRING:
  313.                 if (*((char **)option->p) != NULL) {
  314.                         slen = snprintf(string + pos, size - pos, "%s",
  315.                                         *((char **)option->p));
  316.                 }
  317.                 break;
  318.         }
  319.  
  320.         return slen;
  321. }
  322.  
  323. /* exported interface documented in options.h */
  324. void
  325. nsoption_commandline(int *pargc, char **argv)
  326. {
  327.         char *arg;
  328.         char *val;
  329.         int arglen;
  330.         int idx = 1;
  331.         int mv_loop;
  332.  
  333.         unsigned int entry_loop;
  334.  
  335.         while (idx < *pargc) {
  336.                 arg = argv[idx];
  337.                 arglen = strlen(arg);
  338.  
  339.                 /* check we have an option */
  340.                 /* option must start -- and be as long as the shortest option*/
  341.                 if ((arglen < (2+5) ) || (arg[0] != '-') || (arg[1] != '-'))
  342.                         break;
  343.  
  344.                 arg += 2; /* skip -- */
  345.  
  346.                 val = strchr(arg, '=');
  347.                 if (val == NULL) {
  348.                         /* no equals sign - next parameter is val */
  349.                         idx++;
  350.                         if (idx >= *pargc)
  351.                                 break;
  352.                         val = argv[idx];
  353.                 } else {
  354.                         /* equals sign */
  355.                         arglen = val - arg ;
  356.                         val++;
  357.                 }
  358.  
  359.                 /* arg+arglen is the option to set, val is the value */
  360.  
  361.                 LOG(("%.*s = %s",arglen,arg,val));
  362.  
  363.                 for (entry_loop = 0;
  364.                      entry_loop < option_table_entries;
  365.                      entry_loop++) {
  366.                         if (strncmp(arg, option_table[entry_loop].key,
  367.                                     arglen) == 0) {
  368.                                 strtooption(val, option_table + entry_loop);
  369.                                 break;
  370.                         }                      
  371.                 }
  372.  
  373.                 idx++;
  374.         }
  375.  
  376.         /* remove processed options from argv */
  377.         for (mv_loop=0;mv_loop < (*pargc - idx); mv_loop++) {
  378.                 argv[mv_loop + 1] = argv[mv_loop + idx];
  379.         }
  380.         *pargc -= (idx - 1);
  381. }
  382.  
  383. /* exported interface documented in options.h */
  384. int
  385. nsoption_snoptionf(char *string, size_t size, unsigned int option, const char *fmt)
  386. {
  387.         size_t slen = 0; /* current output string length */
  388.         int fmtc = 0; /* current index into format string */
  389.         struct option_entry_s *option_entry;
  390.  
  391.         if (option >= option_table_entries)
  392.                 return -1;
  393.  
  394.         option_entry = option_table + option;
  395.  
  396.         while((slen < size) && (fmt[fmtc] != 0)) {
  397.                 if (fmt[fmtc] == '%') {
  398.                         fmtc++;
  399.                         switch (fmt[fmtc]) {
  400.                         case 'k':
  401.                                 slen += snprintf(string + slen, size - slen,
  402.                                                 "%s", option_entry->key);
  403.                                 break;
  404.  
  405.                         case 't':
  406.                                 switch (option_entry->type) {
  407.                                 case OPTION_BOOL:
  408.                                         slen += snprintf(string + slen,
  409.                                                          size - slen,
  410.                                                          "boolean");
  411.                                         break;
  412.  
  413.                                 case OPTION_INTEGER:
  414.                                         slen += snprintf(string + slen,
  415.                                                          size - slen,
  416.                                                          "integer");
  417.                                         break;
  418.  
  419.                                 case OPTION_COLOUR:
  420.                                         slen += snprintf(string + slen,
  421.                                                          size - slen,
  422.                                                          "colour");
  423.                                         break;
  424.  
  425.                                 case OPTION_STRING:
  426.                                         slen += snprintf(string + slen,
  427.                                                          size - slen,
  428.                                                          "string");
  429.                                         break;
  430.  
  431.                                 }
  432.                                 break;
  433.  
  434.  
  435.                         case 'V':
  436.                                 slen += nsoption_output_value_html(option_entry,
  437.                                                 size, slen, string);
  438.                                 break;
  439.                         case 'v':
  440.                                 slen += nsoption_output_value_text(option_entry,
  441.                                                 size, slen, string);
  442.                                 break;
  443.                         }
  444.                         fmtc++;
  445.                 } else {
  446.                         string[slen] = fmt[fmtc];
  447.                         slen++;
  448.                         fmtc++;
  449.                 }
  450.         }
  451.  
  452.         /* Ensure that we NUL-terminate the output */
  453.         string[min(slen, size - 1)] = '\0';
  454.  
  455.         return slen;
  456. }
  457.  
  458. /* exported interface documented in options.h */
  459. void
  460. nsoption_dump(FILE *outf)
  461. {
  462.         char buffer[256];
  463.         int opt_loop = 0;
  464.         int res;
  465.  
  466.         do {
  467.                 res = nsoption_snoptionf(buffer, sizeof buffer, opt_loop,
  468.                                 "%k:%v\n");
  469.                 if (res > 0) {
  470.                         fprintf(outf, "%s", buffer);
  471.                 }
  472.                 opt_loop++;
  473.         } while (res > 0);
  474. }
  475.  
  476.