[Config] Add type-safe configuration parsing
authorIra W. Snyder <devel@irasnyder.com>
Mon, 28 Jan 2008 04:42:18 +0000 (20:42 -0800)
committerIra W. Snyder <devel@irasnyder.com>
Mon, 28 Jan 2008 04:42:18 +0000 (20:42 -0800)
This makes the GKeyFile engine do the parsing for all of the GObject
properties, instead of rolling our own. The default configuration was
moved to a file (share-tilda.conf) which will live in /usr/share when
the project is autoconfed.

The rewritten configuration parser determines the type of parameter
given to it using its type registration, then invokes the appropriate
parser in GKeyFile. The whole thing is basically function overloading
from C++, but done in C.

I also exported all of the enums to the tilda-types.[ch] files, then
hooked them into the GType system so they can be auto-parsed later.
The config file parser is actually pretty nice, because it allows
you to use the enum value's nick in the configuration file. It's
harder for us as programmers (and harder on the computer) but it sure
makes for a pretty configuration file. Might as well make the computer
work /for/ us after all. ^_^

Sorry about the huge changeset.

Makefile
share-tilda.conf [new file with mode: 0644]
tilda-config.c
tilda-config.h
tilda-terminal.c
tilda-terminal.h
tilda-types.c [new file with mode: 0644]
tilda-types.h [new file with mode: 0644]
tilda-window.c
tilda-window.h

index 7ce6909..8c5890c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ GCC=gcc
 # Normal CFLAGS
 CFLAGS=-ggdb -O1 -pipe -Wshadow -Wall -DDEBUG=1
 LDFLAGS=-Wl,-O1 -Wl,--sort-common -Wl,--as-needed
-#CFLAGS=-ggdb -O1 -pipe -DDEBUG=1 -ffunction-sections -fdata-sections
+#CFLAGS=-ggdb -O1 -pipe -ffunction-sections -fdata-sections -DDEBUG=1
 #LDFLAGS=-Wl,--gc-sections -Wl,--print-gc-sections
 GOBJ_CFLAGS=`pkg-config --cflags gobject-2.0`
 GOBJ_LIBS=`pkg-config --libs gobject-2.0`
@@ -15,12 +15,15 @@ ALL_LIBS=`pkg-config --libs gtk+-2.0 vte dbus-glib-1`
 
 all: tilda
 
