From http://www.jwz.org/xscreensaver/xscreensaver-5.24.tar.gz
[xscreensaver] / driver / demo-Gtk-conf.c
index 91a305cf5519f54b33daf7009e4004a36933969e..2f03a12f04e20870e152ece5d6e37c8b9a54e31b 100644 (file)
@@ -1,5 +1,5 @@
 /* demo-Gtk-conf.c --- implements the dynamic configuration dialogs.
- * xscreensaver, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2001-2013 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -40,9 +40,9 @@
  * workaround.
  */
 #ifdef HAVE_OLD_XML_HEADERS
-#include <parser.h>
+# include <parser.h>
 #else /* ! HAVE_OLD_XML_HEADERS */
-#include <libxml/parser.h> 
+# include <libxml/parser.h> 
 #endif /* HAVE_OLD_XML_HEADERS */
 
 /* 
 
 #include "demo-Gtk-conf.h"
 
+/* Deal with deprecation of direct access to struct fields on the way to GTK3
+   See http://live.gnome.org/GnomeGoals/UseGseal
+ */
+#if GTK_CHECK_VERSION(2,14,0)
+# define GET_PARENT(w)          gtk_widget_get_parent (w)
+# define GET_ADJ_VALUE(a)       gtk_adjustment_get_value (a)
+# define GET_ADJ_UPPER(a)       gtk_adjustment_get_upper (a)
+# define GET_ADJ_LOWER(a)       gtk_adjustment_get_lower (a)
+#else
+# define GET_PARENT(w)          ((w)->parent)
+# define GET_ADJ_VALUE(a)       ((a)->value)
+# define GET_ADJ_UPPER(a)       ((a)->upper)
+# define GET_ADJ_LOWER(a)       ((a)->lower)
+#endif
+
+
 extern const char *blurb (void);
 
 
+const char *hack_configuration_path = HACK_CONFIGURATION_PATH;
+
 static gboolean debug_p = FALSE;
 
 
+#define MIN_SLIDER_WIDTH     150
+#define MIN_SPINBUTTON_WIDTH  48
+#define MIN_LABEL_WIDTH       70
+
+
 typedef enum {
   COMMAND,
   FAKE,
@@ -89,30 +111,29 @@ typedef struct {
 
   parameter_type type;
 
-  char *id;            /* widget name */
-  char *label;         /* heading label, or null */
+  xmlChar *id;         /* widget name */
+  xmlChar *label;      /* heading label, or null */
 
   /* command, fake, description, fakepreview, string, file
    */
-  char *string;                /* file name, description, whatever. */
+  xmlChar *string;     /* file name, description, whatever. */
 
   /* slider, spinbutton
    */
-  char *low_label;     /* label for the left side */
-  char *high_label;    /* label for the right side */
+  xmlChar *low_label;  /* label for the left side */
+  xmlChar *high_label; /* label for the right side */
   float low;           /* minimum value */
   float high;          /* maximum value */
   float value;         /* default value */
   gboolean integer_p;  /* whether the range is integral, or real */
-  char *arg;           /* command-line option to set (substitute "%") */
+  xmlChar *arg;                /* command-line option to set (substitute "%") */
   gboolean invert_p;   /* whether to flip the value and pretend the
                            range goes from hi-low instead of low-hi. */
 
   /* boolean, select-option
    */
-  char *arg_set;       /* command-line option to set for "yes", or null */
-  char *arg_unset;     /* command-line option to set for "no", or null */
-  char *test;          /* #### no idea - enablement? */
+  xmlChar *arg_set;    /* command-line option to set for "yes", or null */
+  xmlChar *arg_unset;  /* command-line option to set for "no", or null */
 
   /* select
    */
@@ -120,16 +141,14 @@ typedef struct {
 
   /* select_option
    */
-  GList *enable;
-
   GtkWidget *widget;
 
 } parameter;
 
 
 static parameter *make_select_option (const char *file, xmlNodePtr);
-static void make_parameter_widget (const char *filename,
-                                   parameter *, GtkWidget *, int *);
+static void make_parameter_widget (const char *filename, 
+                                   parameter *, GtkWidget *);
 static void browse_button_cb (GtkButton *button, gpointer user_data);
 
 
@@ -148,19 +167,11 @@ free_parameter (parameter *p)
   if (p->arg)        free (p->arg);
   if (p->arg_set)    free (p->arg_set);
   if (p->arg_unset)  free (p->arg_unset);
-  if (p->test)       free (p->test);
 
   for (rest = p->options; rest; rest = rest->next)
     if (rest->data)
       free_parameter ((parameter *) rest->data);
 
-  for (rest = p->enable; rest; rest = rest->next)
-    {
-      free ((char *) rest->data);
-      rest->data = 0;
-    }
-  if (p->enable) g_list_free (p->enable);
-
   memset (p, ~0, sizeof(*p));
   free (p);
 }
@@ -200,7 +211,6 @@ describe_parameter (FILE *out, parameter *p)
   if (p->invert_p)   fprintf (out, " convert=\"invert\"");
   if (p->arg_set)    fprintf (out, " arg-set=\"%s\"",       p->arg_set);
   if (p->arg_unset)  fprintf (out, " arg-unset=\"%s\"",     p->arg_unset);
-  if (p->test)       fprintf (out, " test=\"%s\"",          p->test);
   fprintf (out, ">\n");
 
   if (p->type == SELECT)
@@ -215,15 +225,6 @@ describe_parameter (FILE *out, parameter *p)
           if (o->label)     fprintf (out, " _label=\"%s\"",    o->label);
           if (o->arg_set)   fprintf (out, " arg-set=\"%s\"",   o->arg_set);
           if (o->arg_unset) fprintf (out, " arg-unset=\"%s\"", o->arg_unset);
-          if (o->test)      fprintf (out, " test=\"%s\"",      o->test);
-          if (o->enable)
-            {
-              GList *e;
-              fprintf (out, " enable=\"");
-              for (e = o->enable; e; e = e->next)
-                fprintf (out, "%s%s", (char *) e->data, (e->next ? "," : ""));
-              fprintf (out, "\"");
-            }
           fprintf (out, ">\n");
         }
       fprintf (out, "</select>\n");
