changeset 1053:64e078b7a711

Refactor the preferences parser
author Tim Nieradzik, Jorge Arellano Cid
date Tue, 28 Apr 2009 08:32:47 -0400
parents 1e9c9cd8be73
children 7fd3f0a48588
files dlib/dlib.c dlib/dlib.h dpid/dpid.c lout/msg.h src/Makefile.am src/dillo.cc src/dir.c src/dir.h src/paths.cc src/paths.hh src/prefs.c src/prefs.h src/prefsparser.cc src/prefsparser.hh src/uicmd.cc
diffstat 15 files changed, 445 insertions(+), 409 deletions(-) [+]
line wrap: on
line diff
--- a/dlib/dlib.c	Fri Apr 24 14:43:15 2009 +0000
+++ b/dlib/dlib.c	Tue Apr 28 08:32:47 2009 -0400
@@ -758,9 +758,10 @@
  *    - line is modified!
  *    - it skips blank lines and lines starting with '#'
  *
- * Return value: 0 on successful value/pair, -1 otherwise
+ * Return value: 1 on blank line or comment, 0 on successful value/pair,
+ *              -1 otherwise.
  */
-int dParser_get_rc_pair(char **line, char **name, char **value)
+int dParser_parse_rc_line(char **line, char **name, char **value)
 {
    char *eq, *p;
    int len, ret = -1;
@@ -770,7 +771,10 @@
    *name = NULL;
    *value = NULL;
    dStrstrip(*line);
-   if (*line[0] != '#' && (eq = strchr(*line, '='))) {
+   if (!*line[0] || *line[0] == '#') {
+      /* blank line or comment */
+      ret = 1;
+   } else if ((eq = strchr(*line, '='))) {
       /* get name */
       for (p = *line; *p && *p != '=' && !isspace(*p); ++p);
       *p = 0;
--- a/dlib/dlib.h	Fri Apr 24 14:43:15 2009 +0000
+++ b/dlib/dlib.h	Tue Apr 28 08:32:47 2009 -0400
@@ -158,7 +158,7 @@
 /*
  *- Parse function ------------------------------------------------------------
  */
-int dParser_get_rc_pair(char **line, char **name, char **value);
+int dParser_parse_rc_line(char **line, char **name, char **value);
 
 /*
  *- Misc utility functions ----------------------------------------------------
--- a/dpid/dpid.c	Fri Apr 24 14:43:15 2009 +0000
+++ b/dpid/dpid.c	Tue Apr 28 08:32:47 2009 -0400
@@ -433,9 +433,8 @@
 int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list)
 {
    FILE *dpidrc_stream;
-   char *p, *line = NULL;
-   char *service, *path;
-   int i;
+   char *p, *line = NULL, *service, *path;
+   int i, st;
    struct service *s;
    char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL;
 
@@ -479,15 +478,17 @@
 
    /* dpidrc parser loop */
    while ((line = dGetline(dpidrc_stream)) != NULL) {
-
-      if (dParser_get_rc_pair(&line, &service, &path) == -1) {
-         if (line[0] && line[0] != '#' && (!service || !path)) {
-            MSG_ERR("Syntax error in %s: service=\"%s\" path=\"%s\"\n",
-                    dpidrc, service, path);
-         }
+      st = dParser_parse_rc_line(&line, &service, &path);
+      if (st < 0) {
+         MSG_ERR("dpid: Syntax error in %s: service=\"%s\" path=\"%s\"\n",
+                 dpidrc, service, path);
+         continue;
+      } else if (st != 0) {
          continue;
       }
 
+      _MSG("dpid: service=%s, path=%s\n", service, path);
+
       /* ignore dpi_dir silently */
       if (strcmp(service, "dpi_dir") == 0)
          continue;
@@ -506,6 +507,7 @@
       /* if the dpi exist bind service and dpi */
       if (i < numdpis)
          s->dp_index = i;
+
       dFree(line);
    }
    fclose(dpidrc_stream);
--- a/lout/msg.h	Fri Apr 24 14:43:15 2009 +0000
+++ b/lout/msg.h	Tue Apr 28 08:32:47 2009 -0400
@@ -3,7 +3,6 @@
 
 #include <stdio.h>
 
-/*#include "prefs.h"*/
 #define prefs_show_msg    1
 
 #define D_STMT_START      do
--- a/src/Makefile.am	Fri Apr 24 14:43:15 2009 +0000
+++ b/src/Makefile.am	Tue Apr 28 08:32:47 2009 -0400
@@ -18,8 +18,8 @@
 
 dillo_SOURCES = \
 	dillo.cc \
-	dir.c \
-	dir.h \
+	paths.c \
+	paths.h \
 	ui.cc \
 	ui.hh \
 	uicmd.cc \
@@ -39,6 +39,8 @@
 	history.c \
 	prefs.c \
 	prefs.h \
+	prefsparser.cc \
+	prefsparser.hh \
 	msg.h \
 	list.h \
 	url.c \
--- a/src/dillo.cc	Fri Apr 24 14:43:15 2009 +0000
+++ b/src/dillo.cc	Tue Apr 28 08:32:47 2009 -0400
@@ -29,10 +29,11 @@
 #include <fltk/run.h>
 
 #include "msg.h"
-#include "dir.h"
+#include "paths.hh"
 #include "uicmd.hh"
 
 #include "prefs.h"
+#include "prefsparser.hh"
 #include "bw.h"
 #include "misc.h"
 #include "nav.h"
@@ -177,7 +178,8 @@
    DilloUrl *start_url;
 
    /* Relative path to a local file? */
-   p = (*str == '/') ? dStrdup(str) : dStrconcat(a_Dir_get_owd(),"/",str,NULL);
+   p = (*str == '/') ? dStrdup(str) :
+                       dStrconcat(Paths::getOldWorkingDir(), "/", str, NULL);
 
    if (access(p, F_OK) == 0) {
       /* absolute path may have non-URL characters */
@@ -206,9 +208,11 @@
    uint options_got = 0;
    uint32_t xid = 0;
    int idx = 1;
-   int xpos = D_GEOMETRY_DEFAULT_XPOS, ypos = D_GEOMETRY_DEFAULT_YPOS;
-   int width = D_GEOMETRY_DEFAULT_WIDTH, height = D_GEOMETRY_DEFAULT_HEIGHT;
+   int xpos = PREFS_GEOMETRY_DEFAULT_XPOS, ypos = PREFS_GEOMETRY_DEFAULT_YPOS,
+       width = PREFS_GEOMETRY_DEFAULT_WIDTH,
+       height = PREFS_GEOMETRY_DEFAULT_HEIGHT;
    char **opt_argv;
+   FILE *fp;
 
    srand((uint_t)(time(0) ^ getpid()));
 
@@ -254,10 +258,18 @@
    }
    dFree(opt_argv);
 
-   // Initialize internal modules
-   a_Dir_init();
+   // create ~/.dillo if not present
+   Paths::init();
+
+   // set the default values for the preferences
    a_Prefs_init();
-   a_Dir_check_dillorc_directory(); /* and create if not present */
+
+   // parse dillorc
+   if ((fp = Paths::getPrefsFP(PATHS_RC_PREFS))) {
+      PrefsParser::parse(fp);
+   }
+
+   // initialize internal modules
    a_Dpi_init();
    a_Dns_init();
    a_Web_init();
--- a/src/dir.c	Fri Apr 24 14:43:15 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * File: dir.c
- *
- * Copyright 2006-2007 Jorge Arellano Cid <jcid@dillo.org>
- *
- * 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 3 of the License, or
- * (at your option) any later version.
- */
-
-#include <unistd.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include "msg.h"
-#include "../dlib/dlib.h"
-
-
-/*
- * Local data
- */
-/* Dillo works from an unmounted directory (/tmp). */
-static char *OldWorkingDirectory = NULL;
-
-/*
- * Change current working directory to "/tmp".
- */
-void a_Dir_init(void)
-{
-   dFree(OldWorkingDirectory);
-   OldWorkingDirectory = dGetcwd();
-   chdir("/tmp");
-}
-
-/*
- * Return the initial current working directory in a string.
- */
-char *a_Dir_get_owd(void)
-{
-   return OldWorkingDirectory;
-}
-
-/*
- * Free memory
- */
-void a_Dir_free(void)
-{
-   dFree(OldWorkingDirectory);
-}
-
-/*
- * Check if '~/.dillo' directory exists.
- * If not, try to create it.
- */
-void a_Dir_check_dillorc_directory(void)
-{
-   char *dir;
-   struct stat st;
-
-   dir = dStrconcat(dGethomedir(), "/.dillo", NULL);
-   if (stat(dir, &st) == -1) {
-      if (errno == ENOENT) {
-         MSG("Dillo: creating directory %s.\n", dir);
-         if (mkdir(dir, 0700) < 0) {
-            MSG("Dillo: error creating directory %s: %s\n", dir,
-                dStrerror(errno));
-         }
-      } else {
-         MSG("Dillo: error reading %s: %s\n", dir, dStrerror(errno));
-      }
-   }
-   dFree(dir);
-}
-
--- a/src/dir.h	Fri Apr 24 14:43:15 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#ifndef __DIR_H__
-#define __DIR_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-void a_Dir_init(void);
-char *a_Dir_get_owd(void);
-void a_Dir_free(void);
-void a_Dir_check_dillorc_directory(void);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __DIR_H__ */
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/paths.cc	Tue Apr 28 08:32:47 2009 -0400
@@ -0,0 +1,96 @@
+/*
+ * File: paths.cc
+ *
+ * Copyright 2006-2009 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "msg.h"
+#include "../dlib/dlib.h"
+#include "paths.hh"
+
+/*
+ * Local data
+ */
+
+// Dillo works from an unmounted directory (/tmp)
+static char* oldWorkingDir = NULL;
+
+/*
+ * Changes current working directory to /tmp and creates ~/.dillo
+ * if not exists.
+ */
+void Paths::init(void)
+{
+   char *path;
+   struct stat st;
+
+   dFree(oldWorkingDir);
+   oldWorkingDir = dGetcwd();
+   chdir("/tmp");
+
+   path = dStrconcat(dGethomedir(), "/.dillo", NULL);
+   if (stat(path, &st) == -1) {
+      if (errno == ENOENT) {
+         MSG("paths: creating directory %s.\n", path);
+         if (mkdir(path, 0700) < 0) {
+            MSG("paths: error creating directory %s: %s\n",
+                path, dStrerror(errno));
+         }
+      } else {
+         MSG("Dillo: error reading %s: %s\n", path, dStrerror(errno));
+      }
+   }
+
+   dFree(path);
+}
+
+/*
+ * Return the initial current working directory in a string.
+ */
+char *Paths::getOldWorkingDir(void)
+{
+   return oldWorkingDir;
+}
+
+/*
+ * Free memory
+ */
+void Paths::free(void)
+{
+   dFree(oldWorkingDir);
+}
+
+/*
+ * Examines the path for "rcFile" and assign its file pointer to "fp".
+ */
+FILE *Paths::getPrefsFP(const char *rcFile)
+{
+   FILE *fp;
+   char *path = dStrconcat(dGethomedir(), "/.dillo/", rcFile, NULL);
+
+   if (!(fp = fopen(path, "r"))) {
+      MSG("paths: Cannot open file '%s'\n", path);
+
+      char *path2 = dStrconcat(PATHS_RC_SYS, rcFile, NULL);
+      if (!(fp = fopen(path2, "r"))) {
+         MSG("paths: Cannot open file '%s'\n",path2);
+         MSG("paths: Using internal defaults...\n");
+      } else {
+         MSG("paths: Using %s\n", path);
+      }
+      dFree(path2);
+   }
+
+   dFree(path);
+   return fp;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/paths.hh	Tue Apr 28 08:32:47 2009 -0400
@@ -0,0 +1,27 @@
+/*
+ * File: paths.hh
+ *
+ * Copyright 2006-2009 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __PATHS_HH__
+#define __PATHS_HH__
+
+#define PATHS_RC_PREFS  "dillorc"
+#define PATHS_RC_KEYS   "keysrc"
+#define PATHS_RC_SYS    "/etc/dillo/"
+
+class Paths {
+public:
+   static void init(void);
+   static void free(void);
+   static char *getOldWorkingDir(void);
+   static FILE *getPrefsFP(const char *rcFile);
+};
+
+#endif /* __PATHS_HH__ */
--- a/src/prefs.c	Fri Apr 24 14:43:15 2009 +0000
+++ b/src/prefs.c	Tue Apr 28 08:32:47 2009 -0400
@@ -1,274 +1,53 @@
 /*
- * Preferences for dillo
+ * Preferences
  *
- * Copyright (C) 2006-2007 Jorge Arellano Cid <jcid@dillo.org>
+ * Copyright (C) 2006-2009 Jorge Arellano Cid <jcid@dillo.org>
  *
  * 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 3 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, see <http://www.gnu.org/licenses/>.
  */
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>       /* for strchr */
-#include <fcntl.h>
-#include <unistd.h>
-#include <locale.h>       /* for setlocale */
-#include <ctype.h>        /* for isspace */
 #include "prefs.h"
-#include "misc.h"
-#include "msg.h"
-
-#define RCNAME "dillorc"
-
-#define DILLO_START_PAGE "about:splash"
-#define DILLO_HOME "http://www.dillo.org/"
-
-#define D_FONT_SERIF "DejaVu Serif"
-#define D_FONT_SANS_SERIF "DejaVu Sans"
-#define D_FONT_CURSIVE "DejaVu Sans" /* \todo find good default */
-#define D_FONT_FANTASY "DejaVu Sans" /* \todo find good default */
-#define D_FONT_MONOSPACE "DejaVu Sans Mono"
-#define D_SEARCH_URL "http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s"
-#define D_SAVE_DIR "/tmp/"
 
 /*-----------------------------------------------------------------------------
  * Global Data
  *---------------------------------------------------------------------------*/
 DilloPrefs prefs;
 
-/*-----------------------------------------------------------------------------
- * Local types
- *---------------------------------------------------------------------------*/
-
-typedef enum {
-   PREFS_BOOL,
-   PREFS_STRING,
-   PREFS_URL,
-   PREFS_INT32,
-   PREFS_DOUBLE,
-   PREFS_GEOMETRY,
-   PREFS_PANEL_SIZE
-} PrefType_t;
-
-typedef struct SymNode_ {
-   char *name;
-   void *pref;
-   PrefType_t type;
-} SymNode_t;
-
-/*
- *- Mini parser -------------------------------------------------------------
- */
-
-/*
- * Comparison function for binary search
- */
-static int Prefs_symbol_cmp(const void *a, const void *b)
-{
-   return strcmp(((SymNode_t*)a)->name, ((SymNode_t*)b)->name);
-}
-
 /*
- * Parse a name/value pair and set preferences accordingly.
- */
-static int Prefs_parse_pair(char *name, char *value, const SymNode_t *symbols,
-                            int n_symbols)
-{
-   SymNode_t key, *node;
-
-   key.name = name;
-   node = bsearch(&key, symbols, n_symbols,
-                  sizeof(SymNode_t), Prefs_symbol_cmp);
-   if (!node) {
-      MSG("prefs: {%s} is not a recognized token.\n", name);
-      return -1;
-   }
-
-   switch (node->type) {
-   case PREFS_BOOL:
-      *(bool_t *)node->pref = strcmp(value, "YES") == 0;
-      break;
-   case PREFS_STRING:
-      dFree(*(char **)node->pref);
-      *(char **)node->pref = dStrdup(value);
-      break;
-   case PREFS_URL:
-      a_Url_free(*(DilloUrl **)node->pref);
-      *(DilloUrl **)node->pref = a_Url_new(value, NULL);
-      break;
-   case PREFS_INT32:
-      *(int32_t *)node->pref = strtol(value, NULL, 10);
-      break;
-   case PREFS_DOUBLE:
-      *(double *)node->pref = strtod(value, NULL);
-      break;
-   case PREFS_GEOMETRY:
-      a_Misc_parse_geometry(value, &prefs.xpos, &prefs.ypos,
-                            &prefs.width, &prefs.height);
-      break;
-   case PREFS_PANEL_SIZE:
-      if (!dStrcasecmp(value, "tiny"))
-         prefs.panel_size = P_tiny;
-      else if (!dStrcasecmp(value, "small"))
-         prefs.panel_size = P_small;
-      else if (!dStrcasecmp(value, "large"))
-         prefs.panel_size = P_large;
-      else /* default to "medium" */
-         prefs.panel_size = P_medium;
-      break;
-   default:
-      MSG_WARN("prefs: {%s} IS recognized but not handled!\n", name);
-      break;   /* Not reached */
-   }
-
-   return 0;
-}
-
-/*
- * Parse dillorc and set the values in the prefs structure.
+ * Sets the default settings.
  */
-static int Prefs_parse_dillorc(void)
-{
-   /* Symbol array, sorted alphabetically */
-   const SymNode_t symbols[] = {
-   { "allow_white_bg", &prefs.allow_white_bg, PREFS_BOOL },
-   { "buffered_drawing", &prefs.buffered_drawing, PREFS_INT32 },
-   { "contrast_visited_color", &prefs.contrast_visited_color, PREFS_BOOL },
-   { "enterpress_forces_submit", &prefs.enterpress_forces_submit, PREFS_BOOL },
-   { "focus_new_tab", &prefs.focus_new_tab, PREFS_BOOL },
-   { "font_cursive", &prefs.font_cursive, PREFS_STRING },
-   { "font_factor", &prefs.font_factor, PREFS_DOUBLE },
-   { "font_fantasy", &prefs.font_fantasy, PREFS_STRING },
-   { "font_max_size", &prefs.font_max_size, PREFS_INT32 },
-   { "font_min_size", &prefs.font_min_size, PREFS_INT32 },
-   { "font_monospace", &prefs.font_monospace, PREFS_STRING },
-   { "font_sans_serif", &prefs.font_sans_serif, PREFS_STRING },
-   { "font_serif", &prefs.font_serif, PREFS_STRING },
-   { "fullwindow_start", &prefs.fullwindow_start, PREFS_BOOL },
-   { "geometry", NULL, PREFS_GEOMETRY },
-   { "home", &prefs.home, PREFS_URL },
-   { "http_language", &prefs.http_language, PREFS_STRING },
-   { "http_proxy", &prefs.http_proxy, PREFS_URL },
-   { "http_proxyuser", &prefs.http_proxyuser, PREFS_STRING },
-   { "http_referer", &prefs.http_referer, PREFS_STRING },
-   { "limit_text_width", &prefs.limit_text_width, PREFS_BOOL },
-   { "load_images", &prefs.load_images, PREFS_BOOL },
-   { "load_stylesheets", &prefs.load_stylesheets, PREFS_BOOL },
-   { "middle_click_drags_page", &prefs.middle_click_drags_page, PREFS_BOOL },
-   { "middle_click_opens_new_tab", &prefs.middle_click_opens_new_tab,
-     PREFS_BOOL },
-   { "no_proxy", &prefs.no_proxy, PREFS_STRING },
-   { "panel_size", &prefs.panel_size, PREFS_PANEL_SIZE },
-   { "parse_embedded_css", &prefs.parse_embedded_css, PREFS_BOOL },
-   { "save_dir", &prefs.save_dir, PREFS_STRING },
-   { "search_url", &prefs.search_url, PREFS_STRING },
-   { "show_back", &prefs.show_back, PREFS_BOOL },
-   { "show_bookmarks", &prefs.show_bookmarks, PREFS_BOOL },
-   { "show_clear_url", &prefs.show_clear_url, PREFS_BOOL },
-   { "show_extra_warnings", &prefs.show_extra_warnings, PREFS_BOOL },
-   { "show_filemenu", &prefs.show_filemenu, PREFS_BOOL },
-   { "show_forw", &prefs.show_forw, PREFS_BOOL },
-   { "show_home", &prefs.show_home, PREFS_BOOL },
-   { "show_msg", &prefs.show_msg, PREFS_BOOL },
-   { "show_progress_box", &prefs.show_progress_box, PREFS_BOOL },
-   { "show_reload", &prefs.show_reload, PREFS_BOOL },
-   { "show_save", &prefs.show_save, PREFS_BOOL },
-   { "show_search", &prefs.show_search, PREFS_BOOL },
-   { "show_stop", &prefs.show_stop, PREFS_BOOL },
-   { "show_tools", &prefs.show_tools, PREFS_BOOL },
-   { "show_tooltip", &prefs.show_tooltip, PREFS_BOOL },
-   { "show_url", &prefs.show_url, PREFS_BOOL },
-   { "small_icons", &prefs.small_icons, PREFS_BOOL },
-   { "start_page", &prefs.start_page, PREFS_URL },
-   { "w3c_plus_heuristics", &prefs.w3c_plus_heuristics, PREFS_BOOL }
-   };
-
-   const uint_t n_symbols = sizeof (symbols) / sizeof (symbols[0]);
-
-   FILE *F_in;
-   char *filename, *line, *name, *value;
-   int ret = -1;
-
-   filename = dStrconcat(dGethomedir(), "/.dillo/", RCNAME, NULL);
-   if (!(F_in = fopen(filename, "r"))) {
-      MSG("prefs: Can't open %s file: %s\n", RCNAME, filename);
-      if (!(F_in = fopen(DILLORC_SYS, "r"))) {
-         MSG("prefs: Can't open %s file: %s\n", RCNAME, DILLORC_SYS);
-         MSG("prefs: Using internal defaults.\n");
-      } else {
-         MSG("prefs: Using %s\n", DILLORC_SYS);
-      }
-   }
-
-   if (F_in) {
-      /* scan dillorc line by line */
-      while ((line = dGetline(F_in)) != NULL) {
-         if (dParser_get_rc_pair(&line, &name, &value) == 0) {
-            _MSG("{%s}, {%s}\n", name, value);
-            Prefs_parse_pair(name, value, symbols, n_symbols);
-         } else if (line[0] && line[0] != '#' && (!name || !value)) {
-            MSG("prefs: Syntax error in %s: name=\"%s\" value=\"%s\"\n",
-                RCNAME, name, value);
-         }
-         dFree(line);
-      }
-      fclose(F_in);
-      ret = 0;
-   }
-   dFree(filename);
-
-   if (prefs.limit_text_width) {
-      /* BUG: causes 100% CPU usage with <button> or <input type="image"> */
-      MSG_WARN("Disabling limit_text_width preference (currently broken).\n");
-      prefs.limit_text_width = FALSE;
-   }
-
-   return ret;
-}
-
-/*---------------------------------------------------------------------------*/
 
 void a_Prefs_init(void)
 {
-   char *old_locale;
-
    prefs.allow_white_bg = TRUE;
-   prefs.buffered_drawing=1;
+   prefs.buffered_drawing = 1;
    prefs.contrast_visited_color = TRUE;
    prefs.enterpress_forces_submit = FALSE;
    prefs.focus_new_tab = TRUE;
-   prefs.font_cursive = dStrdup(D_FONT_CURSIVE);
+   prefs.font_cursive = dStrdup(PREFS_FONT_CURSIVE);
    prefs.font_factor = 1.0;
    prefs.font_max_size = 100;
    prefs.font_min_size = 6;
-   prefs.font_fantasy = dStrdup(D_FONT_FANTASY);
-   prefs.font_monospace = dStrdup(D_FONT_MONOSPACE);
-   prefs.font_sans_serif = dStrdup(D_FONT_SANS_SERIF);
-   prefs.font_serif = dStrdup(D_FONT_SERIF);
-   prefs.fullwindow_start=FALSE;
+   prefs.font_fantasy = dStrdup(PREFS_FONT_FANTASY);
+   prefs.font_monospace = dStrdup(PREFS_FONT_MONOSPACE);
+   prefs.font_sans_serif = dStrdup(PREFS_FONT_SANS_SERIF);
+   prefs.font_serif = dStrdup(PREFS_FONT_SERIF);
+   prefs.fullwindow_start = FALSE;
 
    /* these four constitute the geometry */
-   prefs.width = D_GEOMETRY_DEFAULT_WIDTH;
-   prefs.height = D_GEOMETRY_DEFAULT_HEIGHT;
-   prefs.xpos = D_GEOMETRY_DEFAULT_XPOS;
-   prefs.ypos = D_GEOMETRY_DEFAULT_YPOS;
+   prefs.width = PREFS_GEOMETRY_DEFAULT_WIDTH;
+   prefs.height = PREFS_GEOMETRY_DEFAULT_HEIGHT;
+   prefs.xpos = PREFS_GEOMETRY_DEFAULT_XPOS;
+   prefs.ypos = PREFS_GEOMETRY_DEFAULT_YPOS;
 
-   prefs.home = a_Url_new(DILLO_HOME, NULL);
+   prefs.home = a_Url_new(PREFS_HOME, NULL);
    prefs.http_language = NULL;
    prefs.http_proxy = NULL;
    prefs.http_proxyuser = NULL;
-   prefs.http_referer = dStrdup("host");
+   prefs.http_referer = dStrdup(PREFS_HTTP_REFERER);
    prefs.limit_text_width = FALSE;
    prefs.load_images=TRUE;
    prefs.load_stylesheets=TRUE;
@@ -277,58 +56,26 @@
    prefs.no_proxy = NULL;
    prefs.panel_size = P_medium;
    prefs.parse_embedded_css=TRUE;
-   prefs.save_dir = dStrdup(D_SAVE_DIR);
-   prefs.search_url = dStrdup(D_SEARCH_URL);
-   prefs.show_back=TRUE;
-   prefs.show_bookmarks=TRUE;
-   prefs.show_clear_url=TRUE;
+   prefs.save_dir = dStrdup(PREFS_SAVE_DIR);
+   prefs.search_url = dStrdup(PREFS_SEARCH_URL);
+   prefs.show_back = TRUE;
+   prefs.show_bookmarks = TRUE;
+   prefs.show_clear_url = TRUE;
    prefs.show_extra_warnings = FALSE;
    prefs.show_filemenu=TRUE;
-   prefs.show_forw=TRUE;
-   prefs.show_home=TRUE;
+   prefs.show_forw = TRUE;
+   prefs.show_home = TRUE;
    prefs.show_msg = TRUE;
-   prefs.show_progress_box=TRUE;
-   prefs.show_reload=TRUE;
-   prefs.show_save=TRUE;
-   prefs.show_search=TRUE;
-   prefs.show_stop=TRUE;
-   prefs.show_tools=TRUE;
+   prefs.show_progress_box = TRUE;
+   prefs.show_reload = TRUE;
+   prefs.show_save = TRUE;
+   prefs.show_search = TRUE;
+   prefs.show_stop = TRUE;
+   prefs.show_tools = TRUE;
    prefs.show_tooltip = TRUE;
-   prefs.show_url=TRUE;
+   prefs.show_url = TRUE;
    prefs.small_icons = FALSE;
-   prefs.start_page = a_Url_new(DILLO_START_PAGE, NULL);
+   prefs.start_page = a_Url_new(PREFS_START_PAGE, NULL);
    prefs.w3c_plus_heuristics = TRUE;
-
-   /* this locale stuff is to avoid parsing problems with float numbers */
-   old_locale = dStrdup (setlocale (LC_NUMERIC, NULL));
-   setlocale (LC_NUMERIC, "C");
-
-   Prefs_parse_dillorc();
-
-   setlocale (LC_NUMERIC, old_locale);
-   dFree (old_locale);
-
 }
 
-/*
- *  Preferences memory-deallocation
- *  (Call this one at exit time)
- */
-void a_Prefs_freeall(void)
-{
-   dFree(prefs.font_cursive);
-   dFree(prefs.font_fantasy);
-   dFree(prefs.font_monospace);
-   dFree(prefs.font_sans_serif);
-   dFree(prefs.font_serif);
-   dFree(prefs.http_language);
-   dFree(prefs.http_proxyuser);
-   dFree(prefs.http_referer);
-   dFree(prefs.no_proxy);
-   dFree(prefs.save_dir);
-   dFree(prefs.search_url);
-
-   a_Url_free(prefs.home);
-   a_Url_free(prefs.http_proxy);
-   a_Url_free(prefs.start_page);
-}
--- a/src/prefs.h	Fri Apr 24 14:43:15 2009 +0000
+++ b/src/prefs.h	Tue Apr 28 08:32:47 2009 -0400
@@ -1,3 +1,14 @@
+/*
+ * Preferences
+ *
+ * Copyright (C) 2006-2009 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ */
+
 #ifndef __PREFS_H__
 #define __PREFS_H__
 
@@ -7,10 +18,21 @@
 extern "C" {
 #endif /* __cplusplus */
 
-#define D_GEOMETRY_DEFAULT_WIDTH   780
-#define D_GEOMETRY_DEFAULT_HEIGHT  580
-#define D_GEOMETRY_DEFAULT_XPOS  -9999
-#define D_GEOMETRY_DEFAULT_YPOS  -9999
+#define PREFS_GEOMETRY_DEFAULT_WIDTH   780
+#define PREFS_GEOMETRY_DEFAULT_HEIGHT  580
+#define PREFS_GEOMETRY_DEFAULT_XPOS  -9999
+#define PREFS_GEOMETRY_DEFAULT_YPOS  -9999
+#define PREFS_START_PAGE      "about:splash"
+#define PREFS_HOME            "http://www.dillo.org/"
+#define PREFS_FONT_SERIF      "DejaVu Serif"
+#define PREFS_FONT_SANS_SERIF "DejaVu Sans"
+#define PREFS_FONT_CURSIVE    "DejaVu Sans" /* TODO: find good default */
+#define PREFS_FONT_FANTASY    "DejaVu Sans" /* TODO: find good default */
+#define PREFS_FONT_MONOSPACE  "DejaVu Sans Mono"
+#define PREFS_SEARCH_URL "http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s"
+#define PREFS_SAVE_DIR        "/tmp/"
+#define PREFS_VISITED_COLOR   0x800080
+#define PREFS_HTTP_REFERER    "about:blank"
 
 /* Panel sizes */
 enum { P_tiny = 0, P_small, P_medium, P_large };
@@ -76,7 +98,6 @@
 extern DilloPrefs prefs;
 
 void a_Prefs_init(void);
-void a_Prefs_freeall(void);
 
 #ifdef __cplusplus
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/prefsparser.cc	Tue Apr 28 08:32:47 2009 -0400
@@ -0,0 +1,197 @@
+/*
+ * Preferences parser
+ *
+ * Copyright (C) 2006-2009 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <locale.h>            /* for setlocale */
+
+#include "prefs.h"
+#include "misc.h"
+#include "msg.h"
+
+#include "prefsparser.hh"
+
+typedef enum {
+   PREFS_BOOL,
+   PREFS_STRING,
+   PREFS_URL,
+   PREFS_INT32,
+   PREFS_DOUBLE,
+   PREFS_GEOMETRY,
+   PREFS_PANEL_SIZE
+} PrefType_t;
+
+typedef struct SymNode_ {
+   const char *name;
+   void *pref;
+   PrefType_t type;
+} SymNode_t;
+
+/*
+ * Parse a name/value pair and set preferences accordingly.
+ */
+int PrefsParser::parseOption(char *name, char *value)
+{
+   const SymNode_t *node;
+   unsigned int i;
+
+   /* Symbol array, sorted alphabetically */
+   const SymNode_t symbols[] = {
+      { "allow_white_bg", &prefs.allow_white_bg, PREFS_BOOL },
+      { "buffered_drawing", &prefs.buffered_drawing, PREFS_INT32 },
+      { "contrast_visited_color", &prefs.contrast_visited_color, PREFS_BOOL },
+      { "enterpress_forces_submit", &prefs.enterpress_forces_submit, 
+        PREFS_BOOL },
+      { "focus_new_tab", &prefs.focus_new_tab, PREFS_BOOL },
+      { "font_cursive", &prefs.font_cursive, PREFS_STRING },
+      { "font_factor", &prefs.font_factor, PREFS_DOUBLE },
+      { "font_fantasy", &prefs.font_fantasy, PREFS_STRING },
+      { "font_max_size", &prefs.font_max_size, PREFS_INT32 },
+      { "font_min_size", &prefs.font_min_size, PREFS_INT32 },
+      { "font_monospace", &prefs.font_monospace, PREFS_STRING },
+      { "font_sans_serif", &prefs.font_sans_serif, PREFS_STRING },
+      { "font_serif", &prefs.font_serif, PREFS_STRING },
+      { "fullwindow_start", &prefs.fullwindow_start, PREFS_BOOL },
+      { "geometry", NULL, PREFS_GEOMETRY },
+      { "home", &prefs.home, PREFS_URL },
+      { "http_language", &prefs.http_language, PREFS_STRING },
+      { "http_proxy", &prefs.http_proxy, PREFS_URL },
+      { "http_proxyuser", &prefs.http_proxyuser, PREFS_STRING },
+      { "http_referer", &prefs.http_referer, PREFS_STRING },
+      { "limit_text_width", &prefs.limit_text_width, PREFS_BOOL },
+      { "load_images", &prefs.load_images, PREFS_BOOL },
+      { "load_stylesheets", &prefs.load_stylesheets, PREFS_BOOL },
+      { "middle_click_drags_page", &prefs.middle_click_drags_page,
+        PREFS_BOOL },
+      { "middle_click_opens_new_tab", &prefs.middle_click_opens_new_tab,
+        PREFS_BOOL },
+      { "no_proxy", &prefs.no_proxy, PREFS_STRING },
+      { "panel_size", &prefs.panel_size, PREFS_PANEL_SIZE },
+      { "parse_embedded_css", &prefs.parse_embedded_css, PREFS_BOOL },
+      { "save_dir", &prefs.save_dir, PREFS_STRING },
+      { "search_url", &prefs.search_url, PREFS_STRING },
+      { "show_back", &prefs.show_back, PREFS_BOOL },
+      { "show_bookmarks", &prefs.show_bookmarks, PREFS_BOOL },
+      { "show_clear_url", &prefs.show_clear_url, PREFS_BOOL },
+      { "show_extra_warnings", &prefs.show_extra_warnings, PREFS_BOOL },
+      { "show_filemenu", &prefs.show_filemenu, PREFS_BOOL },
+      { "show_forw", &prefs.show_forw, PREFS_BOOL },
+      { "show_home", &prefs.show_home, PREFS_BOOL },
+      { "show_msg", &prefs.show_msg, PREFS_BOOL },
+      { "show_progress_box", &prefs.show_progress_box, PREFS_BOOL },
+      { "show_reload", &prefs.show_reload, PREFS_BOOL },
+      { "show_save", &prefs.show_save, PREFS_BOOL },
+      { "show_search", &prefs.show_search, PREFS_BOOL },
+      { "show_stop", &prefs.show_stop, PREFS_BOOL },
+      { "show_tools", &prefs.show_tools, PREFS_BOOL },
+      { "show_tooltip", &prefs.show_tooltip, PREFS_BOOL },
+      { "show_url", &prefs.show_url, PREFS_BOOL },
+      { "small_icons", &prefs.small_icons, PREFS_BOOL },
+      { "start_page", &prefs.start_page, PREFS_URL },
+      { "w3c_plus_heuristics", &prefs.w3c_plus_heuristics, PREFS_BOOL }
+   };
+
+   node = NULL;
+   for (i = 0; i < sizeof(symbols) / sizeof(SymNode_t); i++) {
+      if (!strcmp(symbols[i].name, name)) {
+         node = & (symbols[i]);
+         break;
+      }
+   }
+
+   if (!node) {
+      MSG("prefs: {%s} is not a recognized token.\n", name);
+      return -1;
+   }
+
+   switch (node->type) {
+   case PREFS_BOOL:
+      *(bool_t *)node->pref = (!dStrcasecmp(value, "yes") ||
+                               !dStrcasecmp(value, "true"));
+      break;
+   case PREFS_STRING:
+      dFree(*(char **)node->pref);
+      *(char **)node->pref = dStrdup(value);
+      break;
+   case PREFS_URL:
+      a_Url_free(*(DilloUrl **)node->pref);
+      *(DilloUrl **)node->pref = a_Url_new(value, NULL);
+      break;
+   case PREFS_INT32:
+      *(int32_t *)node->pref = strtol(value, NULL, 10);
+      break;
+   case PREFS_DOUBLE:
+      *(double *)node->pref = strtod(value, NULL);
+      break;
+   case PREFS_GEOMETRY:
+      a_Misc_parse_geometry(value, &prefs.xpos, &prefs.ypos,
+                            &prefs.width, &prefs.height);
+      break;
+   case PREFS_PANEL_SIZE:
+      if (!dStrcasecmp(value, "tiny"))
+         prefs.panel_size = P_tiny;
+      else if (!dStrcasecmp(value, "small"))
+         prefs.panel_size = P_small;
+      else if (!dStrcasecmp(value, "large"))
+         prefs.panel_size = P_large;
+      else /* default to "medium" */
+         prefs.panel_size = P_medium;
+      break;
+   default:
+      MSG_WARN("prefs: {%s} IS recognized but not handled!\n", name);
+      break;   /* Not reached */
+   }
+
+   if (prefs.limit_text_width) {
+      /* BUG: causes 100% CPU usage with <button> or <input type="image"> */
+      MSG_WARN("Disabling limit_text_width preference (currently broken).\n");
+      prefs.limit_text_width = FALSE;
+   }
+
+   return 0;
+}
+
+/*
+ * Parses the dillorc and sets the values in the prefs structure.
+ */
+void PrefsParser::parse(FILE *fp)
+{
+   char *line, *name, *value, *oldLocale;
+   int st;
+
+   // changing the LC_NUMERIC locale (temporarily) to C
+   // avoids parsing problems with float numbers
+   oldLocale = dStrdup(setlocale(LC_NUMERIC, NULL));
+   setlocale(LC_NUMERIC, "C");
+
+   // scan the file line by line
+   while ((line = dGetline(fp)) != NULL) {
+      st = dParser_parse_rc_line(&line, &name, &value);
+
+      if (st == 0) {
+         _MSG("prefsparser: name=%s, value=%s\n", name, value);
+         parseOption(name, value);
+      } else if (st < 0) {
+         MSG_ERR("prefsparser: Syntax error in dillorc:"
+                 " name=\"%s\" value=\"%s\"\n", name, value);
+      }
+
+      dFree(line);
+   }
+   fclose(fp);
+
+   // restore the old numeric locale
+   setlocale(LC_NUMERIC, oldLocale);
+   dFree(oldLocale);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/prefsparser.hh	Tue Apr 28 08:32:47 2009 -0400
@@ -0,0 +1,24 @@
+/*
+ * Preferences parser
+ *
+ * Copyright (C) 2006-2009 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __PREFS_HH__
+#define __PREFS_HH__
+
+#ifdef __cplusplus
+class PrefsParser {
+public:
+   static int parseOption(char *name, char *value);
+   static int parseLine(char *line, char *name, char *value);
+   static void parse(FILE *fp);
+};
+#endif /* __cplusplus */
+
+#endif /* __PREFS_HH__ */
--- a/src/uicmd.cc	Fri Apr 24 14:43:15 2009 +0000
+++ b/src/uicmd.cc	Tue Apr 28 08:32:47 2009 -0400
@@ -22,7 +22,7 @@
 #include <fltk/TabGroup.h>
 #include <fltk/Tooltip.h>
 
-#include "dir.h"
+#include "paths.hh"
 #include "ui.hh"
 #include "uicmd.hh"
 #include "timeout.hh"
@@ -561,7 +561,7 @@
          /* file URI */
          ch = new_urlstr[5];
          if (!ch || ch == '.') {
-            url = a_Url_new(a_Dir_get_owd(), "file:");
+            url = a_Url_new(Paths::getOldWorkingDir(), "file:");
          } else if (ch == '~') {
             url = a_Url_new(dGethomedir(), "file:");
          } else {