-tilda: tilda.o tilda-config.o tilda-controller.o tilda-window.o tilda-terminal.o tomboykeybinder.o eggaccelerators.o
+tilda: tilda.o tilda-types.o tilda-config.o tilda-controller.o tilda-window.o tilda-terminal.o tomboykeybinder.o eggaccelerators.o
        $(GCC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(ALL_LIBS)
 
 tilda.o: tilda.c tilda.h
        $(GCC) $(CFLAGS) -c -o $@ $< $(ALL_CFLAGS)
 
+tilda-types.o: tilda-types.c tilda-types.h
+       $(GCC) $(CFLAGS) -c -o $@ $< $(ALL_CFLAGS)
+
 tilda-config.o: tilda-config.c tilda-config.h
        $(GCC) $(CFLAGS) -c -o $@ $< $(ALL_CFLAGS)
 
diff --git a/share-tilda.conf b/share-tilda.conf
new file mode 100644 (file)
index 0000000..1e8b474
--- /dev/null
@@ -0,0 +1,47 @@
+# Default configuration values for the Tilda terminal emulator
+#
+# This file is required if you want Tilda to run reliably, and
+# also if you want it to have sane default values.
+#
+# Get a copy of Tilda from http://tilda.sourceforge.net
+#
+
+[controller-defaults]
+initial-windows = 1
+
+[window-defaults]
+height = 300
+width = 600
+x-position = 0
+y-position = 0
+initial-terminals = 1
+tab-position = top
+animation-orientation = top
+keep-above = true
+skip-taskbar-hint = true
+stick = true
+hidden-at-start = false
+centered-horizontally = false
+centered-vertically = false
+
+[terminal-defaults]
+font = Bitstream Vera Sans Mono 12
+title = Tilda
+web-browser = firefox
+scrollback-lines = 2000
+transparency-percent = 0
+backspace-binding = auto
+delete-binding = auto
+dynamic-title = after-initial
+exit-action = exit
+scrollbar-position = right
+scroll-background = false
+scroll-on-output = false
+scroll-on-keystroke = true
+antialiased = true
+allow-bold-text = true
+cursor-blinks = true
+audible-bell = false
+visible-bell = true
+double-buffered = true
+mouse-autohide = true
index c8afbc2..8732793 100644 (file)
@@ -2,8 +2,15 @@
 #include "translation.h"
 #include "tilda-config.h"
 
-GHashTable *config_defaults = NULL;
-GKeyFile   *config_userprefs = NULL;
+#include "tilda.h"
+#include "tilda-types.h"
+#include "tilda-window.h"
+#include "tilda-terminal.h"
+#include <glib-object.h>
+#include <stdlib.h>
+
+GKeyFile *config_defaults = NULL;
+GKeyFile *config_userprefs = NULL;
 
 /*
  * TODO:
@@ -24,103 +31,428 @@ GKeyFile   *config_userprefs = NULL;
  * I thought this would be the most logical solution.
  */
 
-/**
- * This function adds all of the defaults to the defaults hashtable.
- * It just uses their names, since there are currently no conflicts
- * in the properties of TildaWindow and TildaTerminal. If conflicts
- * become a problem in the future, prefix them with "w-" and "t-",
- * for example. Then fix up all callers. :) */
-static void
-tilda_config_setup_defaults ()
+/* NOTE NOTE NOTE:
+ * This essentially works. You still need to feasibility-test it to make sure that
+ * everything pulls out of the gkeyfile ok. And you need to add the lookup code.
+ *
+ * Other than that, this is a mostly generic version :) !!!
+ */
+
+static gboolean
+tilda_config_parse_integer (GKeyFile    *keyfile,
+                                                       const gchar *group_name,
+                                                       const gchar *key,
+                                                       GValue      *value,
+                                                       GError     **user_error)
 {
-       /* NOTE: All properties must be specified as strings. This sucks, but it really
-        * is easiest to keep it this way. We can then implement custom functions to
-        * change the values as we need them. */
-
-       /* Window properties */
-       g_hash_table_insert (config_defaults, "key", NULL);
-       g_hash_table_insert (config_defaults, "height", "300");
-       g_hash_table_insert (config_defaults, "width", "600");
-       g_hash_table_insert (config_defaults, "x-position", "0");
-       g_hash_table_insert (config_defaults, "y-position", "0");
-       g_hash_table_insert (config_defaults, "initial-terminals", "1");
-       g_hash_table_insert (config_defaults, "tab-position", "top");
-       g_hash_table_insert (config_defaults, "animation-orientation", "top");
-       g_hash_table_insert (config_defaults, "animation-delay", "15000");
-       g_hash_table_insert (config_defaults, "keep-above", "true");
-       g_hash_table_insert (config_defaults, "skip-taskbar-hint", "true");
-       g_hash_table_insert (config_defaults, "stick", "true");
-       g_hash_table_insert (config_defaults, "hidden-at-start", "false");
-       g_hash_table_insert (config_defaults, "centered-horizontally", "false");
-       g_hash_table_insert (config_defaults, "centered-vertically", "false");
-
-       /* Terminal Properties */
-       g_hash_table_insert (config_defaults, "background-image", NULL);
-       g_hash_table_insert (config_defaults, "shell", NULL);
-       g_hash_table_insert (config_defaults, "font", "Bitstream Vera Sans Mono 12");
-       g_hash_table_insert (config_defaults, "title", "Tilda");
-       g_hash_table_insert (config_defaults, "working-directory", NULL);
-       g_hash_table_insert (config_defaults, "web-browser", "firefox");
-       g_hash_table_insert (config_defaults, "scrollback-lines", "1000");
-       g_hash_table_insert (config_defaults, "transparency-percent", "0");
-       g_hash_table_insert (config_defaults, "backspace-binding", "vte-erase-auto");
-       g_hash_table_insert (config_defaults, "delete-binding", "vte-erase-auto");
-       g_hash_table_insert (config_defaults, "dynamic-title", "after-initial");
-       g_hash_table_insert (config_defaults, "exit-action", "exit");
-       g_hash_table_insert (config_defaults, "scrollbar-position", "right");
-#if 0
-       /* These don't have properties yet! */
-       g_hash_table_insert (config_defaults, "background-color", "0;0;0");
-       g_hash_table_insert (config_defaults, "foreground-color", "255;255;255");
-#endif
-       g_hash_table_insert (config_defaults, "scroll-background", "false");
-       g_hash_table_insert (config_defaults, "scroll-on-output", "false");
-       g_hash_table_insert (config_defaults, "scroll-on-keystroke", "true");
-       g_hash_table_insert (config_defaults, "antialiased", "true");
-       g_hash_table_insert (config_defaults, "allow-bold-text", "true");
-       g_hash_table_insert (config_defaults, "cursor-blinks", "true");
-       g_hash_table_insert (config_defaults, "audible-bell", "false");
-       g_hash_table_insert (config_defaults, "visible-bell", "true");
-       g_hash_table_insert (config_defaults, "double-buffered", "true");
-       g_hash_table_insert (config_defaults, "mouse-autohide", "true");
+       debug_enter  ();
+       debug_assert (G_IS_VALUE(value));
+
+       GError *error = NULL;
+       gint ret;
+
+       /* Try to get the value */
+       ret = g_key_file_get_integer (keyfile, group_name, key, &error);
+
+       /* Check for error */
+       if (error)
+       {
+               g_propagate_error (user_error, error);
+               return FALSE;
+       }
+
+       /* We successfully parsed the int, so set it in the GValue */
+       g_value_set_int (value, ret);
+
+       return TRUE;
+}
+
+static gboolean
+tilda_config_parse_boolean (GKeyFile    *keyfile,
+                                                       const gchar *group_name,
+                                                       const gchar *key,
+                                                       GValue      *value,
+                                                       GError     **user_error)
+{
+       debug_enter  ();
+       debug_assert (G_IS_VALUE(value));
+
+       GError *error = NULL;
+       gboolean ret;
+
+       /* Try to get the value */
+       ret = g_key_file_get_boolean (keyfile, group_name, key, &error);
+
+       /* Check for error */
+       if (error)
+       {
+               g_propagate_error (user_error, error);
+               return FALSE;
+       }
+
+       /* Success */
+       g_value_set_boolean (value, ret);
+
+       return TRUE;
+}
+
+static gboolean
+tilda_config_parse_string (GKeyFile    *keyfile,
+                                                  const gchar *group_name,
+                                                  const gchar *key,
+                                                  GValue      *value,
+                                                  GError **user_error)
+{
+       debug_enter  ();
+       debug_assert (G_IS_VALUE(value));
+
+       GError *error = NULL;
+       gchar *ret;
+
+       /* Try to get the value */
+       ret = g_key_file_get_string (keyfile, group_name, key, &error);
+
+       /* Check for error */
+       if (error)
+       {
+               g_propagate_error (user_error, error);
+               return FALSE;
+       }
+
+       /* Success */
+       g_value_set_string (value, ret);
+
+       return TRUE;
+}
+
+#define key_is(STR) (g_ascii_strcasecmp(key,(STR)) == 0)
+
+static gboolean
+tilda_config_parse_enum (GKeyFile    *keyfile,
+                                                const gchar *group_name,
+                                                const gchar *key,
+                                                GValue      *value,
+                                                GError     **user_error)
+{
+       gchar *ret;
+       GError *error = NULL;
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+
+       if (key_is("backspace-binding") || key_is("delete-binding"))
+               enum_class = g_type_class_peek (vte_terminal_erase_binding_get_type());
+       else if (key_is("dynamic-title"))
+               enum_class = g_type_class_peek (tilda_dynamic_title_get_type());
+       else if (key_is("exit-action"))
+               enum_class = g_type_class_peek (tilda_child_exit_action_get_type());
+       else if (key_is("scrollbar-position"))
+               enum_class = g_type_class_peek (tilda_scrollbar_position_get_type());
+       else if (key_is("animation-orientation") || key_is("tab-position"))
+               enum_class = g_type_class_peek (gtk_position_type_get_type());
+       else
+       {
+               g_critical ("FIXME: developer error -- unknown enum key used: %s\n", key);
+               exit (1);
+               return FALSE;
+       }
+
+       /* Get the value from the config as a string */
+       ret = g_key_file_get_string (keyfile, group_name, key, &error);
+
+       if (error)
+       {
+               g_propagate_error (user_error, error);
+               return FALSE;
+       }
+
+       enum_value = g_enum_get_value_by_nick (enum_class, ret);
+
+       if (!enum_value)
+       {
+               /* This is exactly the same error that is returned by g_key_file_get_integer()
+                * when it cannot correctly parse the value. */
+               g_set_error (user_error,
+                                        G_KEY_FILE_ERROR,
+                                        G_KEY_FILE_ERROR_INVALID_VALUE,
+                                        _("Key file contains key '%s' in group '%s' which has value that cannot be interpreted."), key, group_name);
+               return FALSE;
+       }
+
+       /* All was successful, let's set it */
+       g_value_set_enum (value, enum_value->value);
+       return TRUE;
 }
 
 gboolean
-tilda_config_init (const gchar *filename)
+tilda_window_set_property_from_config (TildaWindow *self, const gchar *property)
 {
+       debug_enter  ();
+       debug_assert (TILDA_IS_WINDOW(self));
+
+       gchar *group_name;
        GError *error = NULL;
+       gboolean ret;
+
+       GParamSpec *pspec;
+       GValue *value = g_malloc0(sizeof(GValue));
+       gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
+
+       /* Get the pspec for this property */
+       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS(self), property);
 
-       /* Create the hashtable */
-       config_defaults = g_hash_table_new (g_str_hash, g_str_equal);
+       /* Make sure that this property exists */
+       if (pspec == NULL)
+       {
+               g_critical ("FIXME: developer error -- unable to find property: %s\n", property);
+               exit (1);
+       }
 
-       /* Fill it with the default values */
-       tilda_config_setup_defaults ();
+       /* Initialize the GValue that is going to hold the returned value */
+       g_value_init (value, pspec->value_type);
 
-       /* If we have no file to read from, then we are just using the defaults,
-        * and are done. */
-       if (filename == NULL)
+       /* Set the correct function to do the parsing */
+       if      (g_type_is_a (pspec->value_type, G_TYPE_INT))
+               parse_func = tilda_config_parse_integer;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_BOOLEAN))
+               parse_func = tilda_config_parse_boolean;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_STRING))
+               parse_func = tilda_config_parse_string;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_ENUM))
+               parse_func = tilda_config_parse_enum;
+       else
        {
-               config_userprefs = NULL;
-               return TRUE;
+               g_critical ("FIXME: developer error -- unknown property type: %s\n", g_type_name(pspec->value_type));
+               exit(1);
        }
 
