Index: variable.c
===================================================================
--- variable.c	(revision 6a8b5190384f683113444387b65b59ef66bb779f)
+++ variable.c	(revision 8258ea514c05b11da3f68d25d8414e222496fa2d)
@@ -1,105 +1,61 @@
 #include "owl.h"
 #include <stdio.h>
-#include "gmarshal_funcs.h"
-
-/* TODO(davidben): When we can require 2.30 and up, remove this. */
-#ifndef G_VALUE_INIT
-#define G_VALUE_INIT { 0, { { 0 } } }
-#endif
-
-typedef const char *(*get_string_t)(const owl_variable *);
-typedef int (*get_int_t)(const owl_variable *);
-typedef bool (*get_bool_t)(const owl_variable *);
-
-typedef int (*set_string_t)(owl_variable *, const char *);
-typedef int (*set_int_t)(owl_variable *, int);
-typedef int (*set_bool_t)(owl_variable *, bool);
-
-typedef int (*validate_string_t)(const owl_variable *, const char *);
-typedef int (*validate_int_t)(const owl_variable *, int);
-typedef int (*validate_bool_t)(const owl_variable *, bool);
-
-static void owl_variable_dict_newvar_bool_full(owl_vardict *vd,
-                                               const char *name,
-                                               bool default_val,
-                                               const char *summary,
-                                               const char *description,
-                                               validate_bool_t validate_fn,
-                                               set_bool_t set_fn,
-                                               get_bool_t get_fn);
-
-static void owl_variable_dict_newvar_string_full(owl_vardict *vd,
-                                                 const char *name,
-                                                 const char *default_val,
-                                                 const char *summary,
-                                                 const char *description,
-                                                 const char *validsettings,
-                                                 validate_string_t validate_fn,
-                                                 set_string_t set_fn,
-                                                 get_string_t get_fn);
-
-static void owl_variable_dict_newvar_int_full(owl_vardict *vd,
-                                              const char *name,
-                                              int default_val,
-                                              const char *summary,
-                                              const char *description,
-                                              const char *validsettings,
-                                              validate_int_t validate_fn,
-                                              set_int_t set_fn,
-                                              get_int_t get_fn);
-
-static void owl_variable_dict_newvar_enum_full(owl_vardict *vd,
-                                               const char *name,
-                                               int default_val,
-                                               const char *summary,
-                                               const char *description,
-                                               const char *validsettings,
-                                               validate_int_t validate_fn,
-                                               set_int_t set_fn,
-                                               get_int_t get_fn);
-
-#define OWLVAR_BOOL(name, default, summary, description) \
-        owl_variable_dict_newvar_bool(vd, name, default, summary, description)
-
-#define OWLVAR_BOOL_FULL(name, default, summary, description, validate, set, get) \
-        owl_variable_dict_newvar_bool_full(vd, name, default, summary, description, \
-                                           validate, set, get)
-
-#define OWLVAR_INT(name, default, summary, description) \
-        owl_variable_dict_newvar_int(vd, name, default, summary, description)
+
+#define OWLVAR_BOOL(name,default,summary,description) \
+        { g_strdup(name), OWL_VARIABLE_BOOL, NULL, default, "on,off", g_strdup(summary), g_strdup(description), NULL, \
+        NULL, NULL, NULL, NULL, NULL, NULL }
+
+#define OWLVAR_BOOL_FULL(name,default,summary,description,validate,set,get) \
+        { g_strdup(name), OWL_VARIABLE_BOOL, NULL, default, "on,off", g_strdup(summary), g_strdup(description), NULL, \
+        validate, set, NULL, get, NULL, NULL }
+
+#define OWLVAR_INT(name,default,summary,description) \
+        { g_strdup(name), OWL_VARIABLE_INT, NULL, default, "<int>", g_strdup(summary), g_strdup(description), NULL, \
+        NULL, NULL, NULL, NULL, NULL, NULL }
 
 #define OWLVAR_INT_FULL(name,default,summary,description,validset,validate,set,get) \
-        owl_variable_dict_newvar_int_full(vd, name, default, summary, description, \
-                                          validset, validate, set, get)
-
-#define OWLVAR_PATH(name, default, summary, description) \
-        owl_variable_dict_newvar_path(vd, name, default, summary, description)
-
-#define OWLVAR_STRING(name, default, summary, description) \
-        owl_variable_dict_newvar_string(vd, name, default, summary, description)
-
-#define OWLVAR_STRING_FULL(name, default, validset, summary, description, validate, set, get) \
-        owl_variable_dict_newvar_string_full(vd, name, default, summary, description, \
-                                             validset, validate, set, get)
+        { g_strdup(name), OWL_VARIABLE_INT, NULL, default, validset, g_strdup(summary), g_strdup(description), NULL, \
+        validate, set, NULL, get, NULL, NULL }
+
+#define OWLVAR_PATH(name,default,summary,description) \
+        { g_strdup(name), OWL_VARIABLE_STRING, g_strdup(default), 0, "<path>", g_strdup(summary), g_strdup(description),  NULL, \
+        NULL, NULL, NULL, NULL, NULL, NULL }
+
+#define OWLVAR_STRING(name,default,summary,description) \
+        { g_strdup(name), OWL_VARIABLE_STRING, g_strdup(default), 0, "<string>", g_strdup(summary), g_strdup(description), NULL, \
+        NULL, NULL, NULL, NULL, NULL, NULL }
+
+#define OWLVAR_STRING_FULL(name,default,validset,summary,description,validate,set,get) \
+        { g_strdup(name), OWL_VARIABLE_STRING, g_strdup(default), 0, validset, g_strdup(summary), g_strdup(description), NULL, \
+        validate, set, NULL, get, NULL, NULL }
 
 /* enums are really integers, but where validset is a comma-separated
  * list of strings which can be specified.  The tokens, starting at 0,
  * correspond to the values that may be specified. */
-#define OWLVAR_ENUM(name, default, summary, description, validset) \
-        owl_variable_dict_newvar_enum(vd, name, default, summary, description, validset)
+#define OWLVAR_ENUM(name,default,summary,description,validset) \
+        { g_strdup(name), OWL_VARIABLE_INT, NULL, default, validset, g_strdup(summary), g_strdup(description), NULL, \
+        owl_variable_enum_validate, \
+        NULL, owl_variable_enum_set_fromstring, \
+        NULL, owl_variable_enum_get_tostring, \
+        NULL }
 
 #define OWLVAR_ENUM_FULL(name,default,summary,description,validset,validate, set, get) \