@@ -244,9 +245,9 @@ describe_parameter (FILE *out, parameter *p)
    `floatp' is set to TRUE.  Otherwise, it is unchanged.
  */
 static float
-xml_get_float (xmlNodePtr node, const char *name, gboolean *floatpP)
+xml_get_float (xmlNodePtr node, const xmlChar *name, gboolean *floatpP)
 {
-  const char *s = xmlGetProp (node, name);
+  const char *s = (char *) xmlGetProp (node, name);
   float f;
   char c;
   if (!s || 1 != sscanf (s, "%f %c", &f, &c))
@@ -260,8 +261,13 @@ xml_get_float (xmlNodePtr node, const char *name, gboolean *floatpP)
 
 
 static void sanity_check_parameter (const char *filename,
-                                    const char *node_name,
+                                    const xmlChar *node_name,
                                     parameter *p);
+static void sanity_check_text_node (const char *filename,
+                                    const xmlNodePtr node);
+static void sanity_check_menu_options (const char *filename,
+                                       const xmlChar *node_name,
+                                       parameter *p);
 
 /* Allocates and returns a new `parameter' object based on the
    properties in the given XML node.  Returns 0 if there's nothing
@@ -271,7 +277,7 @@ static parameter *
 make_parameter (const char *filename, xmlNodePtr node)
 {
   parameter *p;
-  const char *name = node->name;
+  const char *name = (char *) node->name;
   const char *convert;
   gboolean floatp = FALSE;
 
@@ -291,6 +297,20 @@ make_parameter (const char *filename, xmlNodePtr node)
   else if (!strcmp (name, "file"))         p->type = FILENAME;
   else if (!strcmp (name, "number"))       p->type = SPINBUTTON;
   else if (!strcmp (name, "select"))       p->type = SELECT;
+
+  else if (!strcmp (name, "xscreensaver-text") ||   /* ignored in X11; */
+           !strcmp (name, "xscreensaver-image") ||  /* used in Cocoa. */
+           !strcmp (name, "xscreensaver-updater"))
+    {
+      free (p);
+      return 0;
+    }
+  else if (node->type == XML_TEXT_NODE)
+    {
+      sanity_check_text_node (filename, node);
+      free (p);
+      return 0;
+    }
   else
     {
       if (debug_p)
@@ -302,7 +322,7 @@ make_parameter (const char *filename, xmlNodePtr node)
 
   if (p->type == SPINBUTTON)
     {
-      const char *type = xmlGetProp (node, "type");
+      const char *type = (char *) xmlGetProp (node, (xmlChar *) "type");
       if (!type || !strcmp (type, "spinbutton")) p->type = SPINBUTTON;
       else if (!strcmp (type, "slider"))         p->type = SLIDER;
       else
@@ -319,23 +339,23 @@ make_parameter (const char *filename, xmlNodePtr node)
       if (node->xmlChildrenNode &&
           node->xmlChildrenNode->type == XML_TEXT_NODE &&
           !node->xmlChildrenNode->next)
-        p->string = strdup (node->xmlChildrenNode->content);
+        p->string = (xmlChar *)
+          strdup ((char *) node->xmlChildrenNode->content);
     }
 
-  p->id         = xmlGetProp (node, "id");
-  p->label      = xmlGetProp (node, "_label");
-  p->low_label  = xmlGetProp (node, "_low-label");
-  p->high_label = xmlGetProp (node, "_high-label");
-  p->low        = xml_get_float (node, "low",     &floatp);
-  p->high       = xml_get_float (node, "high",    &floatp);
-  p->value      = xml_get_float (node, "default", &floatp);
+  p->id         = xmlGetProp (node, (xmlChar *) "id");
+  p->label      = xmlGetProp (node, (xmlChar *) "_label");
+  p->low_label  = xmlGetProp (node, (xmlChar *) "_low-label");
+  p->high_label = xmlGetProp (node, (xmlChar *) "_high-label");
+  p->low        = xml_get_float (node, (xmlChar *) "low",     &floatp);
+  p->high       = xml_get_float (node, (xmlChar *) "high",    &floatp);
+  p->value      = xml_get_float (node, (xmlChar *) "default", &floatp);
   p->integer_p  = !floatp;
-  convert       = xmlGetProp (node, "convert");
+  convert       = (char *) xmlGetProp (node, (xmlChar *) "convert");
   p->invert_p   = (convert && !strcmp (convert, "invert"));
-  p->arg        = xmlGetProp (node, "arg");
-  p->arg_set    = xmlGetProp (node, "arg-set");
-  p->arg_unset  = xmlGetProp (node, "arg-unset");
-  p->test       = xmlGetProp (node, "test");
+  p->arg        = xmlGetProp (node, (xmlChar *) "arg");
+  p->arg_set    = xmlGetProp (node, (xmlChar *) "arg-set");
+  p->arg_unset  = xmlGetProp (node, (xmlChar *) "arg-unset");
 
   /* Check for missing decimal point */
   if (debug_p &&
@@ -358,7 +378,7 @@ make_parameter (const char *filename, xmlNodePtr node)
         }
     }
 
-  sanity_check_parameter (filename, name, p);
+  sanity_check_parameter (filename, (const xmlChar *) name, p);
 
   return p;
 }
@@ -373,6 +393,11 @@ make_select_option (const char *filename, xmlNodePtr node)
 {
   if (node->type == XML_COMMENT_NODE)
     return 0;
+  else if (node->type == XML_TEXT_NODE)
+    {
+      sanity_check_text_node (filename, node);
+      return 0;
+    }
   else if (node->type != XML_ELEMENT_NODE)
     {
       if (debug_p)
@@ -381,7 +406,7 @@ make_select_option (const char *filename, xmlNodePtr node)
                  blurb(), filename, node->name, (int)node->type);
       return 0;
     }
