2005-06-22 11:20:32 -07:00
|
|
|
/*
|
|
|
|
* mooutils/mooprefs.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2005 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* See COPYING file that comes with this distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "mooutils/mooprefs.h"
|
|
|
|
#include "mooutils/moocompat.h"
|
|
|
|
#include "mooutils/eggregex.h"
|
|
|
|
#include "mooutils/moomarshals.h"
|
2005-07-28 12:25:10 -07:00
|
|
|
#include "mooutils/moomarkup.h"
|
|
|
|
#include "mooutils/moofileutils.h"
|
2005-06-22 11:20:32 -07:00
|
|
|
#include <string.h>
|
2005-07-28 12:25:10 -07:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#define PREFS_ROOT "Prefs"
|
|
|
|
/* #define DEBUG_READWRITE 1 */
|
2005-06-22 11:20:32 -07:00
|
|
|
|
|
|
|
|
|
|
|
static MooPrefs *instance (void)
|
|
|
|
{
|
|
|
|
static MooPrefs *p = NULL;
|
|
|
|
if (!p)
|
|
|
|
p = MOO_PREFS (g_object_new (MOO_TYPE_PREFS, NULL));
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* MOO_TYPE_PREFS */
|
|
|
|
G_DEFINE_TYPE (MooPrefs, moo_prefs, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2005-07-28 12:25:10 -07:00
|
|
|
GType type;
|
|
|
|
GValue value;
|
|
|
|
GValue default_value;
|
|
|
|
} PrefsItem;
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean type_is_supported (GType type);
|
|
|
|
static gboolean convert_value (const GValue *src,
|
|
|
|
GValue *dest);
|
|
|
|
static gboolean value_equal (const GValue *a,
|
|
|
|
const GValue *b);
|
|
|
|
|
|
|
|
static gboolean convert_to_bool (const GValue *val);
|
|
|
|
static int convert_to_int (const GValue *val);
|
|
|
|
static int convert_to_enum (const GValue *val,
|
|
|
|
GType enum_type);
|
|
|
|
static double convert_to_double (const GValue *val);
|
|
|
|
static const GdkColor *convert_to_color (const GValue *val);
|
|
|
|
static const char *convert_to_string (const GValue *val);
|
|
|
|
|
|
|
|
static PrefsItem *item_new (GType type,
|
|
|
|
const GValue *value,
|
|
|
|
const GValue *default_value)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
PrefsItem *item;
|
|
|
|
|
|
|
|
g_return_val_if_fail (type_is_supported (type), NULL);
|
|
|
|
g_return_val_if_fail (!G_IS_VALUE (value) ||
|
|
|
|
G_VALUE_TYPE (value) == type, NULL);
|
|
|
|
g_return_val_if_fail (!G_IS_VALUE (default_value) ||
|
|
|
|
G_VALUE_TYPE (default_value) == type, NULL);
|
|
|
|
|
|
|
|
item = g_new0 (PrefsItem, 1);
|
|
|
|
item->type = type;
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
{
|
|
|
|
g_value_init (&item->value, type);
|
|
|
|
g_value_copy (value, &item->value);
|
|
|
|
}
|
|
|
|
if (default_value)
|
|
|
|
{
|
|
|
|
g_value_init (&item->default_value, type);
|
|
|
|
g_value_copy (default_value, &item->default_value);
|
|
|
|
}
|
|
|
|
|
2005-06-22 11:20:32 -07:00
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
static const GValue *item_value (PrefsItem *item)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (item != NULL, NULL);
|
|
|
|
if (G_IS_VALUE (&item->value))
|
|
|
|
return &item->value;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const GValue *item_default_value (PrefsItem *item)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (item != NULL, NULL);
|
|
|
|
if (G_IS_VALUE (&item->default_value))
|
|
|
|
return &item->default_value;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CONVERT_VALUE_TYPE(val,type) \
|
|
|
|
G_STMT_START { \
|
|
|
|
if (G_IS_VALUE (val)) \
|
|
|
|
{ \
|
|
|
|
GValue tmp__; \
|
|
|
|
tmp__.g_type = 0; \
|
|
|
|
g_value_init (&tmp__, (type)); \
|
|
|
|
if (!convert_value (val, &tmp__)) \
|
|
|
|
{ \
|
|
|
|
g_warning ("%s: could not convert " \
|
|
|
|
"old value", G_STRLOC); \
|
|
|
|
g_value_unset (val); \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
g_value_unset (val); \
|
|
|
|
g_value_init (val, type); \
|
|
|
|
g_value_copy (&tmp__, val); \
|
|
|
|
g_value_unset (&tmp__); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
|
|
static void item_set_type (PrefsItem *item,
|
|
|
|
GType type)
|
|
|
|
{
|
|
|
|
g_return_if_fail (item != NULL);
|
|
|
|
g_return_if_fail (type_is_supported (type));
|
|
|
|
|
|
|
|
if (type != item->type)
|
|
|
|
{
|
|
|
|
item->type = type;
|
|
|
|
CONVERT_VALUE_TYPE (&item->value, type);
|
|
|
|
CONVERT_VALUE_TYPE (&item->default_value, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-29 04:51:36 -07:00
|
|
|
static void set_val (PrefsItem *item,
|
|
|
|
GValue *dest,
|
|
|
|
const GValue *val)
|
|
|
|
{
|
|
|
|
g_return_if_fail (item != NULL);
|
|
|
|
g_return_if_fail (!val || G_IS_VALUE (val));
|
|
|
|
|
|
|
|
if (val)
|
|
|
|
{
|
|
|
|
if (G_VALUE_TYPE (val) == item->type)
|
|
|
|
{
|
|
|
|
if (!G_IS_VALUE (dest))
|
|
|
|
g_value_init (dest, item->type);
|
|
|
|
g_value_copy (val, dest);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_return_if_fail (type_is_supported (G_VALUE_TYPE (val)));
|
|
|
|
if (!G_IS_VALUE (dest))
|
|
|
|
g_value_init (dest, item->type);
|
|
|
|
g_return_if_fail (convert_value (val, dest));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (G_IS_VALUE (dest))
|
|
|
|
g_value_unset (dest);
|
|
|
|
}
|
|
|
|
}
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
|
|
|
|
static void item_set (PrefsItem *item,
|
|
|
|
const GValue *new_value)
|
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
set_val (item, &item->value, new_value);
|
2005-07-28 12:25:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void item_set_default (PrefsItem *item,
|
|
|
|
const GValue *new_value)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
set_val (item, &item->default_value, new_value);
|
2005-07-28 12:25:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void item_unset_value (PrefsItem *item)
|
|
|
|
{
|
|
|
|
if (G_IS_VALUE (&item->value))
|
|
|
|
g_value_unset (&item->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void item_free (PrefsItem *item)
|
|
|
|
{
|
|
|
|
if (item)
|
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
item->type = 0;
|
2005-07-28 12:25:10 -07:00
|
|
|
if (G_IS_VALUE (&item->value))
|
|
|
|
g_value_unset (&item->value);
|
|
|
|
if (G_IS_VALUE (&item->default_value))
|
|
|
|
g_value_unset (&item->default_value);
|
|
|
|
g_free (item);
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
char *key;
|
|
|
|
EggRegex *regex;
|
|
|
|
} Pattern;
|
|
|
|
|
|
|
|
static void pattern_free (Pattern p,
|
|
|
|
MooPrefsMatchType type);
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
guint id;
|
|
|
|
MooPrefsMatchType type;
|
|
|
|
Pattern pattern;
|
|
|
|
guint prefix_len;
|
|
|
|
MooPrefsNotify callback;
|
|
|
|
gpointer data;
|
|
|
|
guint blocked : 1;
|
|
|
|
} Closure;
|
|
|
|
|
|
|
|
static Closure *closure_new (MooPrefs *prefs,
|
|
|
|
const char *pattern,
|
|
|
|
MooPrefsMatchType match_type,
|
|
|
|
MooPrefsNotify callback,
|
|
|
|
gpointer data);
|
|
|
|
static void closure_free (Closure *closure);
|
|
|
|
static gboolean closure_match (Closure *closure,
|
|
|
|
const char *key);
|
|
|
|
static void closure_invoke (Closure *closure,
|
|
|
|
const char *key,
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *value);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
|
|
|
|
|
|
|
struct _MooPrefsPrivate {
|
2005-07-28 12:25:10 -07:00
|
|
|
GHashTable *data; /* char* -> Item* */
|
|
|
|
guint last_notify_id;
|
|
|
|
GList *closures;
|
|
|
|
GHashTable *closures_map; /* guint -> closures list link */
|
|
|
|
MooMarkupDoc *xml;
|
2005-06-22 11:20:32 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void prefs_set (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
const GValue *value);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static const GValue *prefs_get (MooPrefs *prefs,
|
|
|
|
const char *key);
|
|
|
|
static PrefsItem *prefs_get_item (MooPrefs *prefs,
|
|
|
|
const char *key);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void prefs_change (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
PrefsItem *item,
|
|
|
|
const GValue *value);
|
|
|
|
static void prefs_create (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
const GValue *value,
|
|
|
|
const GValue *default_value);
|
|
|
|
static void prefs_create_type (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
GType type);
|
|
|
|
static void prefs_remove (MooPrefs *prefs,
|
|
|
|
const char *key);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void emit_notify (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
const GValue *value);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
|
|
|
|
|
|
|
static void moo_prefs_finalize (GObject *object);
|
|
|
|
|
|
|
|
|
|
|
|
static void moo_prefs_class_init (MooPrefsClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
gobject_class->finalize = moo_prefs_finalize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void moo_prefs_init (MooPrefs *prefs)
|
|
|
|
{
|
|
|
|
prefs->priv = g_new0 (MooPrefsPrivate, 1);
|
|
|
|
|
2005-07-29 04:51:36 -07:00
|
|
|
prefs->priv->data =
|
|
|
|
g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
(GDestroyNotify) g_free,
|
|
|
|
(GDestroyNotify) item_free);
|
2005-06-22 11:20:32 -07:00
|
|
|
prefs->priv->last_notify_id = 0;
|
|
|
|
prefs->priv->closures = NULL;
|
|
|
|
prefs->priv->closures_map = g_hash_table_new (g_direct_hash, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void moo_prefs_finalize (GObject *obj)
|
|
|
|
{
|
|
|
|
MooPrefs *prefs = MOO_PREFS (obj);
|
|
|
|
|
|
|
|
g_hash_table_destroy (prefs->priv->data);
|
2005-07-29 04:51:36 -07:00
|
|
|
prefs->priv->data = NULL;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
|
|
|
g_hash_table_destroy (prefs->priv->closures_map);
|
2005-07-29 04:51:36 -07:00
|
|
|
prefs->priv->closures_map = NULL;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
|
|
|
g_list_foreach (prefs->priv->closures,
|
|
|
|
(GFunc) closure_free,
|
|
|
|
NULL);
|
|
|
|
g_list_free (prefs->priv->closures);
|
2005-07-29 04:51:36 -07:00
|
|
|
prefs->priv->closures = NULL;
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
if (prefs->priv->xml)
|
|
|
|
moo_markup_doc_unref (prefs->priv->xml);
|
2005-07-29 04:51:36 -07:00
|
|
|
prefs->priv->xml = NULL;
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
g_free (prefs->priv);
|
2005-07-29 04:51:36 -07:00
|
|
|
prefs->priv = NULL;
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
G_OBJECT_CLASS(moo_prefs_parent_class)->finalize (obj);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void prefs_set (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
const GValue *val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
|
|
|
g_return_if_fail (MOO_IS_PREFS (prefs));
|
2005-07-29 04:51:36 -07:00
|
|
|
g_return_if_fail (key && key[0]);
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
if (val)
|
|
|
|
{
|
|
|
|
PrefsItem *item = prefs_get_item (prefs, key);
|
|
|
|
|
|
|
|
if (item)
|
|
|
|
prefs_change (prefs, key, item, val);
|
|
|
|
else
|
|
|
|
prefs_create (prefs, key, val, NULL);
|
|
|
|
}
|
|
|
|
else
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
|
|
|
prefs_remove (prefs, key);
|
|
|
|
}
|
2005-07-28 12:25:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void prefs_new_key (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
GType type,
|
|
|
|
const GValue *default_value)
|
|
|
|
{
|
|
|
|
PrefsItem *item;
|
|
|
|
|
|
|
|
g_return_if_fail (MOO_IS_PREFS (prefs));
|
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
g_return_if_fail (type_is_supported (type));
|
|
|
|
g_return_if_fail (!G_IS_VALUE (default_value) ||
|
|
|
|
G_VALUE_TYPE (default_value) == type);
|
|
|
|
|
|
|
|
item = prefs_get_item (prefs, key);
|
|
|
|
|
|
|
|
if (item)
|
|
|
|
{
|
|
|
|
item_set_type (item, type);
|
|
|
|
if (default_value)
|
|
|
|
item_set_default (item, default_value);
|
2005-07-30 23:20:59 -07:00
|
|
|
if (!item_value (item) && item_default_value (item))
|
2005-07-28 12:25:10 -07:00
|
|
|
item_set (item, item_default_value (item));
|
|
|
|
emit_notify (prefs, key, item_value (item));
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
else
|
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
prefs_create_type (prefs, key, type);
|
|
|
|
if (default_value)
|
|
|
|
{
|
|
|
|
item = prefs_get_item (prefs, key);
|
|
|
|
g_assert (item != NULL);
|
|
|
|
if (default_value)
|
|
|
|
{
|
|
|
|
item_set_default (item, default_value);
|
|
|
|
item_set (item, default_value);
|
|
|
|
}
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static PrefsItem *prefs_get_item (MooPrefs *prefs,
|
|
|
|
const char *key)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
|
|
|
return g_hash_table_lookup (prefs->priv->data, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static const GValue *prefs_get (MooPrefs *prefs,
|
|
|
|
const char *key)
|
|
|
|
{
|
|
|
|
PrefsItem *item = prefs_get_item (prefs, key);
|
2005-07-29 04:51:36 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (item)
|
|
|
|
return item_value (item);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void prefs_change (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
PrefsItem *item,
|
|
|
|
const GValue *val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
item_set (item, val);
|
2005-06-22 11:20:32 -07:00
|
|
|
emit_notify (prefs, key, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void prefs_create (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
const GValue *value,
|
|
|
|
const GValue *default_value)
|
|
|
|
{
|
|
|
|
PrefsItem *item;
|
|
|
|
GType type;
|
|
|
|
|
|
|
|
if (G_IS_VALUE (value))
|
|
|
|
type = G_VALUE_TYPE (value);
|
|
|
|
else if (G_IS_VALUE (default_value))
|
|
|
|
type = G_VALUE_TYPE (default_value);
|
|
|
|
else
|
|
|
|
g_return_if_reached ();
|
|
|
|
|
|
|
|
item = item_new (type, value, default_value);
|
|
|
|
g_hash_table_insert (prefs->priv->data,
|
|
|
|
g_strdup (key), item);
|
|
|
|
emit_notify (prefs, key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void prefs_create_type (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
GType type)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
PrefsItem *item;
|
|
|
|
|
|
|
|
item = item_new (type, NULL, NULL);
|
2005-06-22 11:20:32 -07:00
|
|
|
g_hash_table_insert (prefs->priv->data,
|
2005-07-28 12:25:10 -07:00
|
|
|
g_strdup (key), item);
|
|
|
|
emit_notify (prefs, key, NULL);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void prefs_remove (MooPrefs *prefs,
|
|
|
|
const char *key)
|
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
PrefsItem *item;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-29 04:51:36 -07:00
|
|
|
item = g_hash_table_lookup (prefs->priv->data, key);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-29 04:51:36 -07:00
|
|
|
if (item)
|
2005-07-28 12:25:10 -07:00
|
|
|
{
|
|
|
|
if (item_default_value (item))
|
|
|
|
item_unset_value (item);
|
|
|
|
else
|
|
|
|
g_hash_table_remove (prefs->priv->data, key);
|
2005-07-29 04:51:36 -07:00
|
|
|
|
|
|
|
emit_notify (prefs, key, NULL);
|
2005-07-28 12:25:10 -07:00
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void emit_notify (MooPrefs *prefs,
|
|
|
|
const char *key,
|
|
|
|
const GValue *value)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
g_object_ref (prefs);
|
|
|
|
|
|
|
|
for (l = prefs->priv->closures; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
Closure *closure = l->data;
|
|
|
|
if (!closure->blocked && closure_match (closure, key))
|
2005-07-28 12:25:10 -07:00
|
|
|
closure_invoke (closure, key, value);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (prefs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/* Closure
|
|
|
|
*/
|
|
|
|
|
|
|
|
static Closure *closure_new (MooPrefs *prefs,
|
|
|
|
const char *pattern,
|
|
|
|
MooPrefsMatchType match_type,
|
|
|
|
MooPrefsNotify callback,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
EggRegex *regex;
|
|
|
|
Closure *closure;
|
|
|
|
GError *err = NULL;
|
|
|
|
|
|
|
|
closure = g_new (Closure, 1);
|
|
|
|
closure->type = match_type;
|
|
|
|
closure->callback = callback;
|
|
|
|
closure->data = data;
|
|
|
|
closure->blocked = FALSE;
|
|
|
|
|
|
|
|
closure->id = ++prefs->priv->last_notify_id;
|
|
|
|
|
|
|
|
switch (match_type) {
|
|
|
|
case MOO_PREFS_MATCH_REGEX:
|
|
|
|
regex = egg_regex_new (pattern, EGG_REGEX_EXTENDED, 0, &err);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
g_warning ("%s: %s", G_STRLOC, err->message);
|
|
|
|
g_error_free (err);
|
|
|
|
egg_regex_free (regex);
|
|
|
|
g_free (closure);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
egg_regex_optimize (regex, &err);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
g_warning ("%s: %s", G_STRLOC, err->message);
|
|
|
|
g_error_free (err);
|
|
|
|
}
|
|
|
|
|
|
|
|
closure->pattern.regex = regex;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOO_PREFS_MATCH_PREFIX:
|
|
|
|
closure->pattern.key = g_strdup (pattern);
|
|
|
|
closure->prefix_len = strlen (pattern);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOO_PREFS_MATCH_KEY:
|
|
|
|
closure->pattern.key = g_strdup (pattern);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return closure;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void closure_free (Closure *closure)
|
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
if (closure)
|
|
|
|
{
|
|
|
|
pattern_free (closure->pattern, closure->type);
|
|
|
|
g_free (closure);
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean closure_match (Closure *closure,
|
|
|
|
const char *key)
|
|
|
|
{
|
|
|
|
switch (closure->type) {
|
|
|
|
case MOO_PREFS_MATCH_KEY:
|
|
|
|
return !strcmp (key, closure->pattern.key);
|
|
|
|
|
|
|
|
case MOO_PREFS_MATCH_PREFIX:
|
|
|
|
if (closure->prefix_len)
|
|
|
|
return !strncmp (key, closure->pattern.key,
|
|
|
|
closure->prefix_len);
|
|
|
|
else
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case MOO_PREFS_MATCH_REGEX:
|
|
|
|
egg_regex_clear (closure->pattern.regex);
|
|
|
|
return egg_regex_match (closure->pattern.regex,
|
|
|
|
key, -1, 0) > 0;
|
|
|
|
|
|
|
|
default:
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_val_if_reached (FALSE);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void closure_invoke (Closure *closure,
|
|
|
|
const char *key,
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *value)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
|
|
|
closure->callback (key, value, closure->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void pattern_free (Pattern p,
|
|
|
|
MooPrefsMatchType type)
|
|
|
|
{
|
|
|
|
if (!p.key) return;
|
|
|
|
if (type == MOO_PREFS_MATCH_REGEX)
|
|
|
|
egg_regex_free (p.regex);
|
|
|
|
else
|
|
|
|
g_free (p.key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/* MooPrefs
|
|
|
|
*/
|
|
|
|
|
2005-09-04 21:24:21 -07:00
|
|
|
MooMarkupDoc *moo_prefs_get_markup (void)
|
|
|
|
{
|
|
|
|
MooPrefs *prefs = instance ();
|
|
|
|
return prefs->priv->xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-22 11:20:32 -07:00
|
|
|
guint moo_prefs_notify_connect (const char *pattern,
|
|
|
|
MooPrefsMatchType match_type,
|
|
|
|
MooPrefsNotify callback,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
Closure *closure;
|
|
|
|
MooPrefs *prefs = instance ();
|
|
|
|
|
|
|
|
g_return_val_if_fail (pattern != NULL, 0);
|
|
|
|
g_return_val_if_fail (match_type == MOO_PREFS_MATCH_KEY ||
|
|
|
|
match_type == MOO_PREFS_MATCH_PREFIX ||
|
|
|
|
match_type == MOO_PREFS_MATCH_REGEX, 0);
|
|
|
|
g_return_val_if_fail (callback != NULL, 0);
|
|
|
|
|
|
|
|
closure = closure_new (prefs, pattern, match_type, callback, data);
|
|
|
|
g_return_val_if_fail (closure != NULL, 0);
|
|
|
|
|
|
|
|
prefs->priv->closures = g_list_prepend (prefs->priv->closures, closure);
|
|
|
|
g_hash_table_insert (prefs->priv->closures_map,
|
|
|
|
GUINT_TO_POINTER (closure->id),
|
|
|
|
prefs->priv->closures);
|
|
|
|
|
|
|
|
return closure->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Closure *find_closure (MooPrefs *prefs,
|
|
|
|
guint id)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
l = g_hash_table_lookup (prefs->priv->closures_map,
|
|
|
|
GUINT_TO_POINTER (id));
|
|
|
|
if (l)
|
|
|
|
return l->data;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gboolean moo_prefs_notify_block (guint id)
|
|
|
|
{
|
|
|
|
Closure *c;
|
|
|
|
|
|
|
|
g_return_val_if_fail (id != 0, FALSE);
|
|
|
|
|
|
|
|
c = find_closure (instance(), id);
|
|
|
|
g_return_val_if_fail (c != NULL, FALSE);
|
|
|
|
|
|
|
|
c->blocked = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gboolean moo_prefs_notify_unblock (guint id)
|
|
|
|
{
|
|
|
|
Closure *c;
|
|
|
|
|
|
|
|
g_return_val_if_fail (id != 0, FALSE);
|
|
|
|
|
|
|
|
c = find_closure (instance(), id);
|
|
|
|
g_return_val_if_fail (c != NULL, FALSE);
|
|
|
|
|
|
|
|
c->blocked = FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gboolean moo_prefs_notify_disconnect (guint id)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
MooPrefs *prefs = instance ();
|
|
|
|
|
|
|
|
g_return_val_if_fail (id != 0, FALSE);
|
|
|
|
|
|
|
|
l = g_hash_table_lookup (prefs->priv->closures_map,
|
|
|
|
GUINT_TO_POINTER (id));
|
|
|
|
g_return_val_if_fail (l != NULL, FALSE);
|
|
|
|
|
|
|
|
g_hash_table_remove (prefs->priv->closures_map,
|
|
|
|
GUINT_TO_POINTER (id));
|
|
|
|
|
|
|
|
closure_free (l->data);
|
|
|
|
prefs->priv->closures =
|
|
|
|
g_list_delete_link (prefs->priv->closures, l);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
void moo_prefs_new_key (const char *key,
|
|
|
|
GType value_type,
|
|
|
|
const GValue *default_value)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
|
|
|
g_return_if_fail (key != NULL);
|
2005-07-28 12:25:10 -07:00
|
|
|
prefs_new_key (instance(), key, value_type, default_value);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
const GValue *moo_prefs_get (const char *key)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
const GValue *val;
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_val_if_fail (key != NULL, NULL);
|
2005-07-29 04:51:36 -07:00
|
|
|
val = prefs_get (instance(), key);
|
|
|
|
return val;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
void moo_prefs_set (const char *key,
|
|
|
|
const GValue *value)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
prefs_set (instance(), key, value);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/* Loading abd saving
|
|
|
|
*/
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void process_element (MooMarkupElement *elm)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
MooMarkupNode *child;
|
|
|
|
gboolean dir = FALSE;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (elm->parent->type == MOO_MARKUP_DOC_NODE)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
dir = TRUE;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
2005-07-28 12:25:10 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for (child = elm->children; child != NULL; child = child->next)
|
|
|
|
if (child->type == MOO_MARKUP_ELEMENT_NODE)
|
|
|
|
dir = TRUE;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!dir)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
char *path;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
path = moo_markup_element_get_path (elm);
|
|
|
|
|
|
|
|
if (strlen (path) < strlen (PREFS_ROOT) + 2)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
g_free (path);
|
|
|
|
g_return_if_reached ();
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
2005-07-28 12:25:10 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
const char *key = path + strlen (PREFS_ROOT) + 1;
|
|
|
|
moo_prefs_set_string (key, elm->content);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
#ifdef DEBUG_READWRITE
|
|
|
|
g_print ("key: '%s', val: '%s'\n", key, elm->content);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
g_free (path);
|
|
|
|
return;
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
for (child = elm->children; child != NULL; child = child->next)
|
|
|
|
if (child->type == MOO_MARKUP_ELEMENT_NODE)
|
|
|
|
process_element (MOO_MARKUP_ELEMENT (child));
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
gboolean moo_prefs_load (const char *file)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
MooMarkupDoc *xml;
|
2005-09-10 07:41:16 -07:00
|
|
|
MooMarkupNode *root;
|
2005-06-22 11:20:32 -07:00
|
|
|
GError *err = NULL;
|
2005-07-29 04:51:36 -07:00
|
|
|
MooPrefs *prefs;
|
2005-08-02 14:53:18 -07:00
|
|
|
char *content;
|
2005-07-29 04:51:36 -07:00
|
|
|
|
|
|
|
prefs = instance ();
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_val_if_fail (file != NULL, FALSE);
|
|
|
|
|
2005-08-02 14:53:18 -07:00
|
|
|
if (!g_file_test (file, G_FILE_TEST_EXISTS))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (!g_file_get_contents (file, &content, NULL, &err))
|
|
|
|
{
|
|
|
|
g_warning ("%s: could not load file '%s'", G_STRLOC, file);
|
|
|
|
g_warning ("%s: %s", G_STRLOC, err->message);
|
|
|
|
g_error_free (err);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
xml = moo_markup_parse_memory (content, -1, &err);
|
|
|
|
g_free (content);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!xml)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-08-02 14:53:18 -07:00
|
|
|
g_warning ("%s: parse error", G_STRLOC);
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (err)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-08-02 14:53:18 -07:00
|
|
|
g_warning ("%s: %s", G_STRLOC, err->message);
|
|
|
|
g_error_free (err);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (prefs->priv->xml)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
g_warning ("%s: implement me", G_STRLOC);
|
|
|
|
moo_markup_doc_unref (prefs->priv->xml);
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
prefs->priv->xml = xml;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
root = moo_markup_get_root_element (xml, PREFS_ROOT);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!root)
|
|
|
|
{
|
|
|
|
g_warning ("%s: no " PREFS_ROOT " element", G_STRLOC);
|
|
|
|
return TRUE;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-09-10 07:41:16 -07:00
|
|
|
process_element (MOO_MARKUP_ELEMENT (root));
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
return TRUE;
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
typedef struct {
|
2005-09-10 07:41:16 -07:00
|
|
|
MooMarkupDoc *xml;
|
|
|
|
MooMarkupNode *root;
|
2005-07-28 12:25:10 -07:00
|
|
|
} Stuff;
|
|
|
|
|
|
|
|
static void write_item (const char *key,
|
|
|
|
PrefsItem *item,
|
|
|
|
Stuff *stuff)
|
|
|
|
{
|
|
|
|
gboolean save = FALSE;
|
|
|
|
const char *string = NULL;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL && key[0] != 0);
|
|
|
|
g_return_if_fail (item != NULL && stuff != NULL);
|
2005-07-29 04:51:36 -07:00
|
|
|
g_return_if_fail (type_is_supported (item->type));
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (item_value (item))
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!item_default_value (item))
|
|
|
|
save = TRUE;
|
|
|
|
else
|
|
|
|
save = !value_equal (item_value (item),
|
|
|
|
item_default_value (item));
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!save)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_READWRITE
|
|
|
|
g_print ("skipping '%s'\n", key);
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
string = convert_to_string (item_value (item));
|
|
|
|
g_return_if_fail (string != NULL);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!stuff->root)
|
|
|
|
stuff->root =
|
|
|
|
moo_markup_create_root_element (stuff->xml, PREFS_ROOT);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (stuff->root != NULL);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-09-10 07:41:16 -07:00
|
|
|
moo_markup_create_text_element (stuff->root, key, string);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
#ifdef DEBUG_READWRITE
|
|
|
|
g_print ("writing key: '%s', val: '%s'\n", key, string);
|
|
|
|
#endif
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
static void sync_xml (void)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
MooPrefs *prefs = instance ();
|
|
|
|
MooMarkupDoc *xml;
|
2005-09-10 07:41:16 -07:00
|
|
|
MooMarkupNode *root;
|
2005-07-28 12:25:10 -07:00
|
|
|
Stuff stuff;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (!prefs->priv->xml)
|
|
|
|
prefs->priv->xml = moo_markup_doc_new ("Prefs");
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
xml = prefs->priv->xml;
|
|
|
|
root = moo_markup_get_root_element (xml, PREFS_ROOT);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (root)
|
2005-09-10 07:41:16 -07:00
|
|
|
moo_markup_delete_node (root);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
stuff.xml = xml;
|
|
|
|
stuff.root = NULL;
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
g_hash_table_foreach (prefs->priv->data,
|
|
|
|
(GHFunc) write_item,
|
|
|
|
&stuff);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
gboolean moo_prefs_save (const char *file)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
MooPrefs *prefs = instance ();
|
|
|
|
MooMarkupDoc *xml;
|
|
|
|
MooMarkupNode *node;
|
|
|
|
gboolean empty;
|
|
|
|
GError *err = NULL;
|
2005-08-01 16:09:31 -07:00
|
|
|
gboolean result = TRUE;
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
g_return_val_if_fail (file != NULL, FALSE);
|
|
|
|
|
|
|
|
sync_xml ();
|
|
|
|
|
|
|
|
xml = prefs->priv->xml;
|
|
|
|
|
|
|
|
g_return_val_if_fail (xml != NULL, FALSE);
|
|
|
|
|
|
|
|
empty = TRUE;
|
|
|
|
for (node = xml->children; empty && node != NULL; node = node->next)
|
|
|
|
if (MOO_MARKUP_IS_ELEMENT (node))
|
|
|
|
empty = FALSE;
|
|
|
|
|
|
|
|
if (empty)
|
2005-08-01 16:09:31 -07:00
|
|
|
{
|
|
|
|
if (g_file_test (file, G_FILE_TEST_EXISTS))
|
|
|
|
if (moo_unlink (file))
|
|
|
|
g_critical ("%s: %s", G_STRLOC,
|
|
|
|
g_strerror (errno));
|
2005-07-28 12:25:10 -07:00
|
|
|
return TRUE;
|
2005-08-01 16:09:31 -07:00
|
|
|
}
|
2005-07-28 12:25:10 -07:00
|
|
|
|
2005-09-08 10:08:31 -07:00
|
|
|
result = moo_markup_save_pretty (xml, file, 2, &err);
|
2005-07-28 12:25:10 -07:00
|
|
|
|
2005-08-01 16:09:31 -07:00
|
|
|
if (!result)
|
|
|
|
g_critical ("%s: could not save preferences to '%s'",
|
2005-07-31 07:53:10 -07:00
|
|
|
G_STRLOC, file);
|
|
|
|
|
2005-08-01 16:09:31 -07:00
|
|
|
if (err)
|
2005-07-28 12:25:10 -07:00
|
|
|
{
|
2005-08-01 16:09:31 -07:00
|
|
|
g_critical ("%s: %s", G_STRLOC, err->message);
|
|
|
|
g_error_free (err);
|
2005-07-28 12:25:10 -07:00
|
|
|
}
|
2005-08-02 14:53:18 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
return result;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/* Helpers
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void moo_prefs_new_key_bool (const char *key,
|
|
|
|
gboolean default_val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
GValue val;
|
|
|
|
|
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
|
|
|
|
val.g_type = 0;
|
|
|
|
g_value_init (&val, G_TYPE_BOOLEAN);
|
|
|
|
g_value_set_boolean (&val, default_val);
|
|
|
|
|
|
|
|
moo_prefs_new_key (key, G_TYPE_BOOLEAN, &val);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
void moo_prefs_new_key_int (const char *key,
|
|
|
|
int default_val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
GValue val;
|
|
|
|
|
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
|
|
|
|
val.g_type = 0;
|
|
|
|
g_value_init (&val, G_TYPE_INT);
|
|
|
|
g_value_set_int (&val, default_val);
|
|
|
|
|
|
|
|
moo_prefs_new_key (key, G_TYPE_INT, &val);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
void moo_prefs_new_key_enum (const char *key,
|
|
|
|
GType enum_type,
|
|
|
|
int default_val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
GValue val;
|
|
|
|
|
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
|
|
|
|
val.g_type = 0;
|
|
|
|
g_value_init (&val, enum_type);
|
|
|
|
g_value_set_enum (&val, default_val);
|
|
|
|
|
|
|
|
moo_prefs_new_key (key, enum_type, &val);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
void moo_prefs_new_key_string (const char *key,
|
|
|
|
const char *default_val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
|
|
|
|
if (default_val)
|
|
|
|
{
|
|
|
|
GValue val;
|
|
|
|
|
|
|
|
val.g_type = 0;
|
|
|
|
g_value_init (&val, G_TYPE_STRING);
|
|
|
|
g_value_set_static_string (&val, default_val);
|
|
|
|
|
|
|
|
moo_prefs_new_key (key, G_TYPE_STRING, &val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
moo_prefs_new_key (key, G_TYPE_STRING, NULL);
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
void moo_prefs_new_key_color (const char *key,
|
|
|
|
const GdkColor *default_val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
|
|
|
|
if (default_val)
|
|
|
|
{
|
|
|
|
GValue val;
|
|
|
|
|
|
|
|
val.g_type = 0;
|
|
|
|
g_value_init (&val, GDK_TYPE_COLOR);
|
|
|
|
g_value_set_boxed (&val, default_val);
|
|
|
|
|
|
|
|
moo_prefs_new_key (key, GDK_TYPE_COLOR, &val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
moo_prefs_new_key (key, GDK_TYPE_COLOR, NULL);
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
const char *moo_prefs_get_string (const char *key)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *val;
|
|
|
|
g_return_val_if_fail (key != NULL, NULL);
|
|
|
|
val = moo_prefs_get (key);
|
|
|
|
if (val)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_VALUE_HOLDS (val, G_TYPE_STRING), NULL);
|
|
|
|
return g_value_get_string (val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
2005-09-07 04:19:26 -07:00
|
|
|
const char *moo_prefs_get_filename (const char *key)
|
|
|
|
{
|
|
|
|
const char *utf8_val;
|
|
|
|
static char *val = NULL;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
utf8_val = moo_prefs_get_string (key);
|
|
|
|
|
|
|
|
if (!utf8_val)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
g_free (val);
|
|
|
|
val = g_filename_from_utf8 (utf8_val, -1, NULL, NULL, &error);
|
|
|
|
|
|
|
|
if (!val)
|
|
|
|
{
|
|
|
|
g_warning ("%s: could not convert '%s' to filename encoding",
|
|
|
|
G_STRLOC, utf8_val);
|
|
|
|
g_warning ("%s: %s", G_STRLOC, error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
gboolean moo_prefs_get_bool (const char *key)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *val;
|
|
|
|
g_return_val_if_fail (key != NULL, FALSE);
|
|
|
|
val = moo_prefs_get (key);
|
|
|
|
if (val)
|
|
|
|
return convert_to_bool (val);
|
|
|
|
else
|
|
|
|
return FALSE;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
gdouble moo_prefs_get_double (const char *key)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *val;
|
|
|
|
g_return_val_if_fail (key != NULL, FALSE);
|
|
|
|
val = moo_prefs_get (key);
|
|
|
|
if (val)
|
|
|
|
return convert_to_double (val);
|
|
|
|
else
|
|
|
|
return 0;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
const GdkColor *moo_prefs_get_color (const char *key)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *val;
|
|
|
|
g_return_val_if_fail (key != NULL, FALSE);
|
|
|
|
val = moo_prefs_get (key);
|
|
|
|
if (val)
|
|
|
|
return convert_to_color (val);
|
|
|
|
else
|
|
|
|
return NULL;
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
int moo_prefs_get_int (const char *key)
|
|
|
|
{
|
|
|
|
const GValue *val;
|
|
|
|
g_return_val_if_fail (key != NULL, FALSE);
|
|
|
|
val = moo_prefs_get (key);
|
|
|
|
if (val)
|
|
|
|
return convert_to_int (val);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int moo_prefs_get_enum (const char *key,
|
|
|
|
GType enum_type)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
const GValue *val;
|
|
|
|
g_return_val_if_fail (key != NULL, FALSE);
|
|
|
|
val = moo_prefs_get (key);
|
|
|
|
if (val)
|
|
|
|
return convert_to_enum (val, enum_type);
|
|
|
|
else
|
|
|
|
g_return_val_if_reached (0);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
void moo_prefs_set_string (const char *key,
|
|
|
|
const char *val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
2005-06-22 11:20:32 -07:00
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
if (val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
GValue gval;
|
|
|
|
gval.g_type = 0;
|
|
|
|
g_value_init (&gval, G_TYPE_STRING);
|
|
|
|
g_value_set_string (&gval, val);
|
|
|
|
moo_prefs_set (key, &gval);
|
|
|
|
g_value_unset (&gval);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-07-28 12:25:10 -07:00
|
|
|
moo_prefs_set (key, NULL);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
2005-09-07 04:19:26 -07:00
|
|
|
void moo_prefs_set_filename (const char *key,
|
|
|
|
const char *val)
|
|
|
|
{
|
|
|
|
char *utf8_val;
|
|
|
|
|
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
|
|
|
|
if (!val)
|
|
|
|
return moo_prefs_set_string (key, NULL);
|
|
|
|
|
|
|
|
utf8_val = g_filename_display_name (val);
|
|
|
|
|
|
|
|
if (!utf8_val)
|
|
|
|
{
|
|
|
|
g_warning ("%s: could not convert '%s' to utf8", G_STRLOC, val);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
moo_prefs_set_string (key, utf8_val);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
void moo_prefs_set_double (const char *key,
|
|
|
|
double val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
static GValue gval;
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
2005-07-29 04:51:36 -07:00
|
|
|
if (!G_IS_VALUE (&gval))
|
|
|
|
g_value_init (&gval, G_TYPE_DOUBLE);
|
2005-07-28 12:25:10 -07:00
|
|
|
g_value_set_double (&gval, val);
|
|
|
|
moo_prefs_set (key, &gval);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
void moo_prefs_set_int (const char *key,
|
|
|
|
int val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
static GValue gval;
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
2005-07-29 04:51:36 -07:00
|
|
|
if (!G_IS_VALUE (&gval))
|
|
|
|
g_value_init (&gval, G_TYPE_INT);
|
2005-07-28 12:25:10 -07:00
|
|
|
g_value_set_int (&gval, val);
|
|
|
|
moo_prefs_set (key, &gval);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
void moo_prefs_set_bool (const char *key,
|
|
|
|
gboolean val)
|
2005-06-22 11:20:32 -07:00
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
static GValue gval;
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
2005-07-29 04:51:36 -07:00
|
|
|
if (!G_IS_VALUE (&gval))
|
|
|
|
g_value_init (&gval, G_TYPE_BOOLEAN);
|
2005-07-28 12:25:10 -07:00
|
|
|
g_value_set_boolean (&gval, val);
|
|
|
|
moo_prefs_set (key, &gval);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
void moo_prefs_set_color (const char *key,
|
2005-06-22 11:20:32 -07:00
|
|
|
const GdkColor *val)
|
|
|
|
{
|
2005-07-29 04:51:36 -07:00
|
|
|
static GValue gval;
|
2005-07-28 12:25:10 -07:00
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
gval.g_type = 0;
|
2005-07-29 04:51:36 -07:00
|
|
|
if (!G_IS_VALUE (&gval))
|
|
|
|
g_value_init (&gval, GDK_TYPE_COLOR);
|
2005-07-28 12:25:10 -07:00
|
|
|
g_value_set_boxed (&gval, val);
|
|
|
|
moo_prefs_set (key, &gval);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void moo_prefs_set_enum (const char *key,
|
|
|
|
GType type,
|
|
|
|
int value)
|
|
|
|
{
|
|
|
|
GValue gval;
|
|
|
|
g_return_if_fail (key != NULL);
|
|
|
|
g_return_if_fail (G_TYPE_IS_ENUM (type));
|
|
|
|
gval.g_type = 0;
|
|
|
|
g_value_init (&gval, type);
|
|
|
|
g_value_set_enum (&gval, value);
|
|
|
|
moo_prefs_set (key, &gval);
|
2005-06-22 11:20:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GType moo_prefs_match_type_get_type (void)
|
|
|
|
{
|
|
|
|
static GType type = 0;
|
|
|
|
|
|
|
|
if (!type)
|
|
|
|
{
|
|
|
|
static const GFlagsValue values[] = {
|
|
|
|
{ MOO_PREFS_MATCH_KEY, (char*)"MOO_PREFS_MATCH_KEY", (char*)"match-key" },
|
|
|
|
{ MOO_PREFS_MATCH_PREFIX, (char*)"MOO_PREFS_MATCH_PREFIX", (char*)"match-prefix" },
|
|
|
|
{ MOO_PREFS_MATCH_REGEX, (char*)"MOO_PREFS_MATCH_REGEX", (char*)"match-regex" },
|
|
|
|
{ 0, NULL, NULL }
|
|
|
|
};
|
|
|
|
type = g_flags_register_static ("MooPrefsMatchType", values);
|
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
2005-07-28 12:25:10 -07:00
|
|
|
|
|
|
|
|
|
|
|
static gboolean convert_to_bool (const GValue *val)
|
|
|
|
{
|
|
|
|
GValue result;
|
|
|
|
result.g_type = 0;
|
|
|
|
g_value_init (&result, G_TYPE_BOOLEAN);
|
|
|
|
g_return_val_if_fail (convert_value (val, &result), FALSE);
|
|
|
|
return g_value_get_boolean (&result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int convert_to_int (const GValue *val)
|
|
|
|
{
|
|
|
|
GValue result;
|
|
|
|
result.g_type = 0;
|
|
|
|
g_value_init (&result, G_TYPE_INT);
|
|
|
|
g_return_val_if_fail (convert_value (val, &result), 0);
|
|
|
|
return g_value_get_int (&result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int convert_to_enum (const GValue *val,
|
|
|
|
GType enum_type)
|
|
|
|
{
|
|
|
|
GValue result;
|
|
|
|
result.g_type = 0;
|
|
|
|
g_value_init (&result, enum_type);
|
|
|
|
g_return_val_if_fail (convert_value (val, &result), 0);
|
|
|
|
return g_value_get_enum (&result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static double convert_to_double (const GValue *val)
|
|
|
|
{
|
|
|
|
GValue result;
|
|
|
|
result.g_type = 0;
|
|
|
|
g_value_init (&result, G_TYPE_DOUBLE);
|
|
|
|
g_return_val_if_fail (convert_value (val, &result), 0);
|
|
|
|
return g_value_get_double (&result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const GdkColor *convert_to_color (const GValue *val)
|
|
|
|
{
|
|
|
|
static GdkColor color;
|
|
|
|
GdkColor *c_result;
|
|
|
|
GValue result;
|
|
|
|
result.g_type = 0;
|
|
|
|
g_value_init (&result, GDK_TYPE_COLOR);
|
|
|
|
g_return_val_if_fail (convert_value (val, &result), NULL);
|
|
|
|
c_result = g_value_get_boxed (&result);
|
|
|
|
g_return_val_if_fail (c_result != NULL, NULL);
|
|
|
|
color = *c_result;
|
|
|
|
g_value_unset (&result);
|
|
|
|
return &color;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *convert_to_string (const GValue *val)
|
|
|
|
{
|
|
|
|
static GValue result;
|
|
|
|
if (G_IS_VALUE (&result))
|
|
|
|
g_value_unset (&result);
|
|
|
|
g_value_init (&result, G_TYPE_STRING);
|
|
|
|
g_return_val_if_fail (convert_value (val, &result), NULL);
|
|
|
|
return g_value_get_string (&result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean type_is_supported (GType type)
|
|
|
|
{
|
|
|
|
if (!type)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return type == G_TYPE_BOOLEAN ||
|
|
|
|
type == G_TYPE_INT ||
|
|
|
|
type == G_TYPE_DOUBLE ||
|
|
|
|
type == G_TYPE_STRING ||
|
|
|
|
type == GDK_TYPE_COLOR ||
|
|
|
|
G_TYPE_IS_ENUM (type);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int value_equal (const GValue *a,
|
|
|
|
const GValue *b)
|
|
|
|
{
|
|
|
|
GType type;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_VALUE (a) && G_IS_VALUE (b), a == b);
|
|
|
|
g_return_val_if_fail (G_VALUE_TYPE (a) == G_VALUE_TYPE (b), a == b);
|
|
|
|
g_return_val_if_fail (G_VALUE_TYPE (a) == G_VALUE_TYPE (b), a == b);
|
|
|
|
|
|
|
|
type = G_VALUE_TYPE (a);
|
|
|
|
|
|
|
|
if (type == G_TYPE_BOOLEAN)
|
|
|
|
{
|
|
|
|
gboolean ba = g_value_get_boolean (a);
|
|
|
|
gboolean bb = g_value_get_boolean (b);
|
|
|
|
return (ba && bb) || (!ba && !bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == G_TYPE_INT)
|
|
|
|
return g_value_get_int (a) == g_value_get_int (b);
|
|
|
|
|
|
|
|
if (type == G_TYPE_DOUBLE)
|
|
|
|
return g_value_get_double (a) == g_value_get_double (b);
|
|
|
|
|
|
|
|
if (type == G_TYPE_STRING)
|
|
|
|
{
|
|
|
|
const char *sa, *sb;
|
|
|
|
sa = g_value_get_string (a);
|
|
|
|
sb = g_value_get_string (b);
|
|
|
|
if (!sa || !sb)
|
|
|
|
return sa == sb;
|
|
|
|
else
|
|
|
|
return !strcmp (sa, sb);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type == GDK_TYPE_COLOR)
|
|
|
|
{
|
|
|
|
const GdkColor *ca, *cb;
|
|
|
|
ca = g_value_get_boxed (a);
|
|
|
|
cb = g_value_get_boxed (b);
|
|
|
|
if (!ca || !cb)
|
|
|
|
return ca == cb;
|
|
|
|
else
|
|
|
|
return ca->red == cb->red &&
|
|
|
|
ca->green == cb->green &&
|
|
|
|
ca->blue == cb->blue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_TYPE_IS_ENUM (type))
|
|
|
|
return g_value_get_enum (a) == g_value_get_enum (b);
|
|
|
|
|
|
|
|
g_return_val_if_reached (a == b);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean convert_value (const GValue *src,
|
|
|
|
GValue *dest)
|
|
|
|
{
|
|
|
|
GType src_type, dest_type;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_VALUE (src) && G_IS_VALUE (dest), FALSE);
|
|
|
|
|
|
|
|
src_type = G_VALUE_TYPE (src);
|
|
|
|
dest_type = G_VALUE_TYPE (dest);
|
|
|
|
|
|
|
|
g_return_val_if_fail (type_is_supported (src_type), FALSE);
|
|
|
|
g_return_val_if_fail (type_is_supported (dest_type), FALSE);
|
|
|
|
|
|
|
|
if (src_type == dest_type)
|
|
|
|
{
|
|
|
|
g_value_copy (src, dest);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dest_type == G_TYPE_STRING)
|
|
|
|
{
|
|
|
|
if (src_type == G_TYPE_BOOLEAN)
|
|
|
|
{
|
|
|
|
const char *string =
|
|
|
|
g_value_get_boolean (src) ? "TRUE" : "FALSE";
|
|
|
|
g_value_set_static_string (dest, string);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_type == G_TYPE_DOUBLE)
|
|
|
|
{
|
|
|
|
char *string =
|
|
|
|
g_strdup_printf ("%f", g_value_get_double (src));
|
|
|
|
g_value_take_string (dest, string);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_type == G_TYPE_INT)
|
|
|
|
{
|
|
|
|
char *string =
|
|
|
|
g_strdup_printf ("%d", g_value_get_int (src));
|
|
|
|
g_value_take_string (dest, string);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_type == GDK_TYPE_COLOR)
|
|
|
|
{
|
|
|
|
char string[14];
|
|
|
|
const GdkColor *color = g_value_get_boxed (src);
|
|
|
|
|
|
|
|
if (!color)
|
|
|
|
{
|
|
|
|
g_value_set_string (dest, NULL);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_snprintf (string, 8, "#%02x%02x%02x",
|
|
|
|
color->red >> 8,
|
|
|
|
color->green >> 8,
|
|
|
|
color->blue >> 8);
|
|
|
|
g_value_set_string (dest, string);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_TYPE_IS_ENUM (src_type))
|
|
|
|
{
|
|
|
|
gpointer klass;
|
|
|
|
GEnumClass *enum_class;
|
|
|
|
GEnumValue *enum_value;
|
|
|
|
|
|
|
|
klass = g_type_class_ref (src_type);
|
|
|
|
g_return_val_if_fail (G_IS_ENUM_CLASS (klass), FALSE);
|
|
|
|
enum_class = G_ENUM_CLASS (klass);
|
|
|
|
|
|
|
|
enum_value = g_enum_get_value (enum_class,
|
|
|
|
g_value_get_enum (src));
|
|
|
|
|
|
|
|
if (!enum_value)
|
|
|
|
{
|
|
|
|
char *string = g_strdup_printf ("%d", g_value_get_enum (src));
|
|
|
|
g_value_take_string (dest, string);
|
|
|
|
g_type_class_unref (klass);
|
|
|
|
g_return_val_if_reached (TRUE);
|
|
|
|
}
|
|
|
|
|
2005-07-29 04:51:36 -07:00
|
|
|
g_value_set_static_string (dest, enum_value->value_nick);
|
2005-07-28 12:25:10 -07:00
|
|
|
g_type_class_unref (klass);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_type == G_TYPE_STRING)
|
|
|
|
{
|
|
|
|
const char *string = g_value_get_string (src);
|
|
|
|
|
|
|
|
if (dest_type == G_TYPE_BOOLEAN)
|
|
|
|
{
|
|
|
|
if (!string)
|
|
|
|
g_value_set_boolean (dest, FALSE);
|
|
|
|
else
|
|
|
|
g_value_set_boolean (dest,
|
|
|
|
! g_ascii_strcasecmp (string, "1") ||
|
|
|
|
! g_ascii_strcasecmp (string, "yes") ||
|
|
|
|
! g_ascii_strcasecmp (string, "true"));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dest_type == G_TYPE_DOUBLE)
|
|
|
|
{
|
|
|
|
if (!string)
|
|
|
|
g_value_set_double (dest, 0);
|
|
|
|
else
|
|
|
|
g_value_set_double (dest, g_ascii_strtod (string, NULL));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dest_type == G_TYPE_INT)
|
|
|
|
{
|
|
|
|
if (!string)
|
|
|
|
g_value_set_int (dest, 0);
|
|
|
|
else
|
|
|
|
g_value_set_int (dest, g_ascii_strtod (string, NULL));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dest_type == GDK_TYPE_COLOR)
|
|
|
|
{
|
|
|
|
GdkColor color;
|
|
|
|
|
|
|
|
if (!string)
|
|
|
|
{
|
|
|
|
g_value_set_boxed (dest, NULL);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_fail (gdk_color_parse (string, &color),
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
g_value_set_boxed (dest, &color);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_TYPE_IS_ENUM (dest_type))
|
|
|
|
{
|
|
|
|
gpointer klass;
|
|
|
|
GEnumClass *enum_class;
|
|
|
|
GEnumValue *enum_value;
|
|
|
|
int ival;
|
|
|
|
|
|
|
|
if (!string || !string[0])
|
|
|
|
{
|
|
|
|
g_value_set_enum (dest, 0);
|
|
|
|
g_return_val_if_reached (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
klass = g_type_class_ref (dest_type);
|
|
|
|
g_return_val_if_fail (G_IS_ENUM_CLASS (klass), FALSE);
|
|
|
|
enum_class = G_ENUM_CLASS (klass);
|
|
|
|
|
|
|
|
enum_value = g_enum_get_value_by_name (enum_class, string);
|
|
|
|
if (!enum_value)
|
|
|
|
enum_value = g_enum_get_value_by_nick (enum_class, string);
|
|
|
|
|
|
|
|
if (enum_value)
|
|
|
|
{
|
|
|
|
ival = enum_value->value;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ival = g_ascii_strtod (string, NULL);
|
|
|
|
|
|
|
|
if (ival < enum_class->minimum || ival > enum_class->maximum)
|
|
|
|
{
|
|
|
|
g_value_set_enum (dest, ival);
|
|
|
|
g_type_class_unref (klass);
|
|
|
|
g_return_val_if_reached (TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_value_set_enum (dest, ival);
|
|
|
|
g_type_class_unref (klass);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_TYPE_IS_ENUM (src_type) && dest_type == G_TYPE_INT)
|
|
|
|
{
|
|
|
|
g_value_set_int (dest, g_value_get_enum (src));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_TYPE_IS_ENUM (dest_type) && src_type == G_TYPE_INT)
|
|
|
|
{
|
|
|
|
g_value_set_enum (dest, g_value_get_int (src));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_type == G_TYPE_DOUBLE && dest_type == G_TYPE_INT)
|
|
|
|
{
|
|
|
|
g_value_set_int (dest, g_value_get_double (src));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dest_type == G_TYPE_DOUBLE && src_type == G_TYPE_INT)
|
|
|
|
{
|
|
|
|
g_value_set_double (dest, g_value_get_int (src));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
}
|