-        owl_variable_dict_newvar_enum_full(vd, name, default, summary, description, \
-                                           validset, validate, set, get)
-
-void owl_variable_add_defaults(owl_vardict *vd)
-{
+        { g_strdup(name), OWL_VARIABLE_INT, NULL, default, validset, g_strdup(summary), g_strdup(description), NULL, \
+        validate, \
+        set, owl_variable_enum_set_fromstring, \
+        get, owl_variable_enum_get_tostring, \
+        NULL }
+
+int owl_variable_add_defaults(owl_vardict *vd)
+{
+  owl_variable variables_to_init[] = {
+
   OWLVAR_STRING( "personalbell" /* %OwlVarStub */, "off",
 		 "ring the terminal bell when personal messages are received",
 		 "Can be set to 'on', 'off', or the name of a filter which\n"
-		 "messages need to match in order to ring the bell");
+		 "messages need to match in order to ring the bell"),
 
   OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1,
-	       "enable / disable the terminal bell", "" );
+	       "enable / disable the terminal bell", "" ),
 
   OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG,
@@ -107,32 +63,32 @@
 		    "If set to 'on', debugging messages are logged to the\n"
 		    "file specified by the debugfile variable.\n",
-		    NULL, owl_variable_debug_set, NULL);
+		    NULL, owl_variable_debug_set, NULL),
 
   OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1,
-	       "send a login message when BarnOwl starts", "" );
+	       "send a login message when BarnOwl starts", "" ),
 
   OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1,
-	       "send a logout message when BarnOwl exits", "" );
+	       "send a logout message when BarnOwl exits", "" ),
 
   OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0,
-	       "display received pings", "" );
+	       "display received pings", "" ),
 
   OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1,
-	       "send pings", "" );
+	       "send pings", "" ),
 
   OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0,
-	       "disable printing information in the separator bar", "" );
+	       "disable printing information in the separator bar", "" ),
 
   OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1,
-	       "strip kerberos instance for reply", "");
+	       "strip kerberos instance for reply", ""),
 
   OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1,
-	       "strip leading and trailing newlines", "");
+	       "strip leading and trailing newlines", ""),
 
   OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1,
-	       "display outgoing messages", "" );
+	       "display outgoing messages", "" ),
 
   OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1,
-	       "load logins from .anyone on startup", "" );
+	       "load logins from .anyone on startup", "" ),
 
   OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0,
@@ -141,5 +97,5 @@
 	       "logged in the directory specified\n"
 	       "by the 'logpath' variable.  The filename in that\n"
-	       "directory is derived from the sender of the message.\n" );
+	       "directory is derived from the sender of the message.\n" ),
 
   OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0,
@@ -149,5 +105,5 @@
 	       "by the 'classlogpath' variable.\n" 
 	       "The filename in that directory is derived from\n"
-	       "the name of the class to which the message was sent.\n" );
+	       "the name of the class to which the message was sent.\n" ),
 
   OWLVAR_ENUM( "loggingdirection" /* %OwlVarStub */, OWL_LOGGING_DIRECTION_BOTH,
@@ -158,9 +114,9 @@
 	       "is selected both incoming and outgoing messages are\n"
 	       "logged.",
-	       "both,in,out");
+	       "both,in,out"),
 
   OWLVAR_BOOL_FULL( "colorztext" /* %OwlVarStub */, 1,
                     "allow @color() in zephyrs to change color",
-                    NULL, NULL, owl_variable_colorztext_set, NULL);
+                    NULL, NULL, owl_variable_colorztext_set, NULL),
 
   OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1,
@@ -168,9 +124,9 @@
 	       "If turned off, dashes, pipes and pluses will be used\n"
 	       "to draw lines on the screen.  Useful when the terminal\n"
-	       "is causing problems" );
+	       "is causing problems" ),
 
   OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
 	       "Do automatic zcrypt processing",
-	       "" );
+	       "" ),
 
   OWLVAR_BOOL_FULL( "pseudologins" /* %OwlVarStub */, 0,
@@ -180,5 +136,5 @@
 		    "but sent no login message, or a user is not present that sent no\n"
 		    "logout message, a pseudo login or logout message will be created\n",
-		    NULL, owl_variable_pseudologins_set, NULL);
+		    NULL, owl_variable_pseudologins_set, NULL),
 
   OWLVAR_BOOL( "ignorelogins" /* %OwlVarStub */, 0,
@@ -186,5 +142,5 @@
 	       "When this is enabled, BarnOwl will print login and logout notifications\n"
 	       "for AIM, zephyr, or other protocols.  If disabled BarnOwl will not print\n"
-	       "login or logout notifications.\n");
+	       "login or logout notifications.\n"),
 
   OWLVAR_STRING( "logfilter" /* %OwlVarStub */, "",
@@ -195,5 +151,5 @@
 		 "variables like logging, classlogging, loglogins, loggingdirection,\n"
 		 "etc.  If you want this variable to control all logging, make sure\n"
-		 "all other logging variables are in their default state.\n");
+		 "all other logging variables are in their default state.\n"),
 
   OWLVAR_BOOL( "loglogins" /* %OwlVarStub */, 0,
@@ -201,5 +157,5 @@
 	       "When this is enabled, BarnOwl will log login and logout notifications\n"
 	       "for AIM, zephyr, or other protocols.  If disabled BarnOwl will not print\n"
-	       "login or logout notifications.\n");
+	       "login or logout notifications.\n"),
 
   OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
@@ -213,20 +169,20 @@
 		    "in the editmulti keymap.\n",
 		    "off,middle,on",
-		    NULL, owl_variable_disable_ctrl_d_set, NULL);
+		    NULL, owl_variable_disable_ctrl_d_set, NULL),
 
   OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",
 	       "path for logging personal zephyrs", 
 	       "Specifies a directory which must exist.\n"
-	       "Files will be created in the directory for each sender.\n");
+	       "Files will be created in the directory for each sender.\n"),
 
   OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",
 	       "path for logging class zephyrs",
 	       "Specifies a directory which must exist.\n"
-	       "Files will be created in the directory for each class.\n");
+	       "Files will be created in the directory for each class.\n"),
 
   OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
 	       "path for logging debug messages when debugging is enabled",
 	       "This file will be logged to if 'debug' is set to 'on'.\n"
-               "BarnOwl will append a dot and the current process's pid to the filename.");
+               "BarnOwl will append a dot and the current process's pid to the filename."),
   
   OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
@@ -236,5 +192,5 @@
                "See the documentation for 'zsig' for more information about\n"
                "how the outgoing zsig is chosen."
-               );
+               ),
 
   OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
@@ -242,5 +198,5 @@
 	       "The named program will be run when BarnOwl receives new\n"
 	       "messages.  It will not be run again until the first\n"