-  else if (strcmp (node->name, "option"))
+  else if (strcmp ((char *) node->name, "option"))
     {
       if (debug_p)
         fprintf (stderr,
@@ -392,27 +417,12 @@ make_select_option (const char *filename, xmlNodePtr node)
   else
     {
       parameter *s = calloc (1, sizeof(*s));
-      char *enable, *e;
 
       s->type       = SELECT_OPTION;
-      s->id         = xmlGetProp (node, "id");
-      s->label      = xmlGetProp (node, "_label");
-      s->arg_set    = xmlGetProp (node, "arg-set");
-      s->arg_unset  = xmlGetProp (node, "arg-unset");
-      s->test       = xmlGetProp (node, "test");
-      enable        = xmlGetProp (node, "enable");
-
-      if (enable)
-        {
-          enable = strdup (enable);
-          e = strtok (enable, ", ");
-          while (e)
-            {
-              s->enable = g_list_append (s->enable, strdup (e));
-              e = strtok (0, ", ");
-            }
-          free (enable);
-        }
+      s->id         = xmlGetProp (node, (xmlChar *) "id");
+      s->label      = xmlGetProp (node, (xmlChar *) "_label");
+      s->arg_set    = xmlGetProp (node, (xmlChar *) "arg-set");
+      s->arg_unset  = xmlGetProp (node, (xmlChar *) "arg-unset");
 
       sanity_check_parameter (filename, node->name, s);
       return s;
@@ -424,7 +434,7 @@ make_select_option (const char *filename, xmlNodePtr node)
    when they should have typed "arg=", etc.
  */
 static void
-sanity_check_parameter (const char *filename, const char *node_name,
+sanity_check_parameter (const char *filename, const xmlChar *node_name,
                         parameter *p)
 {
   struct {
@@ -528,10 +538,10 @@ sanity_check_parameter (const char *filename, const char *node_name,
 # define WARN(STR) \
    fprintf (stderr, "%s: %s: " STR " in <%s%s id=\"%s\">\n", \
               blurb(), filename, node_name, \
-              (!strcmp(node_name, "number") \
+              (!strcmp((char *) node_name, "number") \
                ? (p->type == SPINBUTTON ? " type=spinbutton" : " type=slider")\
                : ""), \
-              (p->id ? p->id : ""))
+              (p->id ? (char *) p->id : ""))
 # define CHECK(SLOT,NAME) \
    if (p->SLOT && !allowed.SLOT) \
      WARN ("\"" NAME "\" is not a valid option"); \
@@ -552,21 +562,140 @@ sanity_check_parameter (const char *filename, const char *node_name,
   CHECK (arg_unset,  "arg-unset");
 # undef CHECK
 # undef WARN
+
+  if (p->type == SELECT)
+    sanity_check_menu_options (filename, node_name, p);
 }
 
 
+static void
+sanity_check_menu_options (const char *filename, const xmlChar *node_name,
+                           parameter *p)
+{
+  GList *opts;
+  int noptions = 0;
+  int nulls = 0;
+  char *prefix = 0;
+
+/*  fprintf (stderr, "\n## %s\n", p->id);*/
+  for (opts = p->options; opts; opts = opts->next)
+    {
+      parameter *s = (parameter *) opts->data;
+      if (!s->arg_set) nulls++;
+      noptions++;
+
+      if (s->arg_set)
+        {
+          char *a = strdup ((char *) s->arg_set);
+          char *spc = strchr (a, ' ');
+          if (spc) *spc = 0;
+          if (prefix)
+            {
+              if (strcmp (a, prefix))
+                fprintf (stderr,
+                      "%s: %s: both \"%s\" and \"%s\" used in <select id=\"%s\">\n",
+                         blurb(), filename, prefix, a, p->id);
+              free (prefix);
+            }
+          prefix = a;
+        }
+
+/*      fprintf (stderr, "\n   %s\n", s->arg_set);*/
+    }
+
+  if (prefix) free (prefix);
+  prefix = 0;
+  if (nulls > 1)
+    fprintf (stderr, 
+             "%s: %s: more than one menu with no arg-set in <select id=\"%s\">\n",
+             blurb(), filename, p->id);
+}
+
+
+/* "text" nodes show up for all the non-tag text in the file, including
+   all the newlines between tags.  Warn if there is text there that
+   is not whitespace.
+ */
+static void
+sanity_check_text_node (const char *filename, const xmlNodePtr node)
+{
+  const char *body = (const char *) node->content;
+  if (node->type != XML_TEXT_NODE) abort();
+  while (isspace (*body)) body++;
+  if (*body)
+    fprintf (stderr, "%s: WARNING: %s: random text present: \"%s\"\n",
+             blurb(), filename, body);
+}
+
+
+/* Returns a list of strings, every switch mentioned in the parameters.
+   The strings must be freed.
+ */
+static GList *
+get_all_switches (const char *filename, GList *parms)
+{
+  GList *switches = 0;
+  GList *p;
+  for (p = parms; p; p = p->next)
+    {
+      parameter *pp = (parameter *) p->data;
+
+      if (pp->type == SELECT)
+        {
+          GList *list2 = get_all_switches (filename, pp->options);
+          switches = g_list_concat (switches, list2);
+        }
+      if (pp->arg && *pp->arg)
+        switches = g_list_append (switches, strdup ((char *) pp->arg));
+      if (pp->arg_set && *pp->arg_set)
+        switches = g_list_append (switches, strdup ((char *) pp->arg_set));
+      if (pp->arg_unset && *pp->arg_unset)
+        switches = g_list_append (switches, strdup ((char *) pp->arg_unset));
+    }
+  return switches;
+}
+
+
+/* Ensures that no switch is mentioned more than once.
+ */
+static void
+sanity_check_parameters (const char *filename, GList *parms)
+{
+  GList *list = get_all_switches (filename, parms);
+  GList *p;
+  for (p = list; p; p = p->next)
+    {
+      char *sw = (char *) p->data;
+      GList *p2;
+
+      if (*sw != '-' && *sw != '+')
+        fprintf (stderr, "%s: %s: switch does not begin with hyphen \"%s\"\n",
+                 blurb(), filename, sw);
+
+      for (p2 = p->next; p2; p2 = p2->next)
+        {
+          const char *sw2 = (const char *) p2->data;
+          if (!strcmp (sw, sw2))
+            fprintf (stderr, "%s: %s: duplicate switch \"%s\"\n",
+                     blurb(), filename, sw);
+        }
+
+      free (sw);
+    }
+  g_list_free (list);
+}
+
 
 /* Helper for make_parameters()
  */
 static GList *
-make_parameters_1 (const char *filename, xmlNodePtr node,
-                   GtkWidget *parent, int *row)
+make_parameters_1 (const char *filename, xmlNodePtr node, GtkWidget *parent)
 {
   GList *list = 0;
 
   for (; node; node = node->next)
     {
-      const char *name = node->name;
+      const char *name = (char *) node->name;
       if (!strcmp (name, "hgroup") ||
           !strcmp (name, "vgroup"))
         {
@@ -575,17 +704,9 @@ make_parameters_1 (const char *filename, xmlNodePtr node,
                             : gtk_vbox_new (FALSE, 0));
           GList *list2;
           gtk_widget_show (box);
+          gtk_box_pack_start (GTK_BOX (parent), box, FALSE, FALSE, 0);
 
-          if (row)
-            gtk_table_attach (GTK_TABLE (parent), box, 0, 3, *row, *row + 1,
-                              0, 0, 0, 0);
-          else
-            gtk_box_pack_start (GTK_BOX (parent), box, FALSE, FALSE, 0);
-
-          if (row)
-            (*row)++;
-
-          list2 = make_parameters_1 (filename, node->xmlChildrenNode, box, 0);
+          list2 = make_parameters_1 (filename, node->xmlChildrenNode, box);
           if (list2)
             list = g_list_concat (list, list2);
         }
@@ -595,7 +716,7 @@ make_parameters_1 (const char *filename, xmlNodePtr node,
           if (p)
             {
               list = g_list_append (list, p);
-              make_parameter_widget (filename, p, parent, row);
+              make_parameter_widget (filename, p, parent);
             }
         }
     }
@@ -610,12 +731,11 @@ make_parameters_1 (const char *filename, xmlNodePtr node,
 static GList *
 make_parameters (const char *filename, xmlNodePtr node, GtkWidget *parent)
 {
-  int row = 0;
   for (; node; node = node->next)
     {
       if (node->type == XML_ELEMENT_NODE &&
-          !strcmp (node->name, "screensaver"))
-        return make_parameters_1 (filename, node->xmlChildrenNode, parent, &row);
+          !strcmp ((char *) node->name, "screensaver"))
+        return make_parameters_1 (filename, node->xmlChildrenNode, parent);
     }
   return 0;
 }
@@ -639,6 +759,7 @@ make_adjustment (const char *filename, parameter *p)
                  : p->value);
   gfloat si = (p->high - p->low) / 100;
   gfloat pi = (p->high - p->low) / 10;
+  gfloat page_size = ((p->type == SLIDER) ? 1 : 0);
 
   if (p->value < p->low || p->value > p->high)
     {
@@ -667,59 +788,92 @@ make_adjustment (const char *filename, parameter *p)
     }
 #endif /* 0 */
 
-  if (p->integer_p)
-    {
-      si = (int) (si + 0.5);
-      pi = (int) (pi + 0.5);
-      if (si < 1) si = 1;
-      if (pi < 1) pi = 1;
+  si = (int) (si + 0.5);
+  pi = (int) (pi + 0.5);
+  if (si < 1) si = 1;
+  if (pi < 1) pi = 1;
+
+  if (range <= 500) si = 1;
+
+  return GTK_ADJUSTMENT (gtk_adjustment_new (value,
+                                             p->low,
+                                             p->high + page_size,
+                                             si, pi, page_size));
+}
+
+
 
-      if (range <= 500) si = 1;
+static void
+set_widget_min_width (GtkWidget *w, int width)
+{
+  GtkRequisition req;
+  gtk_widget_size_request (GTK_WIDGET (w), &req);
+  if (req.width < width)
+    gtk_widget_set_size_request (GTK_WIDGET (w), width, -1);
+}
+
+
+/* If we're inside a vbox, we need to put an hbox in it, or labels appear 
+   on top instead of to the left, and things stretch to the full width of
+   the window.
+ */
+static GtkWidget *
+insert_fake_hbox (GtkWidget *parent)
+{
+  if (GTK_IS_VBOX (parent))
+    {
+      GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
+      gtk_box_pack_start (GTK_BOX (parent), hbox, FALSE, FALSE, 4);
+      gtk_widget_show (hbox);
+      return hbox;
     }
-  return GTK_ADJUSTMENT (gtk_adjustment_new (value, p->low, p->high,
-                                             si, pi, pi));
+  return parent;
 }
 
 
+static void
+link_atk_label_to_widget(GtkWidget *label, GtkWidget *widget)
+{
+    AtkObject *atk_label = gtk_widget_get_accessible (label);
+    AtkObject *atk_widget = gtk_widget_get_accessible (widget);
+
+    atk_object_add_relationship (atk_label, ATK_RELATION_LABEL_FOR,
+                                atk_widget);
+    atk_object_add_relationship (atk_widget, ATK_RELATION_LABELLED_BY,
+                                atk_label);
+}
 
 /* Given a `parameter' struct, allocates an appropriate GtkWidget for it,
    and stores it in `p->widget'.
-   `row' is used for keeping track of our position during table layout.
-   `parent' must be a GtkTable or a GtkBox.
+   `parent' must be a GtkBox.
  */
 static void
-make_parameter_widget (const char *filename,
-                       parameter *p, GtkWidget *parent, int *row)
+make_parameter_widget (const char *filename, parameter *p, GtkWidget *parent)
 {
-  const char *label = p->label;
+  const char *label = (char *) p->label;
   if (p->widget) return;
 
   switch (p->type)
     {
     case STRING:
       {
+        GtkWidget *entry = gtk_entry_new ();
+        parent = insert_fake_hbox (parent);
         if (label)
           {
             GtkWidget *w = gtk_label_new (_(label));
+            link_atk_label_to_widget (w, entry);
             gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT);
             gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+            set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
             gtk_widget_show (w);
-            if (row)
-              gtk_table_attach (GTK_TABLE (parent), w, 0, 1, *row, *row + 1,
-                                GTK_FILL, 0, 0, 0);
-            else
-              gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
+            gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
           }
 
-        p->widget = gtk_entry_new ();
+        p->widget = entry;
         if (p->string)
-          gtk_entry_set_text (GTK_ENTRY (p->widget), p->string);
-        if (row)
-          gtk_table_attach (GTK_TABLE (parent), p->widget, 1, 3,
-                            *row, *row + 1,
-                            GTK_FILL, 0, 0, 0);
-        else
-          gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
+          gtk_entry_set_text (GTK_ENTRY (p->widget), (char *) p->string);
+        gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
         break;
       }
     case FILENAME:
@@ -727,6 +881,7 @@ make_parameter_widget (const char *filename,
         GtkWidget *L = gtk_label_new (label ? _(label) : "");
         GtkWidget *entry = gtk_entry_new ();
         GtkWidget *button = gtk_button_new_with_label (_("Browse..."));
+        link_atk_label_to_widget (L, entry);
         gtk_widget_show (entry);
         gtk_widget_show (button);
         p->widget = entry;
@@ -737,29 +892,16 @@ make_parameter_widget (const char *filename,
 
         gtk_label_set_justify (GTK_LABEL (L), GTK_JUSTIFY_RIGHT);
         gtk_misc_set_alignment (GTK_MISC (L), 1.0, 0.5);
+        set_widget_min_width (GTK_WIDGET (L), MIN_LABEL_WIDTH);
         gtk_widget_show (L);
 
         if (p->string)
-          gtk_entry_set_text (GTK_ENTRY (entry), p->string);
+          gtk_entry_set_text (GTK_ENTRY (entry), (char *) p->string);
 
-        if (row)
-          {
-            gtk_table_attach (GTK_TABLE (parent), L, 0, 1,
-                              *row, *row + 1,
-                              GTK_FILL, 0, 0, 0);
-            gtk_table_attach (GTK_TABLE (parent), entry, 1, 2,
-                              *row, *row + 1,
-                              GTK_EXPAND | GTK_FILL, 0, 0, 0);
-            gtk_table_attach (GTK_TABLE (parent), button, 2, 3,
-                              *row, *row + 1,
-                              0, 0, 0, 0);
-          }
-        else
-          {
-            gtk_box_pack_start (GTK_BOX (parent), L,      FALSE, FALSE, 4);
-            gtk_box_pack_start (GTK_BOX (parent), entry,  TRUE,  TRUE,  4);
-            gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 4);
-          }
+        parent = insert_fake_hbox (parent);
+        gtk_box_pack_start (GTK_BOX (parent), L,      FALSE, FALSE, 4);
+        gtk_box_pack_start (GTK_BOX (parent), entry,  TRUE,  TRUE,  4);
+        gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 4);
         break;
       }
     case SLIDER:
@@ -771,95 +913,46 @@ make_parameter_widget (const char *filename,
         if (label)
           {
             labelw = gtk_label_new (_(label));
+            link_atk_label_to_widget (labelw, scale);
             gtk_label_set_justify (GTK_LABEL (labelw), GTK_JUSTIFY_LEFT);
             gtk_misc_set_alignment (GTK_MISC (labelw), 0.0, 0.5);
+            set_widget_min_width (GTK_WIDGET (labelw), MIN_LABEL_WIDTH);
             gtk_widget_show (labelw);
+            gtk_box_pack_start (GTK_BOX (parent), labelw, FALSE, FALSE, 2);
           }
 
-        if (GTK_IS_VBOX (parent))
-          {
-            /* If we're inside a vbox, we need to put an hbox in it, to get
-               the low/high labels to be to the left/right of the slider.
-             */
-            GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
-
-            /* But if we have a label, put that above the slider's hbox. */
-            if (labelw)
-              {
-                gtk_box_pack_start (GTK_BOX (parent), labelw, FALSE, TRUE, 2);
-                labelw = 0;
-              }
-
-            gtk_box_pack_start (GTK_BOX (parent), hbox, TRUE, TRUE, 6);
-            gtk_widget_show (hbox);
-            parent = hbox;
-          }
-
-        if (labelw)
-          {
-            if (row)
-              {
-                gtk_table_attach (GTK_TABLE (parent), labelw,
-                                  0, 3, *row, *row + 1,
-                                  GTK_EXPAND | GTK_FILL, 0, 0, 0);
-                (*row)++;
-              }
-            else
-              {
-                if (GTK_IS_HBOX (parent))
-                  {
-                    GtkWidget *box = gtk_vbox_new (FALSE, 0);
-                    gtk_box_pack_start (GTK_BOX (parent), box, FALSE, TRUE, 0);
-                    gtk_widget_show (box);
-                    gtk_box_pack_start (GTK_BOX (box), labelw, FALSE, TRUE, 4);
-                    parent = box;
-                    box = gtk_hbox_new (FALSE, 0);
-                    gtk_widget_show (box);
-                    gtk_box_pack_start (GTK_BOX (parent), box, TRUE, TRUE, 0);
-                    parent = box;
-                  }
-                else
-                  gtk_box_pack_start (GTK_BOX (parent), labelw,
-                                      FALSE, TRUE, 0);
-              }
-          }
+        /* Do this after 'labelw' so that it appears above, not to left. */
+        parent = insert_fake_hbox (parent);
 
         if (p->low_label)
           {
-            GtkWidget *w = gtk_label_new (_(p->low_label));
+            GtkWidget *w = gtk_label_new (_((char *) p->low_label));
+            link_atk_label_to_widget (w, scale);
             gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT);
             gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+            set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
             gtk_widget_show (w);
-            if (row)
-              gtk_table_attach (GTK_TABLE (parent), w, 0, 1, *row, *row + 1,
-                                GTK_FILL, 0, 0, 0);
-            else
-              gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
+            gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
           }
 
         gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_BOTTOM);
-        gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
+        gtk_scale_set_draw_value (GTK_SCALE (scale), debug_p);
         gtk_scale_set_digits (GTK_SCALE (scale), (p->integer_p ? 0 : 2));
-        if (row)
-          gtk_table_attach (GTK_TABLE (parent), scale, 1, 2,
-                            *row, *row + 1,
-                            GTK_EXPAND | GTK_FILL, 0, 0, 0);
-        else
-          gtk_box_pack_start (GTK_BOX (parent), scale, TRUE, TRUE, 4);
+        set_widget_min_width (GTK_WIDGET (scale), MIN_SLIDER_WIDTH);
+
+        gtk_box_pack_start (GTK_BOX (parent), scale, FALSE, FALSE, 4);
 
         gtk_widget_show (scale);
 
         if (p->high_label)
           {
-            GtkWidget *w = gtk_label_new (_(p->high_label));
+            GtkWidget *w = gtk_label_new (_((char *) p->high_label));
+            link_atk_label_to_widget (w, scale);
             gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
             gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
+            set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
             gtk_widget_show (w);
-            if (row)
-              gtk_table_attach (GTK_TABLE (parent), w, 2, 3, *row, *row + 1,
-                                GTK_FILL, 0, 0, 0);
-            else
-              gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
+            gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
           }
 
         p->widget = scale;
@@ -871,46 +964,34 @@ make_parameter_widget (const char *filename,
         GtkWidget *spin = gtk_spin_button_new (adj, 15, 0);
         gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE);
         gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (spin), TRUE);
-        gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), adj->value);
+        gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), GET_ADJ_VALUE(adj));
+        set_widget_min_width (GTK_WIDGET (spin), MIN_SPINBUTTON_WIDTH);
 
         if (label)
           {
             GtkWidget *w = gtk_label_new (_(label));
+            link_atk_label_to_widget (w, spin);
             gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_RIGHT);
             gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
+            set_widget_min_width (GTK_WIDGET (w), MIN_LABEL_WIDTH);
             gtk_widget_show (w);
-            if (row)
-              gtk_table_attach (GTK_TABLE (parent), w, 0, 1, *row, *row + 1,
-                                GTK_FILL, 0, 0, 0);
-            else
-              gtk_box_pack_start (GTK_BOX (parent), w, TRUE, TRUE, 4);
+            parent = insert_fake_hbox (parent);
+            gtk_box_pack_start (GTK_BOX (parent), w, FALSE, FALSE, 4);
           }
 
         gtk_widget_show (spin);