-       /* Create the key file */
+       /* Do the [Window] lookup */
+       group_name = g_strdup_printf ("Window%d", self->number);
+       ret = parse_func (config_userprefs, group_name, property, value, &error);
+       g_free (group_name);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [Global] lookup */
+       ret = parse_func (config_userprefs, "Global", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [window-defaults] lookup */
+       ret = parse_func (config_defaults, "window-defaults", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+
+               /* This is somewhat of a nasty hack, but I really do want to just set the property to
+                * NULL if there is no default, but ONLY for strings. */
+               if (parse_func == tilda_config_parse_string)
+               {
+                       g_value_set_string (value, NULL);
+                       goto success;
+               }
+       }
+       else
+               goto success;
+
+//failure:
+       g_critical (_("Unable to find a value for window property: %s\n"), property);
+       return FALSE;
+
+success:
+       g_object_set_property (G_OBJECT(self), property, value);
+       g_value_unset (value);
+       g_free (value);
+       return TRUE;
+}
+
+gboolean
+tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *property)
+{
+       debug_enter  ();
+       debug_assert (TILDA_IS_TERMINAL(self));
+
+       TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
+       gchar *group_name;
+       GError *error = NULL;
+       gboolean ret;
+
+       GParamSpec *pspec;
+       GValue *value = g_malloc0(sizeof(GValue));
+       gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
+
+       /* Get the pspec for this property */
+       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS(self), property);
+
+       /* Make sure that this property exists */
+       if (pspec == NULL)
+       {
+               g_critical ("FIXME: developer error -- unable to find property: %s\n", property);
+               exit (1);
+       }
+
+       /* Initialize the GValue that is going to hold the returned value */
+       g_value_init (value, pspec->value_type);
+
+       /* Set the correct function to do the parsing */
+       if      (g_type_is_a (pspec->value_type, G_TYPE_INT))
+               parse_func = tilda_config_parse_integer;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_BOOLEAN))
+               parse_func = tilda_config_parse_boolean;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_STRING))
+               parse_func = tilda_config_parse_string;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_ENUM))
+               parse_func = tilda_config_parse_enum;
+       else
+       {
+               g_critical ("FIXME: developer error -- unknown property type: %s\n", g_type_name(pspec->value_type));
+               exit(1);
+       }
+
+       /* Do the [Window/Terminal] lookup */
+       group_name = g_strdup_printf ("Window%d/Terminal%d", parent_window->number, self->number);
+       ret = parse_func (config_userprefs, group_name, property, value, &error);
+       g_free (group_name);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [Window] lookup */
+       group_name = g_strdup_printf ("Window%d", parent_window->number);
+       ret = parse_func (config_userprefs, group_name, property, value, &error);
+       g_free (group_name);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [Global] lookup */
+       ret = parse_func (config_userprefs, "Global", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [terminal-defaults] lookup */
+       ret = parse_func (config_defaults, "terminal-defaults", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+
+               /* This is somewhat of a nasty hack, but I really do want to just set the property to
+                * NULL if there is no default, but ONLY for strings. */
+               if (parse_func == tilda_config_parse_string)
+               {
+                       g_value_set_string (value, NULL);
+                       goto success;
+               }
+       }
+       else
+               goto success;
+
+//failure:
+       g_critical (_("Unable to find a value for terminal property: %s\n"), property);
+       return FALSE;
+
+success:
+       g_object_set_property (G_OBJECT(self), property, value);
+       g_value_unset (value);
+       g_free (value);
+       return TRUE;
+}
+
+gboolean
+tilda_config_init (const gchar *userprefs_filename)
+{
+       gchar *defaults_filename;
+       GError *error = NULL;
+
+       /* Call g_type_class_ref() on all enum types that are being used */
+       g_type_class_ref (vte_terminal_erase_binding_get_type());
+       g_type_class_ref (tilda_dynamic_title_get_type());
+       g_type_class_ref (tilda_child_exit_action_get_type());
+       g_type_class_ref (tilda_scrollbar_position_get_type());
+       g_type_class_ref (gtk_position_type_get_type());
+
+       /* Create the defaults file's path */
+       defaults_filename = g_build_filename ("share-tilda.conf", NULL); // FIXME: use /usr/share/tilda
+
+       /* Create the keyfiles */
+       config_defaults = g_key_file_new ();
        config_userprefs = g_key_file_new ();
 
-       if (!g_file_test (filename, G_FILE_TEST_EXISTS))
+       /* Check if the defaults exist, and load them */
+       if (!g_file_test (defaults_filename, G_FILE_TEST_EXISTS))
+       {
+               g_critical (_("No configuration defaults file found. Tilda may not work.\n"));
+       }
+       else
        {
-               g_warning (_("No config file found, using defaults\n"));
-               return TRUE;
+               if (!g_key_file_load_from_file (config_defaults, defaults_filename, G_KEY_FILE_NONE, &error))
+               {
+                       g_critical (_("Error reading configuration defaults: %s\n"), error->message);
+                       g_clear_error (&error);
+               }
        }
 
-       if (!g_key_file_load_from_file (config_userprefs, filename, G_KEY_FILE_NONE, &error))
+       /* Check if the user's config exists, and load it */
+       if (!g_file_test (userprefs_filename, G_FILE_TEST_EXISTS))
        {
-               g_warning (_("Error reading from config file: %s\n"), error->message);
-               g_error_free (error);
-               return FALSE;
+               g_warning (_("No user configuration file found, using defaults\n"));
+       }
+       else
+       {
+               if (!g_key_file_load_from_file (config_userprefs, userprefs_filename, G_KEY_FILE_NONE, &error))
+               {
+                       g_warning (_("Error reading user configuration: %s\n"), error->message);
+                       g_clear_error (&error);
+               }
        }
 
-       /* Everything went ok */
+       /* This is just here for the future. Currently, it is acceptable to run without
+        * a configuration, though Tilda may not work very well. */
        return TRUE;
 }
 
@@ -132,7 +464,9 @@ tilda_config_init (const gchar *filename)
 gboolean
 tilda_config_free ()
 {
-       g_hash_table_destroy (config_defaults);
+       /* Since we never write the config file from within Tilda,
+        * we can just close the files. */
+       g_key_file_free (config_defaults);
        g_key_file_free (config_userprefs);
 
        config_defaults = NULL;
index e18b870..ba12de6 100644 (file)
@@ -1,16 +1,21 @@
 #ifndef TILDA_CONFIG_H
 #define TILDA_CONFIG_H
 
+#include "tilda-terminal.h"
 #include <glib.h>
 
 /* Global configuration-holding structures */
-extern GHashTable *config_defaults;
-extern GKeyFile   *config_userprefs;
+extern GKeyFile *config_defaults;
+extern GKeyFile *config_userprefs;
 
 /* Set-up and tear-down functions */
 gboolean tilda_config_init (const gchar *filename);
 gboolean tilda_config_free ();
 
+/* API */
+gboolean tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *property);
+gboolean tilda_window_set_property_from_config (TildaWindow *self, const gchar *property);
+
 #endif /* TILDA_CONFIG_H */
 
 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */
index 16ac539..2904249 100644 (file)
@@ -8,30 +8,6 @@
 #define DINGUS1 "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?"
 #define DINGUS2 "(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.}>\\) ,\\\"]"
 
-typedef enum
-{
-       HOLD_OPEN,
-       RESTART_COMMAND,
-       EXIT,
-} TildaExitActions;
-
-typedef enum
-{
-       NOT_DISPLAYED,
-       AFTER_INITIAL,
-       BEFORE_INITIAL,
-       REPLACE_INITIAL,
-} TildaDynamicTitleActions;
-
-typedef enum
-{
-       /* NOT_DISPLAYED */
-       LEFT = 1,
-       RIGHT,
-} TildaScrollbarPositions;
-
-
-
 static void
 tilda_terminal_dbus_register_object (TildaTerminal *tt)
 {
@@ -165,16 +141,17 @@ tilda_terminal_child_exited_cb (GtkWidget *widget, gpointer data)
         * is closed. Take the appropriate action */
        switch (self->exit_action)
        {
-               case EXIT:
+               case TILDA_CHILD_EXIT_ACTION_EXIT:
                        tilda_window_remove_terminal (TILDA_WINDOW(self->parent_window), self->number);
                        break;
-               case RESTART_COMMAND:
+               case TILDA_CHILD_EXIT_ACTION_RESTART:
                        vte_terminal_feed (VTE_TERMINAL(self->vte_term), "\r\n\r\n", 4);
                        tilda_terminal_start_shell (self);
                        break;
-               case HOLD_OPEN:
+               case TILDA_CHILD_EXIT_ACTION_HOLD_OPEN:
                        break;
                default:
+                       g_warning ("Bad value in self->exit_action\n");
                        break;
        }
 }
@@ -193,41 +170,32 @@ tilda_terminal_window_title_changed_cb (GtkWidget *widget, gpointer data)
        TildaTerminal *self = TILDA_TERMINAL(data);
        TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
        GtkWidget *label;
-       const gchar *vte_title;
-       gchar *new_title;
-
-       label = gtk_notebook_get_tab_label (GTK_NOTEBOOK(parent_window->notebook), self->hbox);
+       const gchar *vte_title = NULL;
+       gchar *new_title = NULL;
 
-       /* If we aren't using a dynamic title -- NOT_DISPLAYED -- then just
-        * set it to the static title and exit */
-       if (!self->dynamic_title)
-       {
-               gtk_label_set_text (GTK_LABEL(label), self->title);
-               return;
-       }
-
-       /* Get the title from VTE */
        vte_title = vte_terminal_get_window_title (VTE_TERMINAL (widget));
+       label = gtk_notebook_get_tab_label (GTK_NOTEBOOK(parent_window->notebook), self->hbox);
 
-       /* Take the appropriate action */
        switch (self->dynamic_title)
        {
-               case REPLACE_INITIAL:
-                       new_title = g_strdup (vte_title);
+               case TILDA_DYNAMIC_TITLE_DISABLED:
+                       new_title = g_strdup (self->title);
+                       break;
+
+               case TILDA_DYNAMIC_TITLE_AFTER_INITIAL:
+                       new_title = g_strdup_printf ("%s - %s", self->title, vte_title);
                        break;
 
-               case BEFORE_INITIAL:
+               case TILDA_DYNAMIC_TITLE_BEFORE_INITIAL:
                        new_title = g_strdup_printf ("%s - %s", vte_title, self->title);
                        break;
 
-               case AFTER_INITIAL:
-                       new_title = g_strdup_printf ("%s - %s", self->title, vte_title);
+               case TILDA_DYNAMIC_TITLE_REPLACE_INITIAL:
+                       new_title = g_strdup (self->title);
                        break;
 
                default:
-                       debug_printf ("ERROR: Bad value of self->dynamic_title\n");
-               case NOT_DISPLAYED:
-                       new_title = g_strdup(self->title);
+                       g_warning ("Bad value in self->dynamic-title\n");
                        break;
        }
 
@@ -352,210 +320,26 @@ tilda_terminal_set_scrollbar_position (TildaTerminal *self)
 
        switch (self->scrollbar_position)
        {
-               case RIGHT:
+               case TILDA_SCROLLBAR_RIGHT:
                        gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 0);
                        gtk_widget_show (self->scrollbar);
                        break;
 
-               case LEFT:
+               case TILDA_SCROLLBAR_LEFT:
                        gtk_box_reorder_child (GTK_BOX(self->hbox), self->scrollbar, 1);
                        gtk_widget_show (self->scrollbar);
                        break;
 
-               default:
-                       debug_printf ("ERROR: Bad scrollbar position\n");
-               case NOT_DISPLAYED:
+               case TILDA_SCROLLBAR_DISABLED:
                        gtk_widget_hide (self->scrollbar);
                        break;
-       }
-}
-
-/*******************************************************************************
- * All configuration subsystem code is below
- ******************************************************************************/
 