-	       "instance exits");
+	       "instance exits"),
 
   OWLVAR_STRING( "zsender" /* %OwlVarStub */, "",
@@ -249,5 +205,5 @@
          "zephyrs.  If this is unset, it will use your Kerberos\n"
          "principal. Note that customizing the sender name will\n"
-         "cause your zephyrs to be sent unauthenticated.");
+         "cause your zephyrs to be sent unauthenticated."),
 
   OWLVAR_STRING( "zsigfunc" /* %OwlVarStub */, "BarnOwl::default_zephyr_signature()",
@@ -256,5 +212,5 @@
 		 "explicit zsig.  The default setting implements the policy\n"
 		 "described in the documentation for the 'zsig' variable.\n"
-		 "See also BarnOwl::random_zephyr_signature().\n");
+		 "See also BarnOwl::random_zephyr_signature().\n"),
 
   OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
@@ -263,5 +219,5 @@
 		 "unset, 'zsigproc' will be run to generate a zsig. If that is\n"
 		 "also unset, the 'zwrite-signature' zephyr variable will be\n"
-		 "used instead.\n");
+		 "used instead.\n"),
 
   OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
@@ -269,44 +225,44 @@
 		 "The sepbar is the bar separating the top and bottom\n"
 		 "of the BarnOwl screen.  Any string specified here will\n"
-		 "be displayed on the right of the sepbar\n");
+		 "be displayed on the right of the sepbar\n"),
 
   OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
-	       "turn zaway on or off", "" );
+	       "turn zaway on or off", "" ),
 
   OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
 		 OWL_DEFAULT_ZAWAYMSG,
-	         "zaway msg for responding to zephyrs when away", "" );
+	         "zaway msg for responding to zephyrs when away", "" ),
 
   OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
 		 OWL_DEFAULT_ZAWAYMSG,
-	         "default zaway message", "" );
+	         "default zaway message", "" ),
 
   OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,
 		    "Set AIM away status",
 		    "",
-		    NULL, owl_variable_aaway_set, NULL);
+		    NULL, owl_variable_aaway_set, NULL),
 
   OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, 
 		 OWL_DEFAULT_AAWAYMSG,
-	         "AIM away msg for responding when away", "" );
+	         "AIM away msg for responding when away", "" ),
 
   OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, 
 		 OWL_DEFAULT_AAWAYMSG,
-	         "default AIM away message", "" );
+	         "default AIM away message", "" ),
 
   OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
 	         "home view to switch to after 'X' and 'V'", 
-		 "SEE ALSO: view, filter\n" );
+		 "SEE ALSO: view, filter\n" ),
 
   OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
 		 "filter on which to trigger alert actions",
-		 "" );
+		 "" ),
 
   OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
 		 "BarnOwl command to execute for alert actions",
-		 "" );
+		 "" ),
 
   OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "<string>", "tty name for zephyr location", "",
-		      NULL, owl_variable_tty_set, NULL);
+		      NULL, owl_variable_tty_set, NULL),
 
   OWLVAR_STRING( "default_style" /* %OwlVarStub */, "default",
@@ -319,5 +275,5 @@
 		 "   perl     - legacy perl interface\n"
 		 "\nSEE ALSO: style, show styles, view -s <style>\n"
-		 );
+		 ),
 
 
@@ -326,5 +282,5 @@
                  "This specifies the maximum number of columns for M-q to fill text\n"
                  "to.  If set to 0, M-q will wrap to the width of the window, and\n"
-                 "values less than 0 disable M-q entirely.\n");
+                 "values less than 0 disable M-q entirely.\n"),
 
   OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 70,
@@ -335,5 +291,5 @@
                  "\n"
                  "As a courtesy to recipients, it is recommended that outgoing\n"
-                 "Zephyr messages be no wider than 70 columns.\n");
+                 "Zephyr messages be no wider than 70 columns.\n"),
 
   OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 15,
@@ -342,5 +298,5 @@
 	      "AIM login before allowing the receipt of AIM login notifications.\n"
 	      "By default this is set to 15.  If you would like to view login\n"
-	      "notifications of buddies as soon as you login, set it to 0 instead.");
+	      "notifications of buddies as soon as you login, set it to 0 instead."),
 
 	      
@@ -355,5 +311,5 @@
 		   owl_variable_typewinsize_set,
 		   NULL /* use default for get */
-		   );
+		   ),
 
   OWLVAR_INT( "typewindelta" /* %OwlVarStub */, 0,
@@ -365,5 +321,5 @@
            "typewinsize to 1.\n\n"
            "This works a lot better with a non-default scrollmode;\n"
-           "try :set scrollmode pagedcenter.\n");
+           "try :set scrollmode pagedcenter.\n"),
 
   OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
@@ -394,5 +350,5 @@
 	       "                 the screen will be paged up or down and\n"
 	       "                 the cursor will be near the center.\n",
-	       "normal,top,neartop,center,paged,pagedcenter" );
+	       "normal,top,neartop,center,paged,pagedcenter" ),
 
   OWLVAR_BOOL( "narrow-related" /* %OwlVarStub:narrow_related */, 1,
@@ -402,5 +358,5 @@
                "for Zephyr, this controls whether to narrow to e.g. class-help or\n"
                "class-help.d alone, or to related-class-help, which includes\n"
-               "help, unhelp, help.d, etc.\n\nDefault is true (include unclasses, etc.).\n" );
+               "help, unhelp, help.d, etc.\n\nDefault is true (include unclasses, etc.).\n" ),
 
   OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
@@ -409,5 +365,5 @@
 	       "continue to follow the last message if this is set.\n"
 	       "Note that this is currently risky as you might accidentally\n"
-	       "delete a message right as it came in.\n" );
+	       "delete a message right as it came in.\n" ),
 
   OWLVAR_STRING_FULL( "default_exposure" /* %OwlVarStub */, "",
@@ -418,5 +374,5 @@
                       "~/.zephyr.vars.\n"
                       "See the description of exposure for the values this can be.",
-                      NULL, owl_variable_default_exposure_set, owl_variable_default_exposure_get );
+                      NULL, owl_variable_default_exposure_set, owl_variable_default_exposure_get ),
 
   OWLVAR_STRING_FULL( "exposure" /* %OwlVarStub */, "",
@@ -474,5 +430,17 @@
                       "                     personal subscriptions will be entered for the\n"
                       "                     user.\n",
-                      NULL, owl_variable_exposure_set, NULL /* use default for get */ );
+                      NULL, owl_variable_exposure_set, NULL /* use default for get */ ),
+
+  /* This MUST be last... */
+  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL }
+
+  };
+
+  int ret = owl_variable_dict_add_from_list(vd, variables_to_init);
+  owl_variable *var;
+  for (var = variables_to_init; var->name != NULL; var++)
+    owl_variable_cleanup(var);
+  return ret;
 }
 
@@ -484,16 +452,20 @@
 /* commonly useful */
 