-        if (row)
-          {
-            GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
-            gtk_widget_show (hbox);
-            gtk_table_attach (GTK_TABLE (parent), hbox, 1, 3,
-                              *row, *row + 1,
-                              GTK_EXPAND | GTK_FILL, 0, 8, 0);
-            gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, FALSE, 0);
-          }
-        else
-          gtk_box_pack_start (GTK_BOX (parent), spin, FALSE, FALSE, 4);
+        gtk_box_pack_start (GTK_BOX (parent), spin, FALSE, FALSE, 4);
 
         p->widget = spin;
         break;
       }
     case BOOLEAN:
       {
-        p->widget = gtk_check_button_new_with_label (label);
-        if (row)
-          gtk_table_attach (GTK_TABLE (parent), p->widget, 0, 3,
-                            *row, *row + 1,
-                            GTK_EXPAND | GTK_FILL, 0, 0, 0);
-        else
-          gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
+        p->widget = gtk_check_button_new_with_label (_(label));
+        /* Let these stretch -- doesn't hurt. 
+           parent = insert_fake_hbox (parent);
+         */
+        gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
         break;
       }
     case SELECT:
@@ -919,33 +1000,18 @@ make_parameter_widget (const char *filename,
         GtkWidget *menu = gtk_menu_new ();
         GList *opts;
 
-        if (label && row)
-          {
-            GtkWidget *w = gtk_label_new (_(label));
-            gtk_label_set_justify (GTK_LABEL (w), GTK_JUSTIFY_LEFT);
-            gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
-            gtk_widget_show (w);
-            gtk_table_attach (GTK_TABLE (parent), w, 0, 3, *row, *row + 1,
-                              GTK_EXPAND | GTK_FILL, 0, 0, 0);
-            (*row)++;
-          }
-
         for (opts = p->options; opts; opts = opts->next)
           {
             parameter *s = (parameter *) opts->data;
-            GtkWidget *i = gtk_menu_item_new_with_label (s->label);
+            GtkWidget *i = gtk_menu_item_new_with_label (_((char *) s->label));
             gtk_widget_show (i);
             gtk_menu_append (GTK_MENU (menu), i);
           }
 
         gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
         p->widget = opt;
-        if (row)
-          gtk_table_attach (GTK_TABLE (parent), p->widget, 0, 3,
-                            *row, *row + 1,
-                            GTK_EXPAND | GTK_FILL, 0, 0, 0);
-        else
-          gtk_box_pack_start (GTK_BOX (parent), p->widget, TRUE, TRUE, 4);
+        parent = insert_fake_hbox (parent);
+        gtk_box_pack_start (GTK_BOX (parent), p->widget, FALSE, FALSE, 4);
         break;
       }
 
