goffice r2083 - in trunk: . goffice/app goffice/component



Author: jbrefort
Date: Mon May 12 07:45:33 2008
New Revision: 2083
URL: http://svn.gnome.org/viewvc/goffice?rev=2083&view=rev

Log:
2008-05-12  Jean Brefort  <jean brefort normalesup org>

	* goffice/app/Makefile.am:
	* goffice/app/go-conf-gconf.c: copied from gnumeric.
	* goffice/app/go-conf-keyfile.c: ditto.
	* goffice/app/go-conf-win32.c: ditto.
	* goffice/app/go-conf.c: ditto.
	* goffice/app/go-conf.h: ditto.
	* goffice/component/go-component.h: add missing header.



Added:
   trunk/goffice/app/go-conf-gconf.c
   trunk/goffice/app/go-conf-keyfile.c
   trunk/goffice/app/go-conf-win32.c
   trunk/goffice/app/go-conf.c
   trunk/goffice/app/go-conf.h
Modified:
   trunk/ChangeLog
   trunk/goffice/app/Makefile.am
   trunk/goffice/component/go-component.h

Modified: trunk/goffice/app/Makefile.am
==============================================================================
--- trunk/goffice/app/Makefile.am	(original)
+++ trunk/goffice/app/Makefile.am	Mon May 12 07:45:33 2008
@@ -16,7 +16,8 @@
 	file.c				\
 	error-info.c			\
 	io-context.c			\
-	go-cmd-context.c
+	go-cmd-context.c		\
+	go-conf.c
 
 libgoffice_app_ladir = $(goffice_include_dir)/app
 libgoffice_app_la_api_headers = 	\
@@ -36,7 +37,9 @@
 	io-context.h			\
 	io-context-priv.h		\
 	go-cmd-context.h		\
-	go-cmd-context-impl.h
+	go-cmd-context-impl.h	\
+	go-conf.h
+
 libgoffice_app_la_HEADERS = 	\
 	$(libgoffice_app_la_api_headers) \
 	module-plugin-defs.h
@@ -51,7 +54,10 @@
 	go-service.h \
 	go-service-impl.h
 
-EXTRA_DIST = $(UNUSED)
+EXTRA_DIST = $(UNUSED)		\
+	go-conf-gconf.c			\
+	go-conf-keyfile.c		\
+	go-conf-win32.c
 
 include $(top_srcdir)/goffice.mk
 