-int owl_variable_int_validate_gt0(const owl_variable *v, int newval)
-{
-  return !(newval < 1);
-}
-
-int owl_variable_int_validate_positive(const owl_variable *v, int newval)
-{
-  return !(newval < 0);
+int owl_variable_int_validate_gt0(const owl_variable *v, const void *newval)
+{
+  if (newval == NULL) return(0);
+  else if (*(const int*)newval < 1) return(0);
+  else return (1);
+}
+
+int owl_variable_int_validate_positive(const owl_variable *v, const void *newval)
+{
+  if (newval == NULL) return(0);
+  else if (*(const int*)newval < 0) return(0);
+  else return (1);
 }
 
 /* typewinsize */
-int owl_variable_typewinsize_set(owl_variable *v, int newval)
+int owl_variable_typewinsize_set(owl_variable *v, const void *newval)
 {
   int rv;
@@ -504,22 +476,26 @@
 
 /* debug (cache value in g->debug) */
-int owl_variable_debug_set(owl_variable *v, bool newval)
-{
-  g.debug = newval;
+int owl_variable_debug_set(owl_variable *v, const void *newval)
+{
+  if (newval && (*(const int*)newval == 1 || *(const int*)newval == 0)) {
+    g.debug = *(const int*)newval;
+  }
   return owl_variable_bool_set_default(v, newval);
 }
 
 /* When 'aaway' is changed, need to notify the AIM server */
-int owl_variable_aaway_set(owl_variable *v, bool newval)
+int owl_variable_aaway_set(owl_variable *v, const void *newval)
 {
   if (newval) {
-    owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
-  } else {
-    owl_aim_set_awaymsg("");
+    if (*(const int*)newval == 1) {
+      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
+    } else if (*(const int*)newval == 0) {
+      owl_aim_set_awaymsg("");
+    }
   }
   return owl_variable_bool_set_default(v, newval);
 }
 
-int owl_variable_colorztext_set(owl_variable *v, bool newval)
+int owl_variable_colorztext_set(owl_variable *v, const void *newval)
 {
   int ret = owl_variable_bool_set_default(v, newval);
@@ -534,16 +510,18 @@
 }
 
-int owl_variable_pseudologins_set(owl_variable *v, bool newval)
+int owl_variable_pseudologins_set(owl_variable *v, const void *newval)
 {
   static guint timer = 0;
   if (newval) {
-    owl_function_zephyr_buddy_check(0);
-    if (timer == 0) {
-      timer = g_timeout_add_seconds(180, owl_zephyr_buddycheck_timer, NULL);
-    }
-  } else {
-    if (timer != 0) {
-      g_source_remove(timer);
-      timer = 0;
+    if (*(const int*)newval == 1) {
+      owl_function_zephyr_buddy_check(0);
+      if (timer == 0) {
+        timer = g_timeout_add_seconds(180, owl_zephyr_buddycheck_timer, NULL);
+      }
+    } else {
+      if (timer != 0) {
+        g_source_remove(timer);
+        timer = 0;
+      }
     }
   }
@@ -553,10 +531,10 @@
 /* note that changing the value of this will clobber 
  * any user setting of this */
-int owl_variable_disable_ctrl_d_set(owl_variable *v, int newval)
-{
-  if (!owl_context_is_startup(owl_global_get_context(&g))) {
-    if (newval == 2) {
+int owl_variable_disable_ctrl_d_set(owl_variable *v, const void *newval)
+{
+  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
+    if (*(const int*)newval == 2) {
       owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
-    } else if (newval == 1) {
+    } else if (*(const int*)newval == 1) {
       owl_function_command_norv("bindkey editmulti C-d command edit:done-or-delete");
     } else {
@@ -564,24 +542,24 @@
     }
   }  
-  return owl_variable_int_set_default(v, newval);
-}
-
-int owl_variable_tty_set(owl_variable *v, const char *newval)
+  return owl_variable_int_set_default(v, newval);  
+}
+
+int owl_variable_tty_set(owl_variable *v, const void *newval)
 {
   owl_zephyr_set_locationinfo(g_get_host_name(), newval);
-  return owl_variable_string_set_default(v, newval);
-}
-
-int owl_variable_default_exposure_set(owl_variable *v, const char *newval)
+  return(owl_variable_string_set_default(v, newval));
+}
+
+int owl_variable_default_exposure_set(owl_variable *v, const void *newval)
 {
   return owl_zephyr_set_default_exposure(newval);
 }
 
-const char *owl_variable_default_exposure_get(const owl_variable *v)
+const void *owl_variable_default_exposure_get(const owl_variable *v)
 {
   return owl_zephyr_get_default_exposure();
 }
 
-int owl_variable_exposure_set(owl_variable *v, const char *newval)
+int owl_variable_exposure_set(owl_variable *v, const void *newval)
 {
   int ret = owl_zephyr_set_exposure(newval);
@@ -595,17 +573,78 @@
 /**************************************************************************/
 
-void owl_variable_dict_setup(owl_vardict *vd) {
+int owl_variable_dict_setup(owl_vardict *vd) {
   owl_dict_create(vd);
-  owl_variable_add_defaults(vd);
-}
-
-CALLER_OWN GClosure *owl_variable_make_closure(owl_variable *v,
-                                               GCallback fn,
-                                               GClosureMarshal marshal) {
-  GClosure *closure = g_cclosure_new_swap(fn, v, NULL);
-  g_closure_set_marshal(closure,marshal);
-  g_closure_ref(closure);
-  g_closure_sink(closure);
-  return closure;
+  return owl_variable_add_defaults(vd);
+}
+
+int owl_variable_dict_add_from_list(owl_vardict *vd, owl_variable *variables_to_init)
+{
+  owl_variable *var, *cur;
+  for (var = variables_to_init; var->name != NULL; var++) {
+    cur = g_new(owl_variable, 1);
+    *cur = *var;
+    /* strdup all the strings so we can delete them consistently. */
+    cur->name = g_strdup(var->name);
+    cur->summary = g_strdup(var->summary);
+    cur->description = g_strdup(var->description);
+    switch (cur->type) {
+    case OWL_VARIABLE_OTHER:
+      cur->set_fn(cur, cur->pval_default);
+      break;
+    case OWL_VARIABLE_STRING:
+      if (!cur->validate_fn) 
+	cur->validate_fn = owl_variable_string_validate_default;
+      if (!cur->set_fn) 
+	cur->set_fn = owl_variable_string_set_default;
+      if (!cur->set_fromstring_fn) 
+	cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
+      if (!cur->get_fn) 
+	cur->get_fn = owl_variable_get_default;
+      if (!cur->get_tostring_fn) 
+	cur->get_tostring_fn = owl_variable_string_get_tostring_default;      
+      if (!cur->delete_fn)
+	cur->delete_fn = owl_variable_delete_default;
+      cur->pval_default = g_strdup(var->pval_default);
+      cur->set_fn(cur, cur->pval_default);
+      break;
+    case OWL_VARIABLE_BOOL:
+      if (!cur->validate_fn) 
+	cur->validate_fn = owl_variable_bool_validate_default;
+      if (!cur->set_fn) 
+	cur->set_fn = owl_variable_bool_set_default;
+      if (!cur->set_fromstring_fn) 
+	cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
+      if (!cur->get_fn) 
+	cur->get_fn = owl_variable_get_default;
+      if (!cur->get_tostring_fn) 
+	cur->get_tostring_fn = owl_variable_bool_get_tostring_default;      
+      if (!cur->delete_fn)
+	cur->delete_fn = owl_variable_delete_default;
+      cur->val = g_new(int, 1);
+      cur->set_fn(cur, &cur->ival_default);
+      break;
+    case OWL_VARIABLE_INT:
+      if (!cur->validate_fn) 
+	cur->validate_fn = owl_variable_int_validate_default;
+      if (!cur->set_fn) 
+	cur->set_fn = owl_variable_int_set_default;
+      if (!cur->set_fromstring_fn) 
+	cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
+      if (!cur->get_fn) 
+	cur->get_fn = owl_variable_get_default;
+      if (!cur->get_tostring_fn) 
+	cur->get_tostring_fn = owl_variable_int_get_tostring_default;      
+      if (!cur->delete_fn)
+	cur->delete_fn = owl_variable_delete_default;
+      cur->val = g_new(int, 1);
+      cur->set_fn(cur, &cur->ival_default);
+      break;
+    default:
+      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
+      return(-2);
+    }
+    owl_dict_insert_element(vd, cur->name, cur, NULL);
+  }
+  return 0;
 }
 
@@ -615,148 +654,86 @@
 }
 
-static owl_variable *owl_variable_newvar(int type, const char *name, const char *summary, const char *description, const char *validsettings) {
-  owl_variable *var = g_new0(owl_variable, 1);
-  var->type = type;
+CALLER_OWN owl_variable *owl_variable_newvar(const char *name, const char *summary, const char *description)
+{
+  owl_variable * var = g_new0(owl_variable, 1);
   var->name = g_strdup(name);
   var->summary = g_strdup(summary);
   var->description = g_strdup(description);
-  var->validsettings = g_strdup(validsettings);
   return var;
 }
 
-static void owl_variable_dict_newvar_int_full(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validsettings, validate_int_t validate_fn, set_int_t set_fn, get_int_t get_fn)
-{
-  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_INT, name, summary,
-                                          description, validsettings);
-  var->takes_on_off = false;
-  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_int_get_default);
-  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_int_set_default);
-  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_int_validate_default);
-
-  var->get_tostring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_int_get_tostring_default),
-      g_cclosure_user_marshal_STRING__VOID);
-  var->set_fromstring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_int_set_fromstring_default),
-      g_cclosure_user_marshal_INT__STRING);
-
-  g_value_init(&var->val, G_TYPE_INT);
-  owl_variable_set_int(var, default_val);
-
-  var->default_str = owl_variable_get_tostring(var);
-  owl_variable_dict_add_variable(vd, var);
-}
-
-void owl_variable_dict_newvar_int(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description) {
-  owl_variable_dict_newvar_int_full(vd, name, default_val, summary, description,
-                                    "<int>", NULL, NULL, NULL);
-}
-
-static void owl_variable_dict_newvar_bool_full(owl_vardict *vd, const char *name, bool default_val, const char *summary, const char *description, validate_bool_t validate_fn, set_bool_t set_fn, get_bool_t get_fn)
-{
-  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_BOOL, name, summary,
-                                          description, "on,off");
-  var->takes_on_off = true;
-  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_bool_get_default);
-  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_bool_set_default);
-  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_bool_validate_default);
-
-  var->get_tostring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_bool_get_tostring_default),
-      g_cclosure_user_marshal_STRING__VOID);
-  var->set_fromstring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_bool_set_fromstring_default),
-      g_cclosure_user_marshal_INT__STRING);
-
-  g_value_init(&var->val, G_TYPE_BOOLEAN);
-  owl_variable_set_bool(var, default_val);
-
-  var->default_str = owl_variable_get_tostring(var);
-  owl_variable_dict_add_variable(vd, var);
-}
-
-void owl_variable_dict_newvar_bool(owl_vardict *vd, const char *name, bool default_val, const char *summary, const char *description) {
-  owl_variable_dict_newvar_bool_full(vd, name, default_val, summary, description,
-                                     NULL, NULL, NULL);
-}
-
-static void owl_variable_dict_newvar_string_full(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description, const char *validsettings, validate_string_t validate_fn, set_string_t set_fn, get_string_t get_fn)
-{
-  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_STRING, name, summary,
-                                          description, validsettings);
-  var->takes_on_off = false;
-  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_string_get_default);
-  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_string_set_default);
-  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_string_validate_default);
-
-  var->get_tostring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_string_get_tostring_default),
-      g_cclosure_user_marshal_STRING__VOID);
-  var->set_fromstring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_string_set_fromstring_default),
-      g_cclosure_user_marshal_INT__STRING);
-
-  g_value_init(&var->val, G_TYPE_STRING);
-  owl_variable_set_string(var, default_val);
-
-  var->default_str = owl_variable_get_tostring(var);
-  owl_variable_dict_add_variable(vd, var);
-}
-
-void owl_variable_dict_newvar_string(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description) {
-  owl_variable_dict_newvar_string_full(vd, name, default_val, summary, description,
-                                       "<string>", NULL, NULL, NULL);
-}
-
-void owl_variable_dict_newvar_path(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description) {
-  owl_variable_dict_newvar_string_full(vd, name, default_val, summary, description,
-                                       "<path>", NULL, NULL, NULL);
-}
-
-static void owl_variable_dict_newvar_enum_full(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validsettings, validate_int_t validate_fn, set_int_t set_fn, get_int_t get_fn)
-{
-  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_INT, name, summary,
-                                          description, validsettings);
-  var->takes_on_off = false;
-  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_int_get_default);
-  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_int_set_default);
-  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_enum_validate);
-
-  var->get_tostring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_enum_get_tostring),
-      g_cclosure_user_marshal_STRING__VOID);
-  var->set_fromstring_fn = owl_variable_make_closure(
-      var, G_CALLBACK(owl_variable_enum_set_fromstring),
-      g_cclosure_user_marshal_INT__STRING);
-
-  g_value_init(&var->val, G_TYPE_INT);
-  owl_variable_set_int(var, default_val);
-
-  var->default_str = owl_variable_get_tostring(var);
-  owl_variable_dict_add_variable(vd, var);
-}
-
-void owl_variable_dict_newvar_enum(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validset) {
-  owl_variable_dict_newvar_enum_full(vd, name, default_val, summary, description,
-                                     validset, NULL, NULL, NULL);
-}
-
-void owl_variable_dict_newvar_other(owl_vardict *vd, const char *name, const char *summary, const char *description, const char *validsettings, bool takes_on_off, GClosure *get_tostring_fn, GClosure *set_fromstring_fn)
-{
-  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_OTHER, name, summary,
-                                          description, validsettings);
-  var->takes_on_off = takes_on_off;
-
-  var->get_tostring_fn = g_closure_ref(get_tostring_fn);
-  g_closure_sink(get_tostring_fn);
-
-  var->set_fromstring_fn = g_closure_ref(set_fromstring_fn);
-  g_closure_sink(set_fromstring_fn);
-
-  var->default_str = owl_variable_get_tostring(var);
-
-  /* Note: this'll overwrite any existing variable of that name, even a C one,
-     but it's consistent with previous behavior and commands. */
-  owl_variable_dict_add_variable(vd, var);
+void owl_variable_update(owl_variable *var, const char *summary, const char *desc) {
+  g_free(var->summary);
+  var->summary = g_strdup(summary);
+  g_free(var->description);
+  var->description = g_strdup(desc);
+}
+
+void owl_variable_dict_newvar_string(owl_vardict *vd, const char *name, const char *summ, const char *desc, const char *initval)
+{
+  owl_variable *old = owl_variable_get_var(vd, name);
+  if (old && owl_variable_get_type(old) == OWL_VARIABLE_STRING) {
+    owl_variable_update(old, summ, desc);
+    g_free(old->pval_default);
+    old->pval_default = g_strdup(initval);
+  } else {
+    owl_variable * var = owl_variable_newvar(name, summ, desc);
+    var->type = OWL_VARIABLE_STRING;
+    var->validsettings = "<string>";
+    var->pval_default = g_strdup(initval);
+    var->set_fn = owl_variable_string_set_default;
+    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
+    var->get_fn = owl_variable_get_default;
+    var->get_tostring_fn = owl_variable_string_get_tostring_default;
+    var->delete_fn = owl_variable_delete_default;
+    var->set_fn(var, initval);
+    owl_variable_dict_add_variable(vd, var);
+  }
+}
+
+void owl_variable_dict_newvar_int(owl_vardict *vd, const char *name, const char *summ, const char *desc, int initval)
+{
+  owl_variable *old = owl_variable_get_var(vd, name);
+  if (old && owl_variable_get_type(old) == OWL_VARIABLE_INT) {
+    owl_variable_update(old, summ, desc);
+    old->ival_default = initval;
+  } else {
+    owl_variable * var = owl_variable_newvar(name, summ, desc);
+    var->type = OWL_VARIABLE_INT;
+    var->validsettings = "<int>";
+    var->ival_default = initval;
+    var->validate_fn = owl_variable_int_validate_default;
+    var->set_fn = owl_variable_int_set_default;
+    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
+    var->get_fn = owl_variable_get_default;
+    var->get_tostring_fn = owl_variable_int_get_tostring_default;
+    var->delete_fn = owl_variable_delete_default;
+    var->val = g_new(int, 1);
+    var->set_fn(var, &initval);
+    owl_variable_dict_add_variable(vd, var);
+  }
+}
+
+void owl_variable_dict_newvar_bool(owl_vardict *vd, const char *name, const char *summ, const char *desc, int initval)
+{
+  owl_variable *old = owl_variable_get_var(vd, name);
+  if (old && owl_variable_get_type(old) == OWL_VARIABLE_BOOL) {
+    owl_variable_update(old, summ, desc);
+    old->ival_default = initval;
+  } else {
+    owl_variable * var = owl_variable_newvar(name, summ, desc);
+    var->type = OWL_VARIABLE_BOOL;
+    var->validsettings = "on,off";
+    var->ival_default = initval;
+    var->validate_fn = owl_variable_bool_validate_default;
+    var->set_fn = owl_variable_bool_set_default;
+    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
+    var->get_fn = owl_variable_get_default;
+    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
+    var->delete_fn = owl_variable_delete_default;
+    var->val = g_new(int, 1);
+    var->set_fn(var, &initval);
+    owl_variable_dict_add_variable(vd, var);
+  }
 }
 