@@ -960,10 +1026,8 @@ make_parameter_widget (const char *filename,
 
   if (p->widget)
     {
-      gtk_widget_set_name (p->widget, p->id);
+      gtk_widget_set_name (p->widget, (char *) p->id);
       gtk_widget_show (p->widget);
-      if (row)
-        (*row)++;
     }
 }
 
@@ -979,8 +1043,8 @@ static void
 file_sel_cancel (GtkWidget *button, gpointer user_data)
 {
   GtkWidget *dialog = button;
-  while (dialog->parent)
-    dialog = dialog->parent;
+  while (GET_PARENT (dialog))
+    dialog = GET_PARENT (dialog);
   gtk_widget_destroy (dialog);
 }
 
@@ -990,9 +1054,10 @@ file_sel_ok (GtkWidget *button, gpointer user_data)
 {
   GtkWidget *entry = GTK_WIDGET (user_data);
   GtkWidget *dialog = button;
-  char *path;
-  while (dialog->parent)
-    dialog = dialog->parent;
+  const char *path;
+
+  while (GET_PARENT (dialog))
+    dialog = GET_PARENT (dialog);
   gtk_widget_hide (dialog);
 
   path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog));
@@ -1016,7 +1081,7 @@ static void
 browse_button_cb (GtkButton *button, gpointer user_data)
 {
   GtkWidget *entry = GTK_WIDGET (user_data);
-  char *text = gtk_entry_get_text (GTK_ENTRY (entry));
+  const char *text = gtk_entry_get_text (GTK_ENTRY (entry));
   GtkFileSelection *selector =
     GTK_FILE_SELECTION (gtk_file_selection_new (_("Select file.")));
 
@@ -1122,7 +1187,7 @@ de_stringify (char *s)
 static char *
 format_switch (parameter *p, const char *value)
 {
-  char *fmt = p->arg;
+  char *fmt = (char *) p->arg;
   char *v2;
   char *result, *s;
   if (!fmt || !value) return 0;
@@ -1154,7 +1219,7 @@ parameter_to_switch (parameter *p)
     {
     case COMMAND:
       if (p->arg)
-        return strdup (p->arg);
+        return strdup ((char *) p->arg);
       else
         return 0;
       break;
@@ -1165,7 +1230,7 @@ parameter_to_switch (parameter *p)
         const char *s = gtk_entry_get_text (GTK_ENTRY (p->widget));
         char *v;
         if (!strcmp ((s ? s : ""),
-                     (p->string ? p->string : "")))
+                     (p->string ? (char *) p->string : "")))
           v = 0;  /* same as default */
         else
           v = format_switch (p, s);
@@ -1184,14 +1249,15 @@ parameter_to_switch (parameter *p)
         char buf[255];
         char *s1;
         float value = (p->invert_p
-                       ? invert_range (adj->lower, adj->upper, adj->value)
-                       : adj->value);
+                       ? invert_range (GET_ADJ_LOWER(adj), GET_ADJ_UPPER(adj),
+                                       GET_ADJ_VALUE(adj)) - 1
+                       : GET_ADJ_VALUE(adj));
 
         if (value == p->value)  /* same as default */
           return 0;
 
         if (p->integer_p)