-/**
- * Lookup a setting in the config file for this TildaTerminal.
- *
- * The returned string MUST be g_strdup()'d if you want to actually use
- * it as a value. It is owned by the config system. You MUST NOT g_free() it.
- */
-static gchar *
-tilda_terminal_lookup_from_config (TildaTerminal *self, const gchar key[])
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_TERMINAL(self));
-       debug_assert (key != NULL);
-
-       GError *error = NULL;
-       gchar *group_name;
-       gpointer value;
-
-       /* Do the bottom-most lookup */
-       group_name = g_strdup_printf ("Window%d/Terminal%d",
-                                                                 TILDA_WINDOW(self->parent_window)->number,
-                                                                 self->number);
-       value = g_key_file_get_string (config_userprefs, group_name, key, &error);
-       g_free (group_name);
-
-       if (!error)
-               return value;
-       else
-               g_clear_error (&error);
-
-       /* Do the next highest lookup */
-       group_name = g_strdup_printf ("Window%d",
-                                                                 TILDA_WINDOW(self->parent_window)->number);
-       value = g_key_file_get_string (config_userprefs, group_name, key, &error);
-       g_free (group_name);
-
-       if (!error)
-               return value;
-       else
-               g_clear_error (&error);
-
-       /* Do the global lookup */
-       value = g_key_file_get_string (config_userprefs, "Global", key, &error);
-
-       if (!error)
-               return value;
-       else
-               g_clear_error (&error);
-
-       /* Look in the defaults */
-       if (!g_hash_table_lookup_extended (config_defaults, key, NULL, &value))
-       {
-               /* If this happened, the developers forgot to set the default for
-                * a key they added. Please email them. */
-               g_critical ("Error: unable to find the default for key=%s\n", key);
-               exit (1);
-       }
-
-       /* Return the default key */
-       return value;
-}
-
-/**
- * Set one of TildaTerminal's integer properties from the config file or defaults.
- */
-static void
-tilda_terminal_config_int_property (TildaTerminal *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_TERMINAL(self));
-       debug_assert (property != NULL);
-
-       gint config_value;
-       gchar *config_value_raw;
-
-       config_value_raw = tilda_terminal_lookup_from_config (self, property);
-       config_value = atoi (config_value_raw);
-       g_object_set (G_OBJECT(self), property, config_value, NULL);
-}
-
-static void
-tilda_terminal_config_enum_property (TildaTerminal *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_TERMINAL(self));
-       debug_assert (property != NULL);
-
-       gint config_value;
-       gchar *config_value_raw;
-
-       /* Copy, then strip spaces off of the string from the config */
-       config_value_raw = g_strstrip (g_strdup (tilda_terminal_lookup_from_config (self, property)));
-
-begin_parsing:
-
-       /* Just try all of the possible enums */
-       if (g_ascii_strcasecmp (config_value_raw, "LEFT") == 0)
-               config_value = LEFT;
-       else if (g_ascii_strcasecmp (config_value_raw, "RIGHT") == 0)
-               config_value = RIGHT;
-       else if (g_ascii_strcasecmp (config_value_raw, "HOLD-OPEN") == 0)
-               config_value = HOLD_OPEN;
-       else if (g_ascii_strcasecmp (config_value_raw, "RESTART-COMMAND") == 0)
-               config_value = RESTART_COMMAND;
-       else if (g_ascii_strcasecmp (config_value_raw, "EXIT") == 0)
-               config_value = EXIT;
-       else if (g_ascii_strcasecmp (config_value_raw, "VTE-ERASE-AUTO") == 0)
-               config_value = VTE_ERASE_AUTO;
-       else if (g_ascii_strcasecmp (config_value_raw, "VTE-ERASE-ASCII-BACKSPACE") == 0)
-               config_value = VTE_ERASE_ASCII_BACKSPACE;
-       else if (g_ascii_strcasecmp (config_value_raw, "VTE-ERASE-ASCII-DELETE") == 0)
-               config_value = VTE_ERASE_ASCII_DELETE;
-       else if (g_ascii_strcasecmp (config_value_raw, "VTE-ERASE-DELETE-SEQUENCE") == 0)
-               config_value = VTE_ERASE_DELETE_SEQUENCE;
-       else if (g_ascii_strcasecmp (config_value_raw, "NOT-DISPLAYED") == 0)
-               config_value = NOT_DISPLAYED;
-       else if (g_ascii_strcasecmp (config_value_raw, "AFTER-INITIAL") == 0)
-               config_value = AFTER_INITIAL;
-       else if (g_ascii_strcasecmp (config_value_raw, "BEFORE-INITIAL") == 0)
-               config_value = BEFORE_INITIAL;
-       else if (g_ascii_strcasecmp (config_value_raw, "REPLACE-INITIAL") == 0)
-               config_value = REPLACE_INITIAL;
-       else
-       {
-               g_critical ("Unable to parse: '%s' as an enum\n", config_value_raw);
-
-               /* Use the default -- which I sure hope is valid (famous last words) */
-               config_value_raw = g_hash_table_lookup (config_defaults, property);
-               goto begin_parsing;
-       }
-
-       /* Free the value from the config system */
-       g_free (config_value_raw);
-
-       g_object_set (G_OBJECT(self), property, config_value, NULL);
-}
-
-static void
-tilda_terminal_config_string_property (TildaTerminal *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_TERMINAL(self));
-       debug_assert (property != NULL);
-
-       gchar *config_value_raw;
-
-       config_value_raw = tilda_terminal_lookup_from_config (self, property);
-
-       /* The property system g_strdup()s strings for us! */
-       g_object_set (G_OBJECT(self), property, config_value_raw, NULL);
-}
-
-static void
-tilda_terminal_config_boolean_property (TildaTerminal *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_TERMINAL(self));
-       debug_assert (property != NULL);
-
-       gboolean config_value;
-       gchar *config_value_raw;
-
-       config_value_raw = tilda_terminal_lookup_from_config (self, property);
-
-begin_parsing:
-
-       if (g_ascii_strcasecmp (config_value_raw, "true") == 0)
-               config_value = TRUE;
-       else if (g_ascii_strcasecmp (config_value_raw, "false") == 0)
-               config_value = FALSE;
-       else
-       {
-               g_critical ("Unable to parse: '%s' as a boolean\n", config_value_raw);
-
-               /* Use the default -- which I sure hope is valid (famous last words) */
-               config_value_raw = g_hash_table_lookup (config_defaults, property);
-               goto begin_parsing;
+               default:
+                       g_warning ("Bad value in self->scrollbar_position\n");
+                       break;
        }
-
-       g_object_set (G_OBJECT(self), property, config_value, NULL);
 }
 
-
 /*******************************************************************************
  * All GObject stuff is below. You probably don't need to change this...
  ******************************************************************************/