@@ -770,15 +747,17 @@
 }
 
-void owl_variable_delete(owl_variable *v)
-{
+void owl_variable_cleanup(owl_variable *v)
+{
+  if (v->delete_fn) v->delete_fn(v);
   g_free(v->name);
   g_free(v->summary);
   g_free(v->description);
-  g_free(v->default_str);
-  g_free(v->validsettings);
-  g_value_unset(&(v->val));
-  g_closure_unref(v->get_tostring_fn);
-  g_closure_unref(v->set_fromstring_fn);
-
+  if (v->type == OWL_VARIABLE_STRING)
+    g_free(v->pval_default);
+}
+
+void owl_variable_delete(owl_variable *v)
+{
+  owl_variable_cleanup(v);
   g_free(v);
 }
@@ -806,66 +785,46 @@
   return v->type;
 }
+
+/* functions for getting and setting variable values */
 
 /* returns 0 on success, prints a status msg if msg is true */
 int owl_variable_set_fromstring(owl_variable *v, const char *value, int msg) {
   char *tostring;
-  GValue values[] = {G_VALUE_INIT, G_VALUE_INIT};
-  GValue return_box = G_VALUE_INIT;
-  int set_successfully;
-
-  g_value_init(&values[0], G_TYPE_POINTER);
-  g_value_set_pointer(&values[0], NULL);
-  g_value_init(&values[1], G_TYPE_STRING);
-  g_value_set_static_string(&values[1], value);
-  g_value_init(&return_box, G_TYPE_INT);
-  g_closure_invoke(v->set_fromstring_fn, &return_box, 2, values, NULL);
-
-  set_successfully = g_value_get_int(&return_box);
-  if (0 != set_successfully) {
+  if (!v->set_fromstring_fn) {
+    if (msg) owl_function_error("Variable %s is read-only", owl_variable_get_name(v));
+    return -1;   
+  }
+  if (0 != v->set_fromstring_fn(v, value)) {
     if (msg) owl_function_error("Unable to set %s (must be %s)", owl_variable_get_name(v),
                                 owl_variable_get_validsettings(v));
-  } else if (msg) {
-    tostring = owl_variable_get_tostring(v);
-    if (tostring) {
+    return -1;
+  }
+  if (msg) {
+    tostring = v->get_tostring_fn(v, v->get_fn(v));
+    if (tostring)
       owl_function_makemsg("%s = '%s'", owl_variable_get_name(v), tostring);
-    } else {
+    else
       owl_function_makemsg("%s = <null>", owl_variable_get_name(v));
-    }
     g_free(tostring);
-  }
-
-  g_value_unset(&return_box);
-  g_value_unset(&values[1]);
-  g_value_unset(&values[0]);
-  return set_successfully;
+  }    
+  return 0;
 }
  
 int owl_variable_set_string(owl_variable *v, const char *newval)
 {
-  g_return_val_if_fail(v->type == OWL_VARIABLE_STRING, -1);
-
-  set_string_t cb = (set_string_t) v->set_fn;
-  return cb(v, newval);
-}
-
+  if (v->type != OWL_VARIABLE_STRING) return -1;
+  return v->set_fn(v, newval);
+}
+ 
 int owl_variable_set_int(owl_variable *v, int newval)
 {
-  g_return_val_if_fail(v->type == OWL_VARIABLE_INT, -1);
-
-  set_int_t cb = (set_int_t) v->set_fn;
-  return cb(v, newval);
-}
-
-int owl_variable_set_bool(owl_variable *v, bool newval) {
-  g_return_val_if_fail(v->type == OWL_VARIABLE_BOOL, -1);
-
-  set_bool_t cb = (set_bool_t) v->set_fn;
-  return cb(v, newval);
-}
-
+  if (v->type != OWL_VARIABLE_INT && v->type != OWL_VARIABLE_BOOL) return -1;
+  return v->set_fn(v, &newval);
+}
+ 
 int owl_variable_set_bool_on(owl_variable *v)
 {
   if (v->type != OWL_VARIABLE_BOOL) return -1;
-  return owl_variable_set_bool(v, true);
+  return owl_variable_set_int(v, true);
 }
 