-          sprintf (buf, "%d", (int) (value + 0.5));
+          sprintf (buf, "%d", (int) (value + (value > 0 ? 0.5 : -0.5)));
         else
           sprintf (buf, "%.4f", value);
           
@@ -1211,8 +1277,8 @@ parameter_to_switch (parameter *p)
       {
         GtkToggleButton *b = GTK_TOGGLE_BUTTON (p->widget);
         const char *s = (gtk_toggle_button_get_active (b)
-                         ? p->arg_set
-                         : p->arg_unset);
+                         ? (char *) p->arg_set
+                         : (char *) p->arg_unset);
         if (s)
           return strdup (s);
         else
@@ -1231,7 +1297,7 @@ parameter_to_switch (parameter *p)
         const char *s;
         if (!o) abort();
         if (o->type != SELECT_OPTION) abort();
-        s = o->arg_set;
+        s = (char *) o->arg_set;
         if (s)
           return strdup (s);
         else
@@ -1249,25 +1315,29 @@ parameter_to_switch (parameter *p)
    All arguments will be properly quoted.
  */
 static char *
-parameters_to_cmd_line (GList *parms)
+parameters_to_cmd_line (GList *parms, gboolean default_p)
 {
   int L = g_list_length (parms);
   int LL = 0;
   char **strs = (char **) calloc (sizeof (*parms), L);
   char *result;
   char *out;
-  int i;
+  int i, j;
 
-  for (i = 0; parms; parms = parms->next, i++)
+  for (i = 0, j = 0; parms; parms = parms->next, i++)
     {
-      char *s = parameter_to_switch ((parameter *) parms->data);
-      strs[i] = s;
-      LL += (s ? strlen(s) : 0) + 1;
+      parameter *p = (parameter *) parms->data;
+      if (!default_p || p->type == COMMAND)
+        {
+          char *s = parameter_to_switch (p);
+          strs[j++] = s;
+          LL += (s ? strlen(s) : 0) + 1;
+        }
     }
 
   result = (char *) malloc (LL + 10);
   out = result;
-  for (i = 0; i < L; i++)
+  for (i = 0; i < j; i++)
     if (strs[i])
       {
         strcpy (out, strs[i]);
@@ -1357,7 +1427,7 @@ parse_command_line_into_parameters (const char *filename,
       char *option = rest->data;
       rest->data = 0;
 
-      if (option[0] != '-')
+      if (option[0] != '-' && option[0] != '+')
         {
           if (debug_p)
             fprintf (stderr, "%s: WARNING: %s: not a switch: \"%s\"\n",
@@ -1430,8 +1500,8 @@ parse_command_line_into_parameters_1 (const char *filename,
 {
   GList *p;
   parameter *match = 0;
-  int which = -1;
-  int index = 0;
+  gint which = -1;
+  gint index = 0;
 
   for (p = parms; p; p = p->next)
     {
@@ -1451,7 +1521,7 @@ parse_command_line_into_parameters_1 (const char *filename,
         }
       else if (pp->arg)
         {
-          if (compare_opts (option, value, pp->arg))
+          if (compare_opts (option, value, (char *) pp->arg))
             {
               which = -1;
               match = pp;
@@ -1459,7 +1529,7 @@ parse_command_line_into_parameters_1 (const char *filename,
         }
       else if (pp->arg_set)
         {
-          if (compare_opts (option, value, pp->arg_set))
+          if (compare_opts (option, value, (char *) pp->arg_set))
             {
               which = 1;
               match = pp;
@@ -1467,7 +1537,7 @@ parse_command_line_into_parameters_1 (const char *filename,
         }
       else if (pp->arg_unset)
         {
-          if (compare_opts (option, value, pp->arg_unset))
+          if (compare_opts (option, value, (char *) pp->arg_unset))
             {
               which = 0;
               match = pp;
@@ -1499,11 +1569,11 @@ parse_command_line_into_parameters_1 (const char *filename,
       break;
     case BOOLEAN:
       if (which != 0 && which != 1) abort();
-      parameter_set_switch (match, (gpointer) which);
+      parameter_set_switch (match, GINT_TO_POINTER(which));
       break;
     case SELECT_OPTION:
       if (which != 1) abort();
-      parameter_set_switch (parent, (gpointer) index);
+      parameter_set_switch (parent, GINT_TO_POINTER(index));
       break;
     default:
       break;
@@ -1542,7 +1612,7 @@ parameter_set_switch (parameter *p, gpointer value)
         if (1 == sscanf ((char *) value, "%f %c", &f, &c))
           {
             if (p->invert_p)
-              f = invert_range (adj->lower, adj->upper, f);
+              f = invert_range (GET_ADJ_LOWER(adj), GET_ADJ_UPPER(adj), f) - 1;
             gtk_adjustment_set_value (adj, f);
           }
         break;
@@ -1550,13 +1620,13 @@ parameter_set_switch (parameter *p, gpointer value)
     case BOOLEAN:
       {
         GtkToggleButton *b = GTK_TOGGLE_BUTTON (p->widget);
-        gtk_toggle_button_set_active (b, (int) value);
+        gtk_toggle_button_set_active (b, GPOINTER_TO_INT(value));
         break;
       }
     case SELECT:
       {
         gtk_option_menu_set_history (GTK_OPTION_MENU (p->widget),
-                                     (int) value);
+                                     GPOINTER_TO_INT(value));
         break;
       }
     default:
@@ -1578,7 +1648,7 @@ restore_defaults (const char *progname, GList *parms)
         case FILENAME:
           {
             gtk_entry_set_text (GTK_ENTRY (p->widget),
-                                (p->string ? p->string : ""));
+                                (p->string ? (char *) p->string : ""));
             break;
           }
         case SLIDER:
@@ -1639,7 +1709,7 @@ restore_defaults (const char *progname, GList *parms)
  */
 
 static char *
-get_description (GList *parms)
+get_description (GList *parms, gboolean verbose_p)
 {
   parameter *doc = 0;
   for (; parms; parms = parms->next)
@@ -1656,8 +1726,9 @@ get_description (GList *parms)
     return 0;
   else
     {
-      char *d = strdup (doc->string);
+      char *d = strdup ((char *) doc->string);
       char *s;
+      char *p;
       for (s = d; *s; s++)
         if (s[0] == '\n')
           {
@@ -1665,6 +1736,8 @@ get_description (GList *parms)
               s++;
             else if (s[1] == ' ' || s[1] == '\t')
               s++;                 /* next line is indented: leave newline */
+            else if (!strncmp(s+1, "http:", 5))
+              s++;                 /* next line begins a URL: leave newline */
             else
               s[0] = ' ';          /* delete newline to un-fold this line */
           }
@@ -1684,7 +1757,27 @@ get_description (GList *parms)
           d[--L] = 0;
       }
 
-      return d;
+      /* strip off duplicated whitespaces */
+      for (s = d; *s; s++)
+         if (s[0] == ' ')
+         {
+           p = s+1;
+           while (*s == ' ')
+             s++;
+            if (*p && (s != p))
+              memmove (p, s, strlen(s)+1);
+         }
+
+#if 0
+      if (verbose_p)
+        {
+          fprintf (stderr, "%s: text read   is \"%s\"\n", blurb(),doc->string);
+          fprintf (stderr, "%s: description is \"%s\"\n", blurb(), d);
+          fprintf (stderr, "%s: translation is \"%s\"\n", blurb(), _(d));
+        }
+#endif /* 0 */
+
+      return (d);
     }
 }
 
@@ -1696,7 +1789,8 @@ static conf_data *
 load_configurator_1 (const char *program, const char *arguments,
                      gboolean verbose_p)
 {
-  const char *dir = HACK_CONFIGURATION_PATH;
+  const char *dir = hack_configuration_path;
+  char *base_program;
   int L = strlen (dir);
   char *file;
   char *s;
@@ -1705,13 +1799,17 @@ load_configurator_1 (const char *program, const char *arguments,
 
   if (L == 0) return 0;
 
-  file = (char *) malloc (L + strlen (program) + 10);
+  base_program = strrchr(program, '/');
+  if (base_program) base_program++;
+  if (!base_program) base_program = (char *) program;
+
+  file = (char *) malloc (L + strlen (base_program) + 10);
   data = (conf_data *) calloc (1, sizeof(*data));
 
   strcpy (file, dir);
   if (file[L-1] != '/')
     file[L++] = '/';
-  strcpy (file+L, program);
+  strcpy (file+L, base_program);
 
   for (s = file+L; *s; s++)
     if (*s == '/' || *s == ' ')
@@ -1728,7 +1826,7 @@ load_configurator_1 (const char *program, const char *arguments,
       char chars[1024];
       xmlParserCtxtPtr ctxt;
       xmlDocPtr doc = 0;
-      GtkWidget *table;
+      GtkWidget *vbox0;
       GList *parms;
 
       if (verbose_p)
@@ -1752,13 +1850,11 @@ load_configurator_1 (const char *program, const char *arguments,
 
       /* Parsed the XML file.  Now make some widgets. */
 
-      table = gtk_table_new (1, 3, FALSE);
-      gtk_table_set_row_spacings (GTK_TABLE (table), 4);
-      gtk_table_set_col_spacings (GTK_TABLE (table), 4);
-      gtk_container_set_border_width (GTK_CONTAINER (table), 8);
-      gtk_widget_show (table);
+      vbox0 = gtk_vbox_new (FALSE, 0);
+      gtk_widget_show (vbox0);
 
-      parms = make_parameters (file, doc->xmlRootNode, table);
+      parms = make_parameters (file, doc->xmlRootNode, vbox0);
+      sanity_check_parameters (file, parms);
 
       xmlFreeDoc (doc);
 
@@ -1766,9 +1862,9 @@ load_configurator_1 (const char *program, const char *arguments,
       if (arguments && *arguments)
         parse_command_line_into_parameters (program, arguments, parms);
 
-      data->widget = table;
+      data->widget = vbox0;
       data->parameters = parms;
-      data->description = get_description (parms);
+      data->description = get_description (parms, verbose_p);
     }
   else
     {
@@ -1779,7 +1875,7 @@ load_configurator_1 (const char *program, const char *arguments,
 
       p = calloc (1, sizeof(*p));
       p->type = COMMAND;
-      p->arg = strdup (arguments);
+      p->arg = (xmlChar *) strdup (arguments);
 
       data->parameters = g_list_append (0, (gpointer) p);
     }
@@ -1833,6 +1929,7 @@ load_configurator (const char *full_command_line, gboolean verbose_p)
   char *prog;
   char *args;
   conf_data *cd;
+  debug_p = verbose_p;
   split_command_line (full_command_line, &prog, &args);
   cd = load_configurator_1 (prog, args, verbose_p);
   free (prog);
@@ -1843,9 +1940,9 @@ load_configurator (const char *full_command_line, gboolean verbose_p)
 
 
 char *
-get_configurator_command_line (conf_data *data)
+get_configurator_command_line (conf_data *data, gboolean default_p)
 {
-  char *args = parameters_to_cmd_line (data->parameters);
+  char *args = parameters_to_cmd_line (data->parameters, default_p);
   char *result = (char *) malloc (strlen (data->progname) +
                                   strlen (args) + 2);
   strcpy (result, data->progname);