@@ -687,29 +471,29 @@ tilda_terminal_set_property (GObject      *object,
                        break;
 
                case TILDA_TERMINAL_BACKSPACE_BINDING:
-                       self->backspace_binding = g_value_get_int (value);
+                       self->backspace_binding = g_value_get_enum (value);
                        vte_terminal_set_backspace_binding (VTE_TERMINAL(self->vte_term), self->backspace_binding);
                        debug_printf ("terminal backspace key: %d\n", self->backspace_binding);
                        break;
 
                case TILDA_TERMINAL_DELETE_BINDING:
-                       self->delete_binding = g_value_get_int (value);
+                       self->delete_binding = g_value_get_enum (value);
                        vte_terminal_set_delete_binding (VTE_TERMINAL(self->vte_term), self->delete_binding);
                        debug_printf ("terminal delete key: %d\n", self->delete_binding);
                        break;
 
                case TILDA_TERMINAL_DYNAMIC_TITLE:
-                       self->dynamic_title = g_value_get_int (value);
+                       self->dynamic_title = g_value_get_enum (value);
                        debug_printf ("terminal dynamic title: %d\n", self->dynamic_title);
                        break;
 
                case TILDA_TERMINAL_EXIT_ACTION:
-                       self->exit_action = g_value_get_int (value);
+                       self->exit_action = g_value_get_enum (value);
                        debug_printf ("terminal exit action: %d\n", self->exit_action);
                        break;
 
                case TILDA_TERMINAL_SCROLLBAR_POSITION:
-                       self->scrollbar_position = g_value_get_int (value);
+                       self->scrollbar_position = g_value_get_enum (value);
                        tilda_terminal_set_scrollbar_position (self);
                        debug_printf ("terminal scrollbar position: %d\n", self->scrollbar_position);
                        break;
@@ -834,23 +618,23 @@ tilda_terminal_get_property (GObject    *object,
                        break;
 
                case TILDA_TERMINAL_BACKSPACE_BINDING:
-                       g_value_set_int (value, self->backspace_binding);
+                       g_value_set_enum (value, self->backspace_binding);
                        break;
 
                case TILDA_TERMINAL_DELETE_BINDING:
-                       g_value_set_int (value, self->delete_binding);
+                       g_value_set_enum (value, self->delete_binding);
                        break;
 
                case TILDA_TERMINAL_DYNAMIC_TITLE:
-                       g_value_set_int (value, self->dynamic_title);
+                       g_value_set_enum (value, self->dynamic_title);
                        break;
 
                case TILDA_TERMINAL_EXIT_ACTION:
-                       g_value_set_int (value, self->exit_action);
+                       g_value_set_enum (value, self->exit_action);
                        break;
 
                case TILDA_TERMINAL_SCROLLBAR_POSITION:
-                       g_value_set_int (value, self->scrollbar_position);
+                       g_value_set_enum (value, self->scrollbar_position);
                        break;
 
                case TILDA_TERMINAL_SCROLL_BACKGROUND:
@@ -945,32 +729,32 @@ tilda_terminal_constructor (GType                  type,
                                          G_CALLBACK(tilda_terminal_button_press_cb), self);
 
        /* Setup all of the defaults from the config file */
-       tilda_terminal_config_string_property (self, "background-image");
-       tilda_terminal_config_string_property (self, "shell");
-       tilda_terminal_config_string_property (self, "font");
-       tilda_terminal_config_string_property (self, "title");
-       tilda_terminal_config_string_property (self, "working-directory");
-       tilda_terminal_config_string_property (self, "web-browser");
-
-       tilda_terminal_config_int_property (self, "scrollback-lines");
-       tilda_terminal_config_int_property (self, "transparency-percent");
-
-       tilda_terminal_config_enum_property (self, "backspace-binding");
-       tilda_terminal_config_enum_property (self, "delete-binding");
-       tilda_terminal_config_enum_property (self, "dynamic-title");
-       tilda_terminal_config_enum_property (self, "exit-action");
-       tilda_terminal_config_enum_property (self, "scrollbar-position");
-
-       tilda_terminal_config_boolean_property (self, "scroll-background");
-       tilda_terminal_config_boolean_property (self, "scroll-on-output");
-       tilda_terminal_config_boolean_property (self, "scroll-on-keystroke");
-       tilda_terminal_config_boolean_property (self, "antialiased");
-       tilda_terminal_config_boolean_property (self, "allow-bold-text");
-       tilda_terminal_config_boolean_property (self, "cursor-blinks");
-       tilda_terminal_config_boolean_property (self, "audible-bell");
-       tilda_terminal_config_boolean_property (self, "visible-bell");
-       tilda_terminal_config_boolean_property (self, "double-buffered");
-       tilda_terminal_config_boolean_property (self, "mouse-autohide");
+       tilda_terminal_set_property_from_config (self, "background-image");
+       tilda_terminal_set_property_from_config (self, "shell");
+       tilda_terminal_set_property_from_config (self, "font");
+       tilda_terminal_set_property_from_config (self, "title");
+       tilda_terminal_set_property_from_config (self, "working-directory");
+       tilda_terminal_set_property_from_config (self, "web-browser");
+
+       tilda_terminal_set_property_from_config (self, "scrollback-lines");
+       tilda_terminal_set_property_from_config (self, "transparency-percent");
+
+       tilda_terminal_set_property_from_config (self, "backspace-binding");
+       tilda_terminal_set_property_from_config (self, "delete-binding");
+       tilda_terminal_set_property_from_config (self, "dynamic-title");
+       tilda_terminal_set_property_from_config (self, "exit-action");
+       tilda_terminal_set_property_from_config (self, "scrollbar-position");
+
+       tilda_terminal_set_property_from_config (self, "scroll-background");
+       tilda_terminal_set_property_from_config (self, "scroll-on-output");
+       tilda_terminal_set_property_from_config (self, "scroll-on-keystroke");
+       tilda_terminal_set_property_from_config (self, "antialiased");
+       tilda_terminal_set_property_from_config (self, "allow-bold-text");
+       tilda_terminal_set_property_from_config (self, "cursor-blinks");
+       tilda_terminal_set_property_from_config (self, "audible-bell");
+       tilda_terminal_set_property_from_config (self, "visible-bell");
+       tilda_terminal_set_property_from_config (self, "double-buffered");
+       tilda_terminal_set_property_from_config (self, "mouse-autohide");
 
        /* All right! We're all ready to go, so register with DBus, and lets start! */
        tilda_terminal_dbus_register_object (self);
@@ -1152,61 +936,56 @@ tilda_terminal_class_init (gpointer g_class,
                                                                         TILDA_TERMINAL_TRANSPARENCY_PERCENT,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("backspace-binding",
-                                                         _("Terminal's backspace binding"),
-                                                         NULL,
-                                                         VTE_ERASE_AUTO,
-                                                         VTE_ERASE_DELETE_SEQUENCE,
-                                                         VTE_ERASE_AUTO,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("backspace-binding",
+                                                          _("Terminal's backspace binding"),
+                                                          NULL,
+                                                          vte_terminal_erase_binding_get_type(),
+                                                          VTE_ERASE_AUTO,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_TERMINAL_BACKSPACE_BINDING,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("delete-binding",
-                                                         _("Terminal's delete binding"),
-                                                         NULL,
-                                                         VTE_ERASE_AUTO,
-                                                         VTE_ERASE_DELETE_SEQUENCE,
-                                                         VTE_ERASE_AUTO,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("delete-binding",
+                                                          _("Terminal's delete binding"),
+                                                          NULL,
+                                                          vte_terminal_erase_binding_get_type(),
+                                                          VTE_ERASE_AUTO,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_TERMINAL_DELETE_BINDING,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("dynamic-title",
-                                                         _("Terminal's dynamic title generation method"),
-                                                         NULL,
-                                                         0,
-                                                         INT_MAX,
-                                                         0,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("dynamic-title",
+                                                          _("Terminal's dynamic title generation method"),
+                                                          NULL,
+                                                          tilda_dynamic_title_get_type(),
+                                                          TILDA_DYNAMIC_TITLE_DISABLED,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_TERMINAL_DYNAMIC_TITLE,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("exit-action",
-                                                         _("Terminal's action upon child exit"),
-                                                         NULL,
-                                                         0,
-                                                         INT_MAX,
-                                                         0,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("exit-action",
+                                                          _("Terminal's action upon child exit"),
+                                                          NULL,
+                                                          tilda_child_exit_action_get_type(),
+                                                          TILDA_CHILD_EXIT_ACTION_EXIT,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_TERMINAL_EXIT_ACTION,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("scrollbar-position",
-                                                         _("Terminal's scrollbar position"),
-                                                         NULL,
-                                                         0,
-                                                         INT_MAX,
-                                                         0,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("scrollbar-position",
+                                                          _("Terminal's scrollbar position"),
+                                                          NULL,
+                                                          tilda_scrollbar_position_get_type(),
+                                                          TILDA_SCROLLBAR_RIGHT,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_TERMINAL_SCROLLBAR_POSITION,
index 5d59a50..1393cc4 100644 (file)
@@ -6,6 +6,7 @@
 #include <vte/vte.h>
 
 #include "tilda-window.h"
+#include "tilda-types.h"
 
 
 #define TILDA_TYPE_TERMINAL                            (tilda_terminal_get_type())
@@ -38,22 +39,17 @@ struct _TildaTerminal {
 
        gint scrollback_lines;
        gint transparency_percent;
-       // TODO: opacity, tint, etc
 
-       // TODO: these really are enums. Maybe the config system
-       // TODO: can be made to handle top, bottom, left, right.
-       // TODO: (similar to the true/false handling)
-       // TODO:
-       // TODO: or, maybe ints would just be better
-       // TODO: REMEMBER THOUGH: make the computer do what it's good at ;)
-       gint backspace_binding;
-       gint delete_binding;
-       gint dynamic_title;
-       gint exit_action;
-       gint scrollbar_position;
+       VteTerminalEraseBinding backspace_binding;
+       VteTerminalEraseBinding delete_binding;
+       TildaDynamicTitle dynamic_title;
+       TildaChildExitAction exit_action;
+       TildaScrollbarPosition scrollbar_position;
+
        // TODO: gint colorscheme; the code can work around the need for
        // TODO: this value. Just check if the back and fore colors match
        // TODO: any pre-defined colorschemes exactly in the GUI.
+       // TODO: opacity, tint, etc
        GdkColor background_color;
        GdkColor foreground_color;
        // TODO: all other colors supported by VTE
diff --git a/tilda-types.c b/tilda-types.c
new file mode 100644 (file)
index 0000000..162c13d
--- /dev/null
@@ -0,0 +1,52 @@
+#include "tilda-types.h"
+
+GType tilda_scrollbar_position_get_type (void)
+{
+       static GType type = 0;
+       static const GEnumValue values[] = {
+               {TILDA_SCROLLBAR_DISABLED, "TILDA_SCROLLBAR_DISABLED", "disabled"},
+               {TILDA_SCROLLBAR_LEFT, "TILDA_SCROLLBAR_LEFT", "left"},
+               {TILDA_SCROLLBAR_RIGHT, "TILDA_SCROLLBAR_RIGHT", "right"},
+               { 0, NULL, NULL },
+       };
+
+       if (G_UNLIKELY(type == 0))
+               type = g_enum_register_static("TildaScrollbarPosition", values);
+
+       return type;
+}
+
+GType tilda_child_exit_action_get_type (void)
+{
+       static GType type = 0;
+       static const GEnumValue values[] = {
+               {TILDA_CHILD_EXIT_ACTION_HOLD_OPEN, "TILDA_CHILD_EXIT_ACTION_HOLD_OPEN", "hold-open"},
+               {TILDA_CHILD_EXIT_ACTION_RESTART, "TILDA_CHILD_EXIT_ACTION_RESTART", "restart"},
+               {TILDA_CHILD_EXIT_ACTION_EXIT, "TILDA_CHILD_EXIT_ACTION_EXIT", "exit"},
+               { 0, NULL, NULL },
+       };
+
+       if (G_UNLIKELY(type == 0))
+               type = g_enum_register_static("TildaChildExitAction", values);
+
+       return type;
+}
+
+GType tilda_dynamic_title_get_type (void)
+{
+       static GType type = 0;
+       static const GEnumValue values[] = {
+               {TILDA_DYNAMIC_TITLE_DISABLED, "TILDA_DYNAMIC_TITLE_DISABLED", "disabled"},
+               {TILDA_DYNAMIC_TITLE_AFTER_INITIAL, "TILDA_DYNAMIC_TITLE_AFTER_INITIAL", "after-initial"},
+               {TILDA_DYNAMIC_TITLE_BEFORE_INITIAL, "TILDA_DYNAMIC_TITLE_BEFORE_INITIAL", "before-initial"},
+               {TILDA_DYNAMIC_TITLE_REPLACE_INITIAL, "TILDA_DYNAMIC_TITLE_REPLACE_INITIAL", "replace-initial"},
+               { 0, NULL, NULL },
+       };
+
+       if (G_UNLIKELY(type == 0))
+               type = g_enum_register_static ("TildaDynamicTitle", values);
+
+       return type;
+}
+
+/* vim: set ts=4 sts=4 sw=4 noet tw=112: */
diff --git a/tilda-types.h b/tilda-types.h
new file mode 100644 (file)
index 0000000..6319832
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef TILDATYPES_H
+#define TILDATYPES_H
+
+#include <glib-object.h>
+
+/* Enum-derived type for scrollbar-position */
+typedef enum
+{
+       TILDA_SCROLLBAR_DISABLED,
+       TILDA_SCROLLBAR_LEFT,
+       TILDA_SCROLLBAR_RIGHT,
+} TildaScrollbarPosition;
+
+GType tilda_scrollbar_position_get_type (void);
+
+/* Enum-derived type for exit-action */
+typedef enum
+{
+       TILDA_CHILD_EXIT_ACTION_HOLD_OPEN,
+       TILDA_CHILD_EXIT_ACTION_RESTART,
+       TILDA_CHILD_EXIT_ACTION_EXIT,
+} TildaChildExitAction;
+
+GType tilda_child_exit_action_get_type (void);
+
+/* Enum-derived type for dynamic-title */
+typedef enum
+{
+       TILDA_DYNAMIC_TITLE_DISABLED,
+       TILDA_DYNAMIC_TITLE_AFTER_INITIAL,
+       TILDA_DYNAMIC_TITLE_BEFORE_INITIAL,
+       TILDA_DYNAMIC_TITLE_REPLACE_INITIAL,
+} TildaDynamicTitle;
+
+GType tilda_dynamic_title_get_type (void);
+
+/* Use GtkPositionType for animation-orientation */
+
+#endif /* TILDATYPES_H */
+
+/* vim: set ts=4 sts=4 sw=4 noet tw=112: */
index 8e8ff6a..822a987 100644 (file)
@@ -350,162 +350,6 @@ tilda_window_dbus_register_object (TildaWindow *self)
        g_free (object_path);
 }
 
-/*******************************************************************************
- * All configuration subsystem code is below
- ******************************************************************************/
-
-/**
- * Lookup a setting in the config file for this TildaWindow.
- *
- * The returned string MUST be g_strdup()'d if you want to actually use
- * it as a value. It is owned by the config system. You MUST NOT g_free() it.
- */
-static gchar *
-tilda_window_lookup_from_config (TildaWindow *self, const gchar key[])
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_WINDOW(self));
-       debug_assert (key != NULL);
-
-       GError *error = NULL;
-       gchar *group_name;
-       gpointer value;
-
-       /* Do the bottom-most lookup */
-       group_name = g_strdup_printf ("Window%d", self->number);
-       value = g_key_file_get_string (config_userprefs, group_name, key, &error);
-       g_free (group_name);
-
-       if (!error)
-               return value;
-       else
-               g_clear_error (&error);
-
-       /* Do the global lookup */
-       value = g_key_file_get_string (config_userprefs, "Global", key, &error);
-
-       if (!error)
-               return value;
-       else
-               g_clear_error (&error);
-
-       /* Look in the defaults */
-       if (!g_hash_table_lookup_extended (config_defaults, key, NULL, &value))
-       {
-               /* If this happened, the developers forgot to set the default for
-                * a key they added. Please email them. */
-               g_critical ("Error: unable to find the default for key=%s\n", key);
-               exit (1);
-       }
-
-       /* Return the default key */
-       return value;
-}
-
-/**
- * Set one of TildaWindow's integer properties from the config file or defaults.
- */
-static void
-tilda_window_config_int_property (TildaWindow *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_WINDOW(self));
-       debug_assert (property != NULL);
-
-       gint config_value;
-       gchar *config_value_raw;
-
-       config_value_raw = tilda_window_lookup_from_config (self, property);
-       config_value = atoi (config_value_raw);
-       g_object_set (G_OBJECT(self), property, config_value, NULL);
-}
-
-static void
-tilda_window_config_enum_property (TildaWindow *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_WINDOW(self));
-       debug_assert (property != NULL);
-
-       gint config_value;
-       gchar *config_value_raw;
-
-       /* Copy, then strip spaces off of the string from the config */
-       config_value_raw = g_strstrip (g_strdup (tilda_window_lookup_from_config (self, property)));
-
-begin_parsing:
-
-       /* Just try all of the possible enums */
-       if (g_ascii_strcasecmp (config_value_raw, "LEFT") == 0)
-               config_value = GTK_POS_LEFT;
-       else if (g_ascii_strcasecmp (config_value_raw, "RIGHT") == 0)
-               config_value = GTK_POS_RIGHT;
-       else if (g_ascii_strcasecmp (config_value_raw, "TOP") == 0)
-               config_value = GTK_POS_TOP;
-       else if (g_ascii_strcasecmp (config_value_raw, "BOTTOM") == 0)
-               config_value = GTK_POS_BOTTOM;
-       else
-       {
-               g_critical ("Unable to parse: '%s' as an enum\n", config_value_raw);
-
-               /* Use the default -- which I sure hope is valid (famous last words) */
-               config_value_raw = g_hash_table_lookup (config_defaults, property);
-               goto begin_parsing;
-       }
-
-       /* Free the value from the config system */
-       g_free (config_value_raw);
-
-       g_object_set (G_OBJECT(self), property, config_value, NULL);
-}
-
-static void
-tilda_window_config_string_property (TildaWindow *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_WINDOW(self));
-       debug_assert (property != NULL);
-
-       gchar *config_value_raw;
-
-       config_value_raw = tilda_window_lookup_from_config (self, property);
-
-       /* The property system g_strdup()s strings for us! */
-       g_object_set (G_OBJECT(self), property, config_value_raw, NULL);
-}
-
-static void
-tilda_window_config_boolean_property (TildaWindow *self, const gchar *property)
-{
-       debug_enter  ();
-       debug_assert (TILDA_IS_WINDOW(self));
-       debug_assert (property != NULL);
-
-       gboolean config_value;
-       gchar *config_value_raw;
-
-       config_value_raw = tilda_window_lookup_from_config (self, property);
-
-begin_parsing:
-
-       if (g_ascii_strcasecmp (config_value_raw, "true") == 0)
-               config_value = TRUE;
-       else if (g_ascii_strcasecmp (config_value_raw, "false") == 0)
-               config_value = FALSE;
-       else
-       {
-               g_critical ("Unable to parse: '%s' as a boolean\n", config_value_raw);
-
-               /* Use the default -- which I sure hope is valid (famous last words) */
-               config_value_raw = g_hash_table_lookup (config_defaults, property);
-               goto begin_parsing;
-       }
-
-       g_object_set (G_OBJECT(self), property, config_value, NULL);
-}
-
-
-
 /*******************************************************************************
  * ALL GOBJECT STUFF BELOW PLEASE
  ******************************************************************************/
@@ -616,13 +460,13 @@ tilda_window_set_property (GObject      *object,
                        break;
 
                case TILDA_WINDOW_TAB_POSITION:
-                       self->tab_position = g_value_get_int (value);
+                       self->tab_position = g_value_get_enum (value);
                        gtk_notebook_set_tab_pos (GTK_NOTEBOOK(self->notebook), self->tab_position);
                        debug_printf ("window tab position: %d\n", self->tab_position);
                        break;
 
                case TILDA_WINDOW_ANIMATION_ORIENTATION:
-                       self->animation_orientation = g_value_get_int (value);
+                       self->animation_orientation = g_value_get_enum (value);
                        debug_printf ("window animation orientation: %d\n", self->animation_orientation);
                        break;
 
@@ -726,11 +570,11 @@ tilda_window_get_property (GObject    *object,
                        break;
 
                case TILDA_WINDOW_TAB_POSITION:
-                       g_value_set_int (value, self->tab_position);
+                       g_value_set_enum (value, self->tab_position);
                        break;
 
                case TILDA_WINDOW_ANIMATION_ORIENTATION:
-                       g_value_set_int (value, self->animation_orientation);
+                       g_value_set_enum (value, self->animation_orientation);
                        break;
 
                case TILDA_WINDOW_ANIMATION_DELAY:
@@ -806,7 +650,7 @@ tilda_window_constructor (GType                  type,
        gtk_window_set_decorated (GTK_WINDOW(self->window), FALSE);
 
        /* Set all of the properties out of the config file */
-       tilda_window_config_string_property (self, "key");
+       tilda_window_set_property_from_config (self, "key");
 
        // FIXME: hack -- start the wizard in this case :)
        if (!self->key)
@@ -818,22 +662,22 @@ tilda_window_constructor (GType                  type,
                g_critical ("HACK: start the wizard here\n");
        }
 
-       tilda_window_config_int_property (self, "height");
-       tilda_window_config_int_property (self, "width");
-       tilda_window_config_int_property (self, "x-position");
-       tilda_window_config_int_property (self, "y-position");
-       tilda_window_config_int_property (self, "initial-terminals");
-       tilda_window_config_int_property (self, "animation-delay");
+       tilda_window_set_property_from_config (self, "height");
+       tilda_window_set_property_from_config (self, "width");
+       tilda_window_set_property_from_config (self, "x-position");
+       tilda_window_set_property_from_config (self, "y-position");
+       tilda_window_set_property_from_config (self, "initial-terminals");
+       tilda_window_set_property_from_config (self, "animation-delay");
 
-       tilda_window_config_enum_property (self, "tab-position");
-       tilda_window_config_enum_property (self, "animation-orientation");
+       tilda_window_set_property_from_config (self, "tab-position");
+       tilda_window_set_property_from_config (self, "animation-orientation");
 
-       tilda_window_config_boolean_property (self, "keep-above");
-       tilda_window_config_boolean_property (self, "skip-taskbar-hint");
-       tilda_window_config_boolean_property (self, "stick");
-       tilda_window_config_boolean_property (self, "hidden-at-start");
-       tilda_window_config_boolean_property (self, "centered-horizontally");
-       tilda_window_config_boolean_property (self, "centered-vertically");
+       tilda_window_set_property_from_config (self, "keep-above");
+       tilda_window_set_property_from_config (self, "skip-taskbar-hint");
+       tilda_window_set_property_from_config (self, "stick");
+       tilda_window_set_property_from_config (self, "hidden-at-start");
+       tilda_window_set_property_from_config (self, "centered-horizontally");
+       tilda_window_set_property_from_config (self, "centered-vertically");
 
        /* Add the initial terminal(s) */
        for (i=0; i<self->initial_terminals; ++i)
@@ -1016,25 +860,23 @@ tilda_window_class_init (gpointer g_class,
                                                                         TILDA_WINDOW_INITIAL_TERMINALS,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("tab-position",
-                                                         _("Position of window's tab bar"),
-                                                         NULL,
-                                                         0,
-                                                         INT_MAX,
-                                                         0,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("tab-position",
+                                                          _("Position of window's tab bar"),
+                                                          NULL,
+                                                          gtk_position_type_get_type(),
+                                                          GTK_POS_TOP,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_WINDOW_TAB_POSITION,
                                                                         pspec);
 
-       pspec = g_param_spec_int ("animation-orientation",
-                                                         _("Window's animation orientation"),
-                                                         NULL,
-                                                         0,
-                                                         INT_MAX,
-                                                         0,
-                                                         G_PARAM_READWRITE);
+       pspec = g_param_spec_enum ("animation-orientation",
+                                                          _("Window's animation orientation"),
+                                                          NULL,
+                                                          gtk_position_type_get_type(),
+                                                          GTK_POS_TOP,
+                                                          G_PARAM_READWRITE);
 
        g_object_class_install_property (gobject_class,
                                                                         TILDA_WINDOW_ANIMATION_ORIENTATION,
index d036c89..54bc2af 100644 (file)
@@ -51,12 +51,11 @@ struct _TildaWindow {
        gint width;
        gint x_position;
        gint y_position;
+       gint animation_delay;
        gint initial_terminals;
 
-       // FIXME: these really should be enum's if possible
-       gint tab_position;
-       gint animation_orientation;
-       gint animation_delay;
+       GtkPositionType tab_position;
+       GtkPositionType animation_orientation;
 
        gboolean keep_above;
        gboolean skip_taskbar_hint;