@@ -873,28 +832,19 @@
 {
   if (v->type != OWL_VARIABLE_BOOL) return -1;
-  return owl_variable_set_bool(v, false);
+  return owl_variable_set_int(v, false);
 }
 
 CALLER_OWN char *owl_variable_get_tostring(const owl_variable *v)
 {
-  GValue instance = G_VALUE_INIT;
-  GValue tostring_box = G_VALUE_INIT;
-  char *ret = NULL;
-
-  g_value_init(&instance, G_TYPE_POINTER);
-  g_value_set_pointer(&instance, NULL);
-  g_value_init(&tostring_box, G_TYPE_STRING);
-  g_closure_invoke(v->get_tostring_fn, &tostring_box, 1, &instance, NULL);
-
-  ret = g_value_dup_string(&tostring_box);
-
-  g_value_unset(&tostring_box);
-  g_value_unset(&instance);
-  return ret;
-}
-
-const char *owl_variable_get_default_tostring(const owl_variable *v)
-{
-  return v->default_str;
+  return v->get_tostring_fn(v, v->get_fn(v));
+}
+
+CALLER_OWN char *owl_variable_get_default_tostring(const owl_variable *v)
+{
+  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
+    return v->get_tostring_fn(v, &(v->ival_default));
+  } else {
+    return v->get_tostring_fn(v, v->pval_default);
+  }
 }
 
@@ -904,35 +854,58 @@
 }
 
+/* returns a reference */
+const void *owl_variable_get(const owl_variable *v)
+{
+  return v->get_fn(v);
+}
+
 const char *owl_variable_get_string(const owl_variable *v)
 {
-  g_return_val_if_fail(v->type == OWL_VARIABLE_STRING, NULL);
-
-  get_string_t cb = (get_string_t) v->get_fn;
-  return cb(v);
+  if (owl_variable_get_type(v) != OWL_VARIABLE_STRING) {
+    owl_function_error("Variable '%s' is not a string.", owl_variable_get_name(v));
+    return NULL;
+  }
+  return owl_variable_get(v);
+}
+
+/* returns a reference */
+const void *owl_variable_get_other(const owl_variable *v)
+{
+  if (owl_variable_get_type(v) != OWL_VARIABLE_OTHER) {
+    owl_function_error("Variable '%s' is not type other.", owl_variable_get_name(v));
+    return NULL;
+  }
+  return owl_variable_get(v);
 }
 
 int owl_variable_get_int(const owl_variable *v)
 {
-  g_return_val_if_fail(v->type == OWL_VARIABLE_INT, 0);
-
-  get_int_t cb = (get_int_t) v->get_fn;
-  return cb(v);
-}
-
-bool owl_variable_get_bool(const owl_variable *v)
-{
-  g_return_val_if_fail(v->type == OWL_VARIABLE_BOOL, FALSE);
-
-  get_bool_t cb = (get_bool_t) v->get_fn;
-  return cb(v);
+  if (owl_variable_get_type(v) != OWL_VARIABLE_INT) {
+    owl_function_error("Variable '%s' is an int.", owl_variable_get_name(v));
+    return -1;
+  }
+  const int *pi = owl_variable_get(v);
+  if (!pi) return -1;
+  return *pi;
+}
+
+int owl_variable_get_bool(const owl_variable *v)
+{
+  if (owl_variable_get_type(v) != OWL_VARIABLE_BOOL) {
+    owl_function_error("Variable '%s' is a boolean.", owl_variable_get_name(v));
+    return -1;
+  }
+  const int *pi = owl_variable_get(v);
+  if (!pi) return -1;
+  return *pi;
 }
 
 void owl_variable_describe(const owl_variable *v, owl_fmtext *fm)
 {
-  const char *default_str = owl_variable_get_default_tostring(v);
+  char *tostring = owl_variable_get_default_tostring(v);
   char *default_buf;
 
-  if (default_str)
-    default_buf = g_strdup_printf("'%s'", default_str);
+  if (tostring)
+    default_buf = g_strdup_printf("'%s'", tostring);
   else
     default_buf = g_strdup("<null>");
@@ -941,9 +914,9 @@
                             owl_variable_get_summary(v), default_buf);
   g_free(default_buf);
+  g_free(tostring);
 }
 
 void owl_variable_get_help(const owl_variable *v, owl_fmtext *fm) {
   char *tostring;
-  const char *default_str;
 
   owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
@@ -960,7 +933,8 @@
   owl_fmtext_append_normal(fm, "\n\n");
 
-  default_str = owl_variable_get_default_tostring(v);
+
+  tostring = owl_variable_get_default_tostring(v);
   owl_fmtext_append_normal(fm, "Default:        ");
-  owl_fmtext_append_normal(fm, (default_str ? default_str : "<null>"));
+  owl_fmtext_append_normal(fm, (tostring ? tostring : "<null>"));
   owl_fmtext_append_normal(fm, "\n\n");
 
@@ -974,4 +948,5 @@
     owl_fmtext_append_normal(fm, "\n\n");
   }
+  g_free(tostring);
 }
 
@@ -985,49 +960,44 @@
 /* default common functions */
 