Added: trunk/goffice/app/go-conf-gconf.c
==============================================================================
--- (empty file)
+++ trunk/goffice/app/go-conf-gconf.c	Mon May 12 07:45:33 2008
@@ -0,0 +1,464 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <gconf/gconf-client.h>
+
+struct _GOConfNode {
+	gchar *path;
+	gboolean root;
+};
+
+static GConfClient *gconf_client = NULL;
+
+void
+go_conf_init ()
+{
+	if (!gconf_client)
+		gconf_client = gconf_client_get_default ();
+}
+
+void
+go_conf_shutdown (void)
+{
+	if (gconf_client) {
+		g_object_unref (G_OBJECT (gconf_client));
+		gconf_client = NULL;
+	}
+}
+
+static gchar *
+go_conf_get_real_key (GOConfNode const *key, gchar const *subkey)
+{
+	return key ? (subkey ? g_strconcat ((key)->path, "/", subkey, NULL): g_strdup (key->path)) :
+		     g_strdup (subkey);
+}
+
+GOConfNode *
+go_conf_get_node (GOConfNode *parent, gchar const *key)
+{
+	GOConfNode *node;
+
+	node = g_new (GOConfNode, 1);
+	gconf_client = gconf_client;
+	node->root = !parent;
+	if (node->root) {
+		node->path = g_strconcat ("/apps/", key, NULL);
+		gconf_client_add_dir (gconf_client, node->path,
+				      GCONF_CLIENT_PRELOAD_RECURSIVE,
+				      NULL);
+	}
+	else
+		node->path = go_conf_get_real_key (parent, key);
+
+	return node;
+}
+
+void
+go_conf_free_node (GOConfNode *node)
+{
+	if (node) {
+		if (node->root)
+			gconf_client_remove_dir (gconf_client, node->path, NULL);
+		g_free (node->path);
+		g_free (node);
+	}
+}
+
+void
+go_conf_sync (GOConfNode *node)
+{
+	gconf_client_suggest_sync (gconf_client, NULL);
+}
+
+void
+go_conf_set_bool (GOConfNode *node, gchar const *key, gboolean val)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gconf_client_set_bool (gconf_client, real_key, val, NULL);
+	g_free (real_key);
+}
+
+void
+go_conf_set_int (GOConfNode *node, gchar const *key, gint val)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gconf_client_set_int (gconf_client, real_key, val, NULL);
+	g_free (real_key);
+}
+
+void
+go_conf_set_double (GOConfNode *node, gchar const *key, gdouble val)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gconf_client_set_float (gconf_client, real_key, val, NULL);
+	g_free (real_key);
+}
+
+void
+go_conf_set_string (GOConfNode *node, gchar const *key, gchar const *str)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gconf_client_set_string (gconf_client, real_key, str, NULL);
+	g_free (real_key);
+}
+
+void
+go_conf_set_str_list (GOConfNode *node, gchar const *key, GSList *list)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gconf_client_set_list (gconf_client, real_key,
+		GCONF_VALUE_STRING, list, NULL);
+	g_free (real_key);
+}
+
+static GConfValue *
+go_conf_get (GOConfNode *node, gchar const *key, GConfValueType t)
+{
+	GError *err = NULL;
+	GConfValue *val;
+	gchar *real_key;
+
+	real_key = go_conf_get_real_key (node, key);
+	val = gconf_client_get (gconf_client, real_key, &err);
+
+	if (err != NULL) {
+		d (g_warning ("Unable to load key '%s' : because %s",
+			      real_key, err->message));
+		g_free (real_key);
+		g_error_free (err);
+		return NULL;
+	}
+	if (val == NULL) {
+		d (g_warning ("Unable to load key '%s'", real_key));
+		g_free (real_key);
+		return NULL;
+	}
+
+	if (val->type != t) {
+#if 1 /* gconf_value_type_to_string is internal */
+		g_warning ("Expected `%d' got `%d' for key %s",
+			   t, val->type, real_key);
+#else
+		g_warning ("Expected `%s' got `%s' for key %s",
+			   gconf_value_type_to_string (t),
+			   gconf_value_type_to_string (val->type),
+			   real_key);
+#endif
+		g_free (real_key);
+		gconf_value_free (val);
+		return NULL;
+	}
+	g_free (real_key);
+
+	return val;
+}
+
+gboolean
+go_conf_load_bool (GOConfNode *node, gchar const *key, gboolean default_val)
+{
+	gboolean res;
+	GConfValue *val = go_conf_get (node, key, GCONF_VALUE_BOOL);
+
+	if (val != NULL) {
+		res = gconf_value_get_bool (val);
+		gconf_value_free (val);
+	} else {
+		d (g_warning ("Using default value '%s'", default_val ? "true" : "false"));
+		return default_val;
+	}
+	return res;
+}
+
+gint
+go_conf_load_int (GOConfNode *node, gchar const *key, gint minima, gint maxima, gint default_val)
+{
+	gint res = -1;
+	GConfValue *val = go_conf_get (node, key, GCONF_VALUE_INT);
+
+	if (val != NULL) {
+		res = gconf_value_get_int (val);
+		gconf_value_free (val);
+		if (res < minima || maxima < res) {
+			g_warning ("Invalid value '%d' for %s.  If should be >= %d and <= %d",
+				   res, key, minima, maxima);
+			val = NULL;
+		}
+	}
+	if (val == NULL) {
+		d (g_warning ("Using default value '%d'", default_val));
+		return default_val;
+	}
+	return res;
+}
+
+gdouble
+go_conf_load_double (GOConfNode *node, gchar const *key,
+		     gdouble minima, gdouble maxima, gdouble default_val)
+{
+	gdouble res = -1;
+	GConfValue *val = go_conf_get (node, key, GCONF_VALUE_FLOAT);
+
+	if (val != NULL) {
+		res = gconf_value_get_float (val);
+		gconf_value_free (val);
+		if (res < minima || maxima < res) {
+			g_warning ("Invalid value '%g' for %s.  If should be >= %g and <= %g",
+				   res, key, minima, maxima);
+			val = NULL;
+		}
+	}
+	if (val == NULL) {
+		d (g_warning ("Using default value '%g'", default_val));
+		return default_val;
+	}
+	return res;
+}
+
+gchar *
+go_conf_load_string (GOConfNode *node, gchar const *key)
+{
+	gchar *val;
+
+	gchar *real_key = go_conf_get_real_key (node, key);
+	val = gconf_client_get_string (gconf_client, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+GSList *
+go_conf_load_str_list (GOConfNode *node, gchar const *key)
+{
+	GSList *list;
+
+	gchar *real_key = go_conf_get_real_key (node, key);
+	list = gconf_client_get_list (gconf_client, real_key,
+				      GCONF_VALUE_STRING, NULL);
+	g_free (real_key);
+
+	return list;
+}
+
+static GConfSchema *
+get_schema (GOConfNode *node, gchar const *key)
+{
+	gchar *schema_key = g_strconcat (
+		"/schemas", node->path, "/", key, NULL);
+	GConfSchema *schema = gconf_client_get_schema (
+		gconf_client, schema_key, NULL);
+	g_free (schema_key);
+	return schema;
+}
+
+gchar *
+go_conf_get_short_desc (GOConfNode *node, gchar const *key)
+{
+	GConfSchema *schema = get_schema (node, key);
+
+	if (schema != NULL) {
+		gchar *desc = g_strdup (gconf_schema_get_short_desc (schema));
+		gconf_schema_free (schema);
+		return desc;
+	}
+	return NULL;
+}
+
+gchar *
+go_conf_get_long_desc  (GOConfNode *node, gchar const *key)
+{
+	GConfSchema *schema = get_schema (node, key);
+
+	if (schema != NULL) {
+		gchar *desc =  g_strdup (gconf_schema_get_long_desc (schema));
+		gconf_schema_free (schema);
+		return desc;
+	}
+	return NULL;
+}
+
+GType
+go_conf_get_type (GOConfNode *node, gchar const *key)
+{
+	GConfSchema *schema = get_schema (node, key);
+	GType t;
+
+	switch (gconf_schema_get_type (schema)) {
+	case GCONF_VALUE_STRING: t = G_TYPE_STRING; break;
+	case GCONF_VALUE_FLOAT: t = G_TYPE_FLOAT; break;
+	case GCONF_VALUE_INT: t = G_TYPE_INT; break;
+	case GCONF_VALUE_BOOL: t = G_TYPE_BOOLEAN; break;
+	default :
+		t = G_TYPE_NONE;
+	}
+
+	if (schema != NULL)
+		gconf_schema_free (schema);
+	return t;
+}
+
+gchar *
+go_conf_get_value_as_str (GOConfNode *node, gchar const *key)
+{
+	gchar *value_string;
+
+	switch (go_conf_get_type (node, key)) {
+	case G_TYPE_STRING:
+		value_string = go_conf_get_string (node, key);
+		break;
+	case G_TYPE_INT:
+		value_string = g_strdup_printf ("%i", go_conf_get_int (node, key));
+		break;
+	case G_TYPE_FLOAT:
+		value_string = g_strdup_printf ("%f", go_conf_get_double (node, key));
+		break;
+	case G_TYPE_BOOLEAN:
+		value_string = g_strdup (go_locale_boolean_name (go_conf_get_bool (node, key)));
+		break;
+	default:
+		value_string = g_strdup ("ERROR FIXME");
+	}
+
+	return value_string;
+}
+
+gboolean
+go_conf_get_bool (GOConfNode *node, gchar const *key)
+{
+	gboolean val;
+	gchar *real_key;
+
+	real_key = go_conf_get_real_key (node, key);
+	val = gconf_client_get_bool (gconf_client, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+gint
+go_conf_get_int	(GOConfNode *node, gchar const *key)
+{
+	gint val;
+	gchar *real_key;
+
+	real_key = go_conf_get_real_key (node, key);
+	val = gconf_client_get_int (gconf_client, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+gdouble
+go_conf_get_double (GOConfNode *node, gchar const *key)
+{
+	gdouble val;
+	gchar *real_key;
+
+	real_key = go_conf_get_real_key (node, key);
+	val = gconf_client_get_float (gconf_client, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+gchar *
+go_conf_get_string (GOConfNode *node, gchar const *key)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gchar *res = gconf_client_get_string (gconf_client, real_key, NULL);
+	g_free (real_key);
+	return res;
+}
+
+
+GSList *
+go_conf_get_str_list (GOConfNode *node, gchar const *key)
+{
+	return go_conf_load_str_list (node, key);
+}
+
+#if 0
+gboolean
+go_conf_set_value_from_str (GOConfNode *node, gchar const *key, gchar const *val_str)
+{
+	switch (go_conf_get_type (node, key)) {
+	case G_TYPE_STRING:
+		go_conf_set_string (node, key, val_str);
+		break;
+	case G_TYPE_FLOAT: {
+		GODateConventions const *conv = NULL;  /* workbook_date_conv (state->wb); */
+		GnmValue *value = format_match_number (val_str, NULL, conv);
+		if (value != NULL) {
+			gnm_float the_float = value_get_as_float (value);
+			go_conf_set_double (node, key, the_float);
+		}
+		if (value)
+			value_release (value);
+		break;
+	}
+	case G_TYPE_INT: {
+		GODateConventions const *conv = NULL;  /* workbook_date_conv (state->wb); */
+		GnmValue *value = format_match_number (val_str, NULL, conv);
+		if (value != NULL) {
+			gint the_int = value_get_as_int (value);
+			go_conf_set_int (node, key, the_int);
+		}
+		if (value)
+			value_release (value);
+		break;
+	}
+	case G_TYPE_BOOLEAN: {
+		GODateConventions const *conv = NULL;  /* workbook_date_conv (state->wb); */
+		GnmValue *value = format_match_number (val_str, NULL, conv);
+		gboolean err, the_bool;
+		if (value != NULL) {
+			err = FALSE;
+			the_bool =  value_get_as_bool (value, &err);
+			go_conf_set_bool (node, key, the_bool);
+		}
+		if (value)
+			value_release (value);
+		break;
+	}
+	default:
+		g_warning ("Unsupported gconf type in preference dialog");
+	}
+
+	return TRUE;
+}
+#endif
+
+void
+go_conf_remove_monitor (guint monitor_id)
+{
+	gconf_client_notify_remove (gconf_client,
+		GPOINTER_TO_INT (monitor_id));
+}
+
+typedef struct {
+	GOConfMonitorFunc monitor;
+	gpointer data;
+} GOConfClosure;
+
+static void
+cb_key_changed (GConfClient *client, guint cnxn_id,
+		GConfEntry *entry, GOConfClosure *close)
+{
+	close->monitor (NULL, gconf_entry_get_key (entry), close->data);
+}
+
+guint
+go_conf_add_monitor (GOConfNode *node, gchar const *key,
+		     GOConfMonitorFunc monitor, gpointer data)
+{
+	guint ret;
+	GOConfClosure *close = g_new0 (GOConfClosure, 1);
+	gchar *real_key;
+
+	close->monitor = monitor;
+	close->data = data;
+	real_key = go_conf_get_real_key (node, key);
+	ret = gconf_client_notify_add (gconf_client, real_key,
+		(GConfClientNotifyFunc) cb_key_changed, close, g_free, NULL);
+	g_free (real_key);
+
+	return ret;
+}

Added: trunk/goffice/app/go-conf-keyfile.c
==============================================================================
--- (empty file)
+++ trunk/goffice/app/go-conf-keyfile.c	Mon May 12 07:45:33 2008
@@ -0,0 +1,500 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <glib/gstdio.h>
+#include <errno.h>
+#include <string.h>
+
+#define BOOL_GROUP    "Booleans"
+#define INT_GROUP     "Ints"
+#define DOUBLE_GROUP  "Doubles"
+#define STRING_GROUP  "Strings"
+#define STRLIST_GROUP "StringLists"
+
+struct _GOConfNode {
+	gchar *path;
+	GKeyFile *key_file;
+};
+
+static GHashTable *key_files = NULL;
+
+static gchar *get_rc_filename (char const *root_name)
+{
+	const gchar *home = g_get_home_dir ();
+	gchar *fname = NULL;
+	gchar *rcname = g_strconcat (".", root_name, "rc", NULL);
+
+	if (home != NULL)
+		fname = g_build_filename (home, rcname, NULL);
+
+	g_free (rcname);
+	return fname;
+}
+
+static void dump_key_data_to_file_cb (char const *rcfile, GKeyFile *key_file)
+{
+	FILE *fp = NULL;
+	gchar *key_data;
+
+	fp = g_fopen (rcfile, "w");
+	if (fp == NULL) {
+		g_warning ("Couldn't write configuration info to %s", rcfile);
+		return;
+	}
+
+	key_data = g_key_file_to_data (key_file, NULL, NULL);
+
+	if (key_data != NULL) {
+		fputs (key_data, fp);
+		g_free (key_data);
+	}
+
+	fclose (fp);
+}
+
+static gchar *
+go_conf_get_real_key (GOConfNode const *key, gchar const *subkey)
+{
+	return key ? g_strconcat ((key)->path, "/", subkey, NULL) :
+		     g_strdup (subkey);
+}
+
+void
+go_conf_init ()
+{
+	key_files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_key_file_free);
+}
+
+void
+go_conf_shutdown (void)
+{
+	if (!key_files)
+		return;
+	g_hash_table_foreach (key_files, (GHFunc) dump_key_data_to_file_cb, NULL);
+	g_hash_table_destroy (key_files);
+	key_files = NULL;
+}
+
+GOConfNode *
+go_conf_get_node (GOConfNode *parent, gchar const *key)
+{
+	GOConfNode *node;
+
+	node = g_new (GOConfNode, 1);
+	node->path = go_conf_get_real_key (parent, key);
+	if (parent)
+		node->key_file = parent->key_file;
+	else {
+		char *end = strchr (key, '/'), *name, *rcfile;
+		name = (end)? g_strndup (key, end - key): g_strdup (key);
+		rcfile = get_rc_filename (name);
+		g_free (name);
+		if (rcfile != NULL) {
+			GKeyFile *key_file = g_hash_table_lookup (key_files, rcfile);
+			if (key_file == NULL) {
+				key_file = g_key_file_new ();
+				g_key_file_load_from_file (key_file, rcfile, G_KEY_FILE_NONE, NULL);
+				g_hash_table_insert (key_files, rcfile, key_file);
+			} else
+				g_free (rcfile);
+			node->key_file = key_file;
+		}
+	}
+	return node;
+}
+
+void
+go_conf_free_node (GOConfNode *node)
+{
+	if (node != NULL) {
+		g_free (node->path);
+		g_free (node);
+	}
+}
+
+void
+go_conf_set_bool (GOConfNode *node, gchar const *key, gboolean val)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+
+	if (node == NULL)
+		return;
+
+	g_key_file_set_boolean (node->key_file, BOOL_GROUP, real_key, val);
+	g_free (real_key);
+}
+
+void
+go_conf_set_int (GOConfNode *node, gchar const *key, gint val)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+
+	if (node == NULL)
+		return;
+
+	g_key_file_set_integer (node->key_file, INT_GROUP, real_key, val);
+	g_free (real_key);
+}
+
+void
+go_conf_set_double (GOConfNode *node, gchar const *key, gdouble val)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+	gchar str[G_ASCII_DTOSTR_BUF_SIZE];
+
+	if (node == NULL)
+		return;
+
+	g_ascii_dtostr (str, sizeof (str), val);
+	g_key_file_set_value (node->key_file, DOUBLE_GROUP, real_key, str);
+	g_free (real_key);
+}
+
+void
+go_conf_set_string (GOConfNode *node, gchar const *key, char const *str)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+
+	if (node == NULL)
+		return;
+
+	g_key_file_set_string (node->key_file, STRING_GROUP, real_key, str);
+	g_free (real_key);
+}
+
+void
+go_conf_set_str_list (GOConfNode *node, gchar const *key, GSList *list)
+{
+	gchar *real_key;
+	gchar **strs = NULL;
+	int i, ns;
+
+	if (node == NULL || list == NULL)
+		return;
+
+	real_key = go_conf_get_real_key (node, key);
+	ns = g_slist_length (list);
+	strs = g_new (gchar *, ns);
+
+	for (i = 0; i < ns; i++) {
+		const gchar *lstr = list->data;
+		strs[i] = g_strdup (lstr);
+		list = list->next;
+	}
+
+	g_key_file_set_string_list (node->key_file, STRLIST_GROUP, real_key,
+				    (gchar const **const) strs, ns);
+	g_free (real_key);
+
+	for (i = 0; i < ns; i++)
+		g_free (strs[i]);
+	g_free (strs);
+}
+
+gboolean
+go_conf_get_bool (GOConfNode *node, gchar const *key)
+{
+	gboolean val;
+	gchar *real_key;
+
+	if (!node)
+		return FALSE;
+	real_key = go_conf_get_real_key (node, key);
+	val = g_key_file_get_boolean (node->key_file, BOOL_GROUP, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+gint
+go_conf_get_int	(GOConfNode *node, gchar const *key)
+{
+	gboolean val;
+	gchar *real_key;
+
+	if (!node)
+		return 0;
+	real_key = go_conf_get_real_key (node, key);
+	val = g_key_file_get_integer (node->key_file, INT_GROUP, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+gdouble
+go_conf_get_double (GOConfNode *node, gchar const *key)
+{
+	gchar *ptr;
+	gchar *real_key;
+	gdouble val;
+
+	if (!node)
+		return 0.;
+	real_key = go_conf_get_real_key (node, key);
+	ptr = g_key_file_get_value (node->key_file, DOUBLE_GROUP, real_key, NULL);
+	g_free (real_key);
+	if (ptr) {
+		val = g_ascii_strtod (ptr, NULL);
+		g_free (ptr);
+		if (errno != ERANGE)
+			return val;
+	}
+
+	return 0.0;
+}
+
+/**
+ * go_conf_get_string :
+ * @node : #GOConfNode
+ * @key : non NULL string.
+ *
+ * Returns the string value of @node's @key child as a string which the called needs to free
+ **/
+gchar *
+go_conf_get_string (GOConfNode *node, gchar const *key)
+{
+	gchar *real_key;
+	gchar *val = NULL;
+
+	if (!node)
+		return NULL;
+	real_key = go_conf_get_real_key (node, key);
+	val = g_key_file_get_string (node->key_file, STRING_GROUP, real_key, NULL);
+	g_free (real_key);
+
+	return val;
+}
+
+GSList *
+go_conf_get_str_list (GOConfNode *node, gchar const *key)
+{
+	gchar *real_key;
+	GSList *list = NULL;
+	gchar **str_list;
+	gsize i, nstrs;
+
+	if (!node)
+		return NULL;
+	real_key = go_conf_get_real_key (node, key);
+	str_list = g_key_file_get_string_list (node->key_file, STRLIST_GROUP, real_key, &nstrs, NULL);
+	g_free (real_key);
+
+	if (str_list != NULL) {
+		for (i = 0; i < nstrs; i++) {
+			if (str_list[i][0]) {
+				list = g_slist_append (list, g_strcompress (str_list[i]));
+			}
+		}
+		g_strfreev (str_list);
+	}
+
+	return list;
+}
+
+gboolean
+go_conf_load_bool (GOConfNode *node, gchar const *key, gboolean default_val)
+{
+	gchar *real_key;
+	gboolean val;
+	GError *err = NULL;
+
+	if (!node)
+		return default_val;
+	
+	real_key = go_conf_get_real_key (node, key);
+	val = g_key_file_get_boolean (node->key_file, BOOL_GROUP, real_key, &err);
+	if (err) {
+		val = default_val;
+		g_error_free (err);
+#if 0
+		d (g_warning ("%s: using default value '%s'", real_key, default_val ? "true" : "false"));
+#endif
+	}
+
+	g_free (real_key);
+	return val;
+}
+
+int
+go_conf_load_int (GOConfNode *node, gchar const *key,
+		  gint minima, gint maxima,
+		  gint default_val)
+{
+	gchar *real_key;
+	int val;
+	GError *err = NULL;
+
+	if (!node)
+		return default_val;
+	
+	real_key = go_conf_get_real_key (node, key);
+	val = g_key_file_get_integer (node->key_file, INT_GROUP, real_key, &err);
+
+	if (err) {
+		val = default_val;
+		g_error_free(err);
+#if 0
+		d (g_warning ("%s: using default value %d", real_key, default_val));
+#endif
+	} else if (val < minima || val > maxima) {
+		val = default_val;
+	}
+
+	g_free (real_key);
+	return val;
+}
+
+double
+go_conf_load_double (GOConfNode *node, gchar const *key,
+		     gdouble minima, gdouble maxima,
+		     gdouble default_val)
+{
+	gchar *real_key;
+	gchar *ptr;
+	double val;
+	GError *err = NULL;
+
+	if (!node)
+		return default_val;
+	
+	real_key = go_conf_get_real_key (node, key);
+	ptr = g_key_file_get_value (node->key_file, DOUBLE_GROUP, real_key, &err);
+
+	if (err) {
+		val = default_val;
+		g_error_free (err);
+	} else {
+		val = g_ascii_strtod (ptr, NULL);
+		if (val < minima || val > maxima) {
+			val = default_val;
+		}
+	}
+
+	g_free(ptr);
+	g_free (real_key);
+	return val;
+}
+
+char *
+go_conf_load_string (GOConfNode *node, gchar const *key)
+{
+	gchar *real_key;
+	char *val = NULL;
+	GError *err = NULL;
+
+	if (!node)
+		return NULL;
+	
+	real_key = go_conf_get_real_key (node, key);
+	val = g_key_file_get_string (node->key_file, STRING_GROUP, real_key, &err);
+
+	if (err) {
+#if 0
+		g_warning (err->message);
+#endif
+		g_error_free (err);
+	}
+
+	g_free (real_key);
+	return val;
+}
+
+GSList *
+go_conf_load_str_list (GOConfNode *node, gchar const *key)
+{
+	return go_conf_get_str_list (node, key);
+}
+
+char *
+go_conf_get_short_desc (GOConfNode *node, gchar const *key)
+{
+	return NULL;
+}
+
+gchar *
+go_conf_get_long_desc  (GOConfNode *node, gchar const *key)
+{
+	return NULL;
+}
+
+GType
+go_conf_get_type (GOConfNode *node, gchar const *key)
+{
+	gchar **groups;
+	gchar *real_key;
+	GType type = G_TYPE_NONE;
+	gsize i, ng;
+
+	if (!node)
+		return type;
+
+	real_key = go_conf_get_real_key (node, key);
+	groups = g_key_file_get_groups (node->key_file, &ng);
+
+	if (groups != NULL) {
+		for (i = 0; i < ng; i++) {
+			if (g_key_file_has_key (node->key_file, groups[i], real_key, NULL)) {
+				if (!g_ascii_strcasecmp (groups[i], BOOL_GROUP)) {
+					type = G_TYPE_BOOLEAN;
+				} else if (!g_ascii_strcasecmp (groups[i], INT_GROUP)) {
+					type = G_TYPE_INT;
+				} else if (!g_ascii_strcasecmp (groups[i], DOUBLE_GROUP)) {
+					type = G_TYPE_DOUBLE;
+				} else if (!g_ascii_strcasecmp (groups[i], STRING_GROUP)) {
+					type = G_TYPE_STRING;
+				} else if (!g_ascii_strcasecmp (groups[i], STRLIST_GROUP)) {
+					type = G_TYPE_STRING;
+				}
+				break;
+			}
+		}
+		g_strfreev (groups);
+	}
+
+	g_free (real_key);
+
+	return type;
+}
+
+gchar *
+go_conf_get_value_as_str (GOConfNode *node, gchar const *key)
+{
+	gchar *val = NULL;
+	gchar *real_key = go_conf_get_real_key (node, key);
+
+	if (!node)
+		return NULL;
+
+	val = g_key_file_get_string (node->key_file, STRING_GROUP, real_key, NULL);
+	g_free (real_key);
+	return val;
+}
+
+gboolean
+go_conf_set_value_from_str (GOConfNode *node, gchar const *key, gchar const *val_str)
+{
+	gchar *real_key = go_conf_get_real_key (node, key);
+
+	if (!node)
+		return FALSE;
+
+	g_key_file_set_value (node->key_file, STRING_GROUP, real_key, val_str);
+	g_free (real_key);
+	return TRUE;
+}
+
+void
+go_conf_sync (GOConfNode *node)
+{
+}
+
+void
+go_conf_remove_monitor (guint monitor_id)
+{
+}
+
+guint
+go_conf_add_monitor (GOConfNode *node, gchar const *key,
+		     GOConfMonitorFunc monitor, gpointer data)
+{
+	return 1;
+}

Added: trunk/goffice/app/go-conf-win32.c
==============================================================================
--- (empty file)
+++ trunk/goffice/app/go-conf-win32.c	Mon May 12 07:45:33 2008
@@ -0,0 +1,570 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <windows.h>
+
+#ifndef ERANGE
+/* mingw has not defined ERANGE (yet), MSVC has it though */
+# define ERANGE 34
+#endif
+
+struct _GOConfNode {
+	HKEY hKey;
+	gchar *path;
+};
+
+void
+go_conf_init ()
+{
+}
+
+void
+go_conf_shutdown (void)
+{
+}
+
+static gboolean
+go_conf_win32_get_node (GOConfNode *node, HKEY *phKey, gchar const *key, gboolean *is_new)
+{
+	gchar *path, *c;
+	LONG ret;
+	DWORD disposition;
+
+	path = g_strconcat (node ? "" : "Software\\", key, NULL);
+	for (c = path; *c; ++c) {
+		if (*c == '/')
+			*c = '\\';
+	}
+	ret = RegCreateKeyEx (node ? node->hKey : HKEY_CURRENT_USER, path,
+			      0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
+			      NULL, phKey, &disposition);
+	g_free (path);
+
+	if (is_new)
+		*is_new = disposition == REG_CREATED_NEW_KEY;
+
+	return ret == ERROR_SUCCESS;
+}
+
+static gboolean
+go_conf_win32_set (GOConfNode *node, gchar const *key,
+		   gint type, guchar *data, gint size)
+{
+	gchar *last_sep, *path = NULL;
+	HKEY hKey;
+	gboolean ok;
+
+	if ((last_sep = strrchr (key, '/')) != NULL) {
+		path = g_strndup (key, last_sep - key);
+		ok = go_conf_win32_get_node (node, &hKey, path, NULL);
+		g_free (path);
+		if (!ok)
+			return FALSE;
+		key = last_sep + 1;
+	}
+	else
+		hKey = node->hKey;
+	RegSetValueEx (hKey, key, 0, type, data, size);
+	if (path)
+		RegCloseKey (hKey);
+
+	return TRUE;
+}
+
+static gboolean
+go_conf_win32_get (GOConfNode *node, gchar const *key,
+		   gulong *type, guchar **data, gulong *size,
+		   gboolean realloc, gint *ret_code)
+{
+	gchar *last_sep, *path = NULL;
+	HKEY hKey;
+	LONG ret;
+	gboolean ok;
+
+	if ((last_sep = strrchr (key, '/')) != NULL) {
+		path = g_strndup (key, last_sep - key);
+		ok = go_conf_win32_get_node (node, &hKey, path, NULL);
+		g_free (path);
+		if (!ok)
+			return FALSE;
+		key = last_sep + 1;
+	}
+	else
+		hKey = node->hKey;
+	if (!*data && realloc) {
+		RegQueryValueEx (hKey, key, NULL, type, NULL, size);
+		*data = g_new (guchar, *size);
+	}
+	while ((ret = RegQueryValueEx (hKey, key, NULL,
+				       type, *data, size)) == ERROR_MORE_DATA &&
+	       realloc)
+		*data = g_realloc (*data, *size);
+	if (path)
+		RegCloseKey (hKey);
+	if (ret_code)
+		*ret_code = ret;
+
+	return ret == ERROR_SUCCESS;
+}
+
+static void
+go_conf_win32_clone (HKEY hSrcKey, gchar *key, HKEY hDstKey, gchar *buf1, gchar *buf2, gchar *buf3)
+{
+#define WIN32_MAX_REG_KEYNAME_LEN 256
+#define WIN32_MAX_REG_VALUENAME_LEN 32767
+#define WIN32_INIT_VALUE_DATA_LEN 2048
+	gint i;
+	gchar *subkey, *value_name, *data;
+	DWORD name_size, type, data_size;
+	HKEY hSrcSK, hDstSK;
+	FILETIME ft;
+	LONG ret;
+
+	if (RegOpenKeyEx (hSrcKey, key, 0, KEY_READ, &hSrcSK) != ERROR_SUCCESS)
+		return;
+
+	if (!buf1) {
+		subkey = g_malloc (WIN32_MAX_REG_KEYNAME_LEN);
+		value_name = g_malloc (WIN32_MAX_REG_VALUENAME_LEN);
+		data = g_malloc (WIN32_INIT_VALUE_DATA_LEN);
+	}
+	else {
+		subkey = buf1;
+		value_name = buf2;
+		data = buf3;
+	}
+
+	ret = ERROR_SUCCESS;
+	for (i = 0; ret == ERROR_SUCCESS; ++i) {
+		name_size = WIN32_MAX_REG_KEYNAME_LEN;
+		ret = RegEnumKeyEx (hSrcSK, i, subkey, &name_size, NULL, NULL, NULL, &ft);
+		if (ret != ERROR_SUCCESS)
+			continue;
+
+		if (RegCreateKeyEx (hDstKey, subkey, 0, NULL, 0, KEY_WRITE,
+				    NULL, &hDstSK, NULL) == ERROR_SUCCESS) {
+			go_conf_win32_clone (hSrcSK, subkey, hDstSK, subkey, value_name, data);
+			RegCloseKey (hDstSK);
+		}
+	}
+
+	ret = ERROR_SUCCESS;
+	for (i = 0; ret == ERROR_SUCCESS; ++i) {
+		name_size = WIN32_MAX_REG_KEYNAME_LEN;
+		data_size = WIN32_MAX_REG_VALUENAME_LEN;
+		while ((ret = RegEnumValue (hSrcSK, i, value_name, &name_size,
+					    NULL, &type, data, &data_size)) ==
+		       ERROR_MORE_DATA)
+			data = g_realloc (data, data_size);
+		if (ret != ERROR_SUCCESS)
+			continue;
+
+		RegSetValueEx (hDstKey, value_name, 0, type, data, data_size);
+	}
+
+	RegCloseKey (hSrcSK);
+	if (!buf1) {
+		g_free (subkey);
+		g_free (value_name);
+		g_free (data);
+	}
+}
+
+GOConfNode *
+go_conf_get_node (GOConfNode *parent, const gchar *key)
+{
+	HKEY hKey;
+	GOConfNode *node = NULL;
+	gboolean is_new;
+
+	if (go_conf_win32_get_node (parent, &hKey, key, &is_new)) {
+		if (!parent && is_new) {
+			gchar *path;
+
+			path = g_strconcat (".DEFAULT\\Software\\", key, NULL);
+			go_conf_win32_clone (HKEY_USERS, path, hKey, NULL, NULL, NULL);
+			g_free (path);
+		}
+		node = g_malloc (sizeof (GOConfNode));
+		node->hKey = hKey;
+		node->path = g_strdup (key);
+	}
+
+	return node;
+}
+
+void
+go_conf_free_node (GOConfNode *node)
+{
+	if (node) {
+		RegCloseKey (node->hKey);
+		g_free (node->path);
+		g_free (node);
+	}
+}
+
+void
+go_conf_set_bool (GOConfNode *node, gchar const *key, gboolean val)
+{
+	guchar bool = val ? 1 : 0;
+
+	go_conf_win32_set (node, key, REG_BINARY, (guchar *) &bool,
+			   sizeof (bool));
+}
+
+void
+go_conf_set_int (GOConfNode *node, gchar const *key, gint val)
+{
+	go_conf_win32_set (node, key, REG_DWORD, (guchar *) &val,
+			   sizeof (DWORD));
+}
+
+void
+go_conf_set_double (GOConfNode *node, gchar const *key, gdouble val)
+{
+	gchar str[G_ASCII_DTOSTR_BUF_SIZE];
+
+	g_ascii_dtostr (str, sizeof (str), val);
+	go_conf_win32_set (node, key, REG_SZ, (guchar *) str,
+			   strlen (str) + 1);
+}
+
+void
+go_conf_set_string (GOConfNode *node, gchar const *key, gchar const *str)
+{
+	go_conf_win32_set (node, key, REG_SZ, (guchar *) str,
+			   strlen (str) + 1);
+}
+
+void
+go_conf_set_str_list (GOConfNode *node, gchar const *key, GSList *list)
+{
+	GString *str_list;
+	GSList *list_node = list;
+
+	str_list = g_string_new ("");
+	while (list_node) {
+		g_string_append (str_list, g_strescape (list_node->data, NULL));
+		g_string_append_c (str_list, '\n');
+		list_node = list_node->next;
+	}
+	if (list)
+		g_string_truncate (str_list, str_list->len - 1);
+	go_conf_win32_set (node, key, REG_SZ, (guchar *) str_list->str,
+			   str_list->len + 1);
+	g_string_free (str_list, TRUE);
+}
+
+gboolean
+go_conf_get_bool (GOConfNode *node, gchar const *key)
+{
+	guchar val, *ptr = &val;
+	gulong type, size = sizeof (val);
+
+	if (go_conf_win32_get (node, key, &type, &ptr, &size, FALSE, NULL) &&
+	    type == REG_BINARY)
+		return val;
+
+	return FALSE;
+}
+
+gint
+go_conf_get_int	(GOConfNode *node, gchar const *key)
+{
+	gint val;
+	gulong type, size = sizeof (DWORD);
+	guchar *ptr = (guchar *) &val;
+
+	if (go_conf_win32_get (node, key, &type, &ptr, &size, FALSE, NULL) &&
+	    type == REG_DWORD)
+		return val;
+
+	return 0;
+}
+
+gdouble
+go_conf_get_double (GOConfNode *node, gchar const *key)
+{
+	gchar *ptr = go_conf_get_string (node, key);
+	gdouble val;
+
+	if (ptr) {
+		val = g_ascii_strtod (ptr, NULL);
+		g_free (ptr);
+		if (errno != ERANGE)
+			return val;
+	}
+
+	return 0.0;
+}
+
+/**
+ * go_conf_get_string :
+ * @node : #GOConfNode
+ * @key : non NULL string.
+ *
+ * Returns the string value of @node's @key child as a string which the called needs to free
+ **/
+gchar *
+go_conf_get_string (GOConfNode *node, gchar const *key)
+{
+	DWORD type, size = 0;
+	guchar *ptr = NULL;
+
+	if (go_conf_win32_get (node, key, &type, &ptr, &size, TRUE, NULL) &&
+	    type == REG_SZ)
+		return ptr;
+
+	g_free (ptr);
+
+	return NULL;
+}
+
+GSList *
+go_conf_get_str_list (GOConfNode *node, gchar const *key)
+{
+	return go_conf_load_str_list (node, key);
+}
+
+static guchar *
+go_conf_get (GOConfNode *node, gchar const *key, gulong expected)
+{
+	gulong type, size = 0;
+	guchar *ptr = NULL;
+	gint ret_code;
+
+	if (!go_conf_win32_get (node, key, &type, &ptr, &size, TRUE, &ret_code)) {
+		LPTSTR msg_buf;
+
+		FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			       FORMAT_MESSAGE_FROM_SYSTEM |
+			       FORMAT_MESSAGE_IGNORE_INSERTS,
+			       NULL,
+			       ret_code,
+			       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+			       (LPTSTR) &msg_buf,
+			       0,
+			       NULL);
+		d (g_warning ("Unable to load key '%s' : because %s",
+			      key, msg_buf));
+		LocalFree (msg_buf);
+		g_free (ptr);
+		return NULL;
+	}
+
+	if (type != expected) {
+		g_warning ("Expected `%lu' got `%lu' for key %s of node %s",
+			   expected, type, key, node->path);
+		g_free (ptr);
+		return NULL;
+	}
+
+	return ptr;
+}
+
+gboolean
+go_conf_load_bool (GOConfNode *node, gchar const *key,
+		   gboolean default_val)
+{
+	guchar *val = go_conf_get (node, key, REG_BINARY);
+	gboolean res;
+
+	if (val) {
+		res = (gboolean) *val;
+		g_free (val);
+	} else {
+		d (g_warning ("Using default value '%s'", default_val ? "true" : "false"));
+		return default_val;
+	}
+
+	return res;
+}
+
+gint
+go_conf_load_int (GOConfNode *node, gchar const *key,
+		  gint minima, gint maxima, gint default_val)
+{
+	guchar *val = go_conf_get (node, key, REG_DWORD);
+	gint res;
+
+	if (val) {
+		res = *(gint *) val;
+		g_free (val);
+		if (res < minima || maxima < res) {
+			g_warning ("Invalid value '%d' for %s. If should be >= %d and <= %d",
+				   res, key, minima, maxima);
+			val = NULL;
+		}
+	}
+	if (!val) {
+		d (g_warning ("Using default value '%d'", default_val));
+		return default_val;
+	}
+
+	return res;
+}
+
+gdouble
+go_conf_load_double (GOConfNode *node, gchar const *key,
+		     gdouble minima, gdouble maxima, gdouble default_val)
+{
+	gdouble res = -1;
+	gchar *val = (gchar *) go_conf_get (node, key, REG_SZ);
+
+	if (val) {
+		res = g_ascii_strtod (val, NULL);
+		g_free (val);
+		if (errno == ERANGE || res < minima || maxima < res) {
+			g_warning ("Invalid value '%g' for %s.  If should be >= %g and <= %g",
+				   res, key, minima, maxima);
+			val = NULL;
+		}
+	}
+	if (!val) {
+		d (g_warning ("Using default value '%g'", default_val));
+		return default_val;
+	}
+
+	return res;
+}
+
+gchar *
+go_conf_load_string (GOConfNode *node, gchar const *key)
+{
+	return go_conf_get (node, key, REG_SZ);
+}
+
+GSList *
+go_conf_load_str_list (GOConfNode *node, gchar const *key)
+{
+	GSList *list = NULL;
+	gchar *ptr;
+	gchar **str_list;
+	gint i;
+
+	if ((ptr = go_conf_get_string (node, key)) != NULL) {
+		str_list = g_strsplit ((gchar const *) ptr, "\n", 0);
+		for (i = 0; str_list[i]; ++i)
+			list = g_slist_prepend (list, g_strcompress (str_list[i]));
+		list = g_slist_reverse (list);
+		g_strfreev (str_list);
+		g_free (ptr);
+	}
+
+	return list;
+}
+
+gchar *
+go_conf_get_short_desc (GOConfNode *node, gchar const *key)
+{
+	return NULL;
+}
+
+gchar *
+go_conf_get_long_desc  (GOConfNode *node, gchar const *key)
+{
+	return NULL;
+}
+
+GType
+go_conf_get_type (GOConfNode *node, gchar const *key)
+{
+	gulong type, size;
+	guchar *ptr = NULL;
+	GType t = G_TYPE_NONE;
+
+	if (go_conf_win32_get (node, key, &type, &ptr, &size, FALSE, NULL)) {
+		switch (type) {
+		case REG_BINARY:
+			t = G_TYPE_BOOLEAN; break;
+		case REG_DWORD:
+			t = G_TYPE_INT; break;
+		case REG_SZ:
+			t = G_TYPE_STRING; break;
+		}
+	}
+
+	return t;
+}
+
+gchar *
+go_conf_get_value_as_str (GOConfNode *node, gchar const *key)
+{
+	gchar *value_string;
+
+	switch (go_conf_get_type (node, key)) {
+	case G_TYPE_STRING:
+		value_string = go_conf_get_string (node, key);
+		break;
+	case G_TYPE_INT:
+		value_string = g_strdup_printf ("%i", go_conf_get_int (node, key));
+		break;
+	case G_TYPE_FLOAT:
+		value_string = go_conf_get_string (node, key);
+		break;
+	case G_TYPE_BOOLEAN:
+		value_string = g_strdup (go_locale_boolean_name (go_conf_get_bool (node, key)));
+		break;
+	default:
+		value_string = g_strdup ("ERROR FIXME");
+	}
+
+	return value_string;
+}
+
+gboolean
+go_conf_set_value_from_str (GOConfNode *node, gchar const *key,
+			    gchar const *val_str)
+{
+	switch (go_conf_get_type (node, key)) {
+	case G_TYPE_STRING:
+		go_conf_set_string (node, key, val_str);
+		break;
+	case G_TYPE_INT: {
+		GODateConventions const *conv = NULL;  /* workbook_date_conv (state->wb); */
+		GnmValue *value = format_match_number (val_str, NULL, conv);
+		if (value != NULL) {
+			gint the_int = value_get_as_int (value);
+			go_conf_set_int (node, key, the_int);
+		}
+		if (value)
+			value_release (value);
+		break;
+	}
+	case G_TYPE_BOOLEAN: {
+		GODateConventions const *conv = NULL;  /* workbook_date_conv (state->wb); */
+		GnmValue *value = format_match_number (val_str, NULL, conv);
+		gboolean err, the_bool;
+		if (value != NULL) {
+			err = FALSE;
+			the_bool =  value_get_as_bool (value, &err);
+			go_conf_set_bool (node, key, the_bool);
+		}
+		if (value)
+			value_release (value);
+		break;
+	}
+	default:
+		g_warning ("Unsupported gconf type in preference dialog");
+	}
+
+	return TRUE;
+}
+
+void
+go_conf_sync (GOConfNode *node)
+{
+	if (node)
+		RegFlushKey (node->hKey);
+}
+
+void
+go_conf_remove_monitor (guint monitor_id)
+{
+}
+
+guint
+go_conf_add_monitor (GOConfNode *node, gchar const *key,
+		     GOConfMonitorFunc monitor, gpointer data)
+{
+	return 1;
+}

Added: trunk/goffice/app/go-conf.c
==============================================================================
--- (empty file)
+++ trunk/goffice/app/go-conf.c	Mon May 12 07:45:33 2008
@@ -0,0 +1,94 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * go-conf.c:
+ *
+ * Author:
+ *	Andreas J. Guelzow <aguelzow taliesin ca>
+ *
+ * (C) Copyright 2002-2005 Andreas J. Guelzow <aguelzow taliesin ca>
+ *
+ * Introduced the concept of "node" and implemented the win32 backend
+ * by Ivan, Wong Yat Cheung <email ivanwong info>, 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <goffice-config.h>
+#include <go-conf.h>
+#include <goffice/utils/goffice-utils.h>
+#include <goffice/utils/go-format.h>
+#include <goffice/utils/go-locale.h>
+
+#define NO_DEBUG_GCONF
+#ifndef NO_DEBUG_GCONF
+#define d(code)	{ code; }
+#else
+#define d(code)
+#endif
+
+#ifdef GOFFICE_WITH_GNOME
+#include "go-conf-gconf.c"
+#elif defined G_OS_WIN32
+#include "go-conf-win32.c"
+#else
+#include "go-conf-keyfile.c"
+#endif
+
+gchar *
+go_conf_get_enum_as_str (GOConfNode *node, gchar const *key)
+{
+	return go_conf_get_string (node, key);
+}
+int
+go_conf_load_enum (GOConfNode *node, gchar const *key, GType t, int default_val)
+{
+	int	 res;
+	gchar   *val_str = go_conf_load_string (node, key);
+	gboolean use_default = TRUE;
+
+	if (NULL != val_str) {
+		GEnumClass *enum_class = G_ENUM_CLASS (g_type_class_ref (t));
+		GEnumValue *enum_value = g_enum_get_value_by_nick (enum_class, val_str);
+		if (NULL == enum_value)
+			enum_value = g_enum_get_value_by_name (enum_class, val_str);
+
+		if (NULL != enum_value) {
+			use_default = FALSE;
+			res = enum_value->value;
+		} else {
+			g_warning ("Unknown value '%s' for %s", val_str, key);
+		}
+
+		g_type_class_unref (enum_class);
+		g_free (val_str);
+
+	}
+
+	if (use_default) {
+		d (g_warning ("Using default value '%d'", default_val));
+		return default_val;
+	}
+	return res;
+}
+
+void
+go_conf_set_enum (GOConfNode *node, gchar const *key, GType t, gint val)
+{
+	GEnumClass *enum_class = G_ENUM_CLASS (g_type_class_ref (t));
+	GEnumValue *enum_value = g_enum_get_value (enum_class, val);
+	go_conf_set_string (node, key, enum_value->value_nick);
+	g_type_class_unref (enum_class);
+}
+

Added: trunk/goffice/app/go-conf.h
==============================================================================
--- (empty file)
+++ trunk/goffice/app/go-conf.h	Mon May 12 07:45:33 2008
@@ -0,0 +1,53 @@
+/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef GO_CONF_H
+# define GO_CONF_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GOConfNode GOConfNode;
+
+void go_conf_init (void);
+void go_conf_shutdown (void);
+
+GOConfNode * go_conf_get_node       (GOConfNode *parent, gchar const *key);
+void	 go_conf_free_node	    (GOConfNode *node);
+
+gchar	*go_conf_get_short_desc     (GOConfNode *node, gchar const *key);
+gchar	*go_conf_get_long_desc      (GOConfNode *node, gchar const *key);
+GType	 go_conf_get_type	    (GOConfNode *node, gchar const *key);
+gchar	*go_conf_get_value_as_str   (GOConfNode *node, gchar const *key);
+gboolean go_conf_set_value_from_str (GOConfNode *node, gchar const *key, gchar const *val_str);
+
+gboolean go_conf_get_bool	(GOConfNode *node, gchar const *key);
+gint	 go_conf_get_int	(GOConfNode *node, gchar const *key);
+gdouble	 go_conf_get_double	(GOConfNode *node, gchar const *key);
+gchar	*go_conf_get_string	(GOConfNode *node, gchar const *key);
+GSList	*go_conf_get_str_list	(GOConfNode *node, gchar const *key);
+gchar	*go_conf_get_enum_as_str(GOConfNode *node, gchar const *key);
+
+gboolean go_conf_load_bool	(GOConfNode *node, gchar const *key, gboolean default_val);
+gint	 go_conf_load_int	(GOConfNode *node, gchar const *key, gint minima, gint maxima, gint default_val);
+gdouble	 go_conf_load_double	(GOConfNode *node, gchar const *key, gdouble minima, gdouble maxima, gdouble default_val);
+gchar	*go_conf_load_string	(GOConfNode *node, gchar const *key);
+GSList	*go_conf_load_str_list	(GOConfNode *node, gchar const *key);
+int	 go_conf_load_enum	(GOConfNode *node, gchar const *key, GType t, int default_val);
+
+void	 go_conf_set_bool	(GOConfNode *node, gchar const *key, gboolean val);
+void	 go_conf_set_int	(GOConfNode *node, gchar const *key, gint val);
+void	 go_conf_set_double	(GOConfNode *node, gchar const *key, gdouble val);
+void	 go_conf_set_string	(GOConfNode *node, gchar const *key, gchar const *str);
+void	 go_conf_set_str_list	(GOConfNode *node, gchar const *key, GSList *list);
+void	 go_conf_set_enum	(GOConfNode *node, gchar const *key, GType t, gint val);
+
+void	 go_conf_sync		(GOConfNode *node);
+
+typedef void (*GOConfMonitorFunc) (GOConfNode *node, gchar const *key, gpointer data);
+void	 go_conf_remove_monitor	(guint monitor_id);
+guint	 go_conf_add_monitor	(GOConfNode *node, gchar const *key,
+				 GOConfMonitorFunc monitor, gpointer data);
+
+G_END_DECLS
+
+#endif /* GO_CONF_H */

Modified: trunk/goffice/component/go-component.h
==============================================================================
--- trunk/goffice/component/go-component.h	(original)
+++ trunk/goffice/component/go-component.h	Mon May 12 07:45:33 2008
@@ -26,6 +26,7 @@
 #include <gtk/gtkwindow.h>
 #include <goffice/goffice.h>
 #include <goffice/app/goffice-app.h>
+#include <goffice/component/goffice-component.h>
 
 G_BEGIN_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]