-const char *owl_variable_string_get_default(const owl_variable *v) {
-  return g_value_get_string(&(v->val));
-}
-
-int owl_variable_int_get_default(const owl_variable *v) {
-  return g_value_get_int(&(v->val));
-}
-
-bool owl_variable_bool_get_default(const owl_variable *v) {
-  return g_value_get_boolean(&(v->val));
+const void *owl_variable_get_default(const owl_variable *v) {
+  return v->val;
+}
+
+void owl_variable_delete_default(owl_variable *v)
+{
+  g_free(v->val);
 }
 
 /* default functions for booleans */
 
-int owl_variable_bool_validate_default(const owl_variable *v, bool newval) {
-  return (newval == 1) || (newval == 0);
-}
-
-int owl_variable_bool_set_default(owl_variable *v, bool newval) {
-  if (!((validate_bool_t)v->validate_fn)(v, newval))
-    return -1;
-
-  g_value_set_boolean(&(v->val), newval);
+int owl_variable_bool_validate_default(const owl_variable *v, const void *newval) {
+  if (newval == NULL) return(0);
+  else if (*(const int*)newval==1 || *(const int*)newval==0) return(1);
+  else return (0);
+}
+
+int owl_variable_bool_set_default(owl_variable *v, const void *newval) {
+  if (v->validate_fn) {
+    if (!v->validate_fn(v, newval)) return(-1);
+  }
+  *(int*)v->val = *(const int*)newval;
   return(0);
 }
 
-int owl_variable_bool_set_fromstring_default(owl_variable *v, const char *newval, void *dummy) {
-  bool i;
-  if (!strcmp(newval, "on")) {
-    i = true;
-  } else if (!strcmp(newval, "off")) {
-    i = false;
-  } else {
-    return(-1);
-  }
-
-  return owl_variable_set_bool(v, i);
-}
-
-CALLER_OWN char *owl_variable_bool_get_tostring_default(const owl_variable *v, void *dummy)
-{
-  bool val = owl_variable_get_bool(v);
-  if (val == 0) {
+int owl_variable_bool_set_fromstring_default(owl_variable *v, const char *newval) {
+  int i;
+  if (!strcmp(newval, "on")) i=1;
+  else if (!strcmp(newval, "off")) i=0;
+  else return(-1);
+  return (v->set_fn(v, &i));
+}
+
+CALLER_OWN char *owl_variable_bool_get_tostring_default(const owl_variable *v, const void *val)
+{
+  if (val == NULL) {
+    return NULL;
+  } else if (*(const int*)val == 0) {
     return g_strdup("off");
-  } else if (val == 1) {
+  } else if (*(const int*)val == 1) {
     return g_strdup("on");
   } else {
@@ -1038,39 +1008,44 @@
 /* default functions for integers */
 
-int owl_variable_int_validate_default(const owl_variable *v, int newval)
-{
-  return (1);
-}
-
-int owl_variable_int_set_default(owl_variable *v, int newval) {
-  if (!((validate_int_t)v->validate_fn)(v, newval))
-    return -1;
-
-  g_value_set_int(&(v->val), newval);
+int owl_variable_int_validate_default(const owl_variable *v, const void *newval) {
+  if (newval == NULL) return(0);
+  else return (1);
+}
+
+int owl_variable_int_set_default(owl_variable *v, const void *newval) {
+  if (v->validate_fn) {
+    if (!v->validate_fn(v, newval)) return(-1);
+  }
+  *(int*)v->val = *(const int*)newval;
   return(0);
 }
 
-int owl_variable_int_set_fromstring_default(owl_variable *v, const char *newval, void *dummy) {
+int owl_variable_int_set_fromstring_default(owl_variable *v, const char *newval) {
   int i;
   char *ep;
   i = strtol(newval, &ep, 10);
   if (*ep || ep==newval) return(-1);
-  return owl_variable_set_int(v, i);
-}
-
-CALLER_OWN char *owl_variable_int_get_tostring_default(const owl_variable *v, void *dummy)
-{
-  return g_strdup_printf("%d", owl_variable_get_int(v));
+  return (v->set_fn(v, &i));
+}
+
+CALLER_OWN char *owl_variable_int_get_tostring_default(const owl_variable *v, const void *val)
+{
+  if (val == NULL) {
+    return NULL;
+  } else {
+    return g_strdup_printf("%d", *(const int*)val);
+  } 
 }
 
 /* default functions for enums (a variant of integers) */
 
-int owl_variable_enum_validate(const owl_variable *v, int newval) {
+int owl_variable_enum_validate(const owl_variable *v, const void *newval) {  
   char **enums;
   int nenums, val;
+  if (newval == NULL) return(0);
   enums = g_strsplit_set(v->validsettings, ",", 0);
   nenums = g_strv_length(enums);
   g_strfreev(enums);
-  val = newval;
+  val = *(const int*)newval;
   if (val < 0 || val >= nenums) {
     return(0);
@@ -1079,5 +1054,5 @@
 }
 
-int owl_variable_enum_set_fromstring(owl_variable *v, const char *newval, void *dummy) {
+int owl_variable_enum_set_fromstring(owl_variable *v, const char *newval) {
   char **enums;
   int i, val=-1;
@@ -1091,8 +1066,8 @@
   g_strfreev(enums);
   if (val == -1) return(-1);
-  return owl_variable_set_int(v, val);
-}
-
-CALLER_OWN char *owl_variable_enum_get_tostring(const owl_variable *v, void *dummy)
+  return (v->set_fn(v, &val));
+}
+
+CALLER_OWN char *owl_variable_enum_get_tostring(const owl_variable *v, const void *val)
 {
   char **enums;
@@ -1100,7 +1075,10 @@
   char *tostring;
 
+  if (val == NULL) {
+    return NULL;
+  }
   enums = g_strsplit_set(v->validsettings, ",", 0);
   nenums = g_strv_length(enums);
-  i = owl_variable_get_int(v);
+  i = *(const int*)val;
   if (i<0 || i>=nenums) {
     g_strfreev(enums);
@@ -1114,25 +1092,25 @@
 /* default functions for stringeans */
 
-int owl_variable_string_validate_default(const owl_variable *v, const char *newval) {
+int owl_variable_string_validate_default(const struct _owl_variable *v, const void *newval) {
   if (newval == NULL) return(0);
   else return (1);
 }
 
-int owl_variable_string_set_default(owl_variable *v, const char *newval) {
-  if (!((validate_string_t)v->validate_fn)(v, newval))
-    return -1;
-
-  g_value_set_string(&(v->val), newval);
+int owl_variable_string_set_default(owl_variable *v, const void *newval) {
+  if (v->validate_fn) {
+    if (!v->validate_fn(v, newval)) return(-1);
+  }
+  g_free(v->val);
+  v->val = g_strdup(newval);
   return(0);
 }
 
-int owl_variable_string_set_fromstring_default(owl_variable *v, const char *newval, void *dummy) 
-{
-  return owl_variable_set_string(v, newval);
-}
-
-CALLER_OWN char *owl_variable_string_get_tostring_default(const owl_variable *v, void *dummy)
-{
-  return g_strdup(owl_variable_get_string(v));
-}
-
+int owl_variable_string_set_fromstring_default(owl_variable *v, const char *newval) {
+  return (v->set_fn(v, newval));
+}
+
+CALLER_OWN char *owl_variable_string_get_tostring_default(const owl_variable *v, const void *val)
+{
+  return g_strdup((const char*)val);
+}
+
