summaryrefslogtreecommitdiff
path: root/libpurple/prefs.c
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2016-08-19 23:03:37 -0500
committerGary Kramlich <grim@reaperworld.com>2016-08-19 23:03:37 -0500
commitc7b9962bf16de217464db64fe4318f36c8a71566 (patch)
tree0a4f3f57c4561f50ddd62a649835836a14806cf3 /libpurple/prefs.c
parentcd5969e35b2d75deae9e199b9289baa2096fa5f6 (diff)
parentb1909cbe71f04e3b52f2718101eecf1af24cf289 (diff)
downloadpidgin-c7b9962bf16de217464db64fe4318f36c8a71566.tar.gz
Monster merge everything
Diffstat (limited to 'libpurple/prefs.c')
-rw-r--r--libpurple/prefs.c385
1 files changed, 347 insertions, 38 deletions
diff --git a/libpurple/prefs.c b/libpurple/prefs.c
index e1be5a113f..9d7a9a5508 100644
--- a/libpurple/prefs.c
+++ b/libpurple/prefs.c
@@ -40,6 +40,8 @@ struct pref_cb {
gpointer data;
guint id;
void *handle;
+ void *ui_data;
+ char *name;
};
/* TODO: This should use PurpleValues? */
@@ -78,6 +80,24 @@ static struct purple_pref prefs = {
static GHashTable *prefs_hash = NULL;
static guint save_timer = 0;
static gboolean prefs_loaded = FALSE;
+static GSList *ui_callbacks = NULL;
+
+#define PURPLE_PREFS_UI_OP_CALL(member, ...) \
+ { \
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); \
+ if (uiop && uiop->member) { \
+ uiop->member(__VA_ARGS__); \
+ return; \
+ } \
+ }
+
+#define PURPLE_PREFS_UI_OP_CALL_RETURN(member, ...) \
+ { \
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); \
+ if (uiop && uiop->member) { \
+ return uiop->member(__VA_ARGS__); \
+ } \
+ }
/*********************************************************************
@@ -207,6 +227,8 @@ sync_prefs(void)
return;
}
+ PURPLE_PREFS_UI_OP_CALL(save);
+
node = prefs_to_xmlnode();
data = purple_xmlnode_to_formatted_str(node, NULL);
purple_util_write_data_to_file("prefs.xml", data, -1);
@@ -225,6 +247,8 @@ save_cb(gpointer data)
static void
schedule_prefs_save(void)
{
+ PURPLE_PREFS_UI_OP_CALL(schedule_save);
+
if (save_timer == 0)
save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
}
@@ -376,12 +400,21 @@ static GMarkupParser prefs_parser = {
gboolean
purple_prefs_load()
{
- gchar *filename = g_build_filename(purple_user_dir(), "prefs.xml", NULL);
+ gchar *filename;
gchar *contents = NULL;
gsize length;
GMarkupParseContext *context;
GError *error = NULL;
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+ if (uiop && uiop->load) {
+ prefs_loaded = TRUE;
+ return uiop->load();
+ }
+
+ filename = g_build_filename(purple_user_dir(), "prefs.xml", NULL);
+
if (!filename) {
prefs_loaded = TRUE;
return FALSE;
@@ -603,13 +636,19 @@ add_pref(PurplePrefType type, const char *name)
void
purple_prefs_add_none(const char *name)
{
+ PURPLE_PREFS_UI_OP_CALL(add_none, name);
+
add_pref(PURPLE_PREF_NONE, name);
}
void
purple_prefs_add_bool(const char *name, gboolean value)
{
- struct purple_pref *pref = add_pref(PURPLE_PREF_BOOLEAN, name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(add_bool, name, value);
+
+ pref = add_pref(PURPLE_PREF_BOOLEAN, name);
if(!pref)
return;
@@ -620,7 +659,11 @@ purple_prefs_add_bool(const char *name, gboolean value)
void
purple_prefs_add_int(const char *name, int value)
{
- struct purple_pref *pref = add_pref(PURPLE_PREF_INT, name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(add_int, name, value);
+
+ pref = add_pref(PURPLE_PREF_INT, name);
if(!pref)
return;
@@ -638,6 +681,8 @@ purple_prefs_add_string(const char *name, const char *value)
return;
}
+ PURPLE_PREFS_UI_OP_CALL(add_string, name, value);
+
pref = add_pref(PURPLE_PREF_STRING, name);
if(!pref)
@@ -649,9 +694,13 @@ purple_prefs_add_string(const char *name, const char *value)
void
purple_prefs_add_string_list(const char *name, GList *value)
{
- struct purple_pref *pref = add_pref(PURPLE_PREF_STRING_LIST, name);
+ struct purple_pref *pref;
GList *tmp;
+ PURPLE_PREFS_UI_OP_CALL(add_string_list, name, value);
+
+ pref = add_pref(PURPLE_PREF_STRING_LIST, name);
+
if(!pref)
return;
@@ -668,7 +717,12 @@ purple_prefs_add_string_list(const char *name, GList *value)
void
purple_prefs_add_path(const char *name, const char *value)
{
- struct purple_pref *pref = add_pref(PURPLE_PREF_PATH, name);
+ struct purple_pref *pref;
+
+ /* re-use the string UI OP */
+ PURPLE_PREFS_UI_OP_CALL(add_string, name, value);
+
+ pref = add_pref(PURPLE_PREF_PATH, name);
if(!pref)
return;
@@ -679,9 +733,14 @@ purple_prefs_add_path(const char *name, const char *value)
void
purple_prefs_add_path_list(const char *name, GList *value)
{
- struct purple_pref *pref = add_pref(PURPLE_PREF_PATH_LIST, name);
+ struct purple_pref *pref;
GList *tmp;
+ /* re-use the string list UI OP */
+ PURPLE_PREFS_UI_OP_CALL(add_string_list, name, value);
+
+ pref = add_pref(PURPLE_PREF_PATH_LIST, name);
+
if(!pref)
return;
@@ -738,7 +797,11 @@ remove_pref(struct purple_pref *pref)
void
purple_prefs_remove(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(remove, name);
+
+ pref = find_pref(name);
if(!pref)
return;
@@ -759,16 +822,51 @@ do_callbacks(const char* name, struct purple_pref *pref)
struct purple_pref *cb_pref;
for(cb_pref = pref; cb_pref; cb_pref = cb_pref->parent) {
for(cbs = cb_pref->callbacks; cbs; cbs = cbs->next) {
- struct pref_cb *cb = cbs->data;
+ PurplePrefCallbackData *cb = cbs->data;
cb->func(name, pref->type, pref->value.generic, cb->data);
}
}
}
+static void
+do_ui_callbacks(const char *name)
+{
+ GSList *cbs;
+
+ purple_debug_misc("prefs", "trigger callback %s\n", name);
+
+ for (cbs = ui_callbacks; cbs; cbs = cbs->next) {
+ PurplePrefCallbackData *cb = cbs->data;
+ const char *cb_name = cb->name;
+ size_t len = strlen(cb_name);
+ if (!strncmp(cb_name, name, len) &&
+ (name[len] == 0 || name[len] == '/' ||
+ (len && name[len - 1] == '/'))) {
+ /* This test should behave like this:
+ * name = /toto/tata
+ * cb_name = /toto/tata --> true
+ * cb_name = /toto/tatatiti --> false
+ * cb_name = / --> true
+ * cb_name = /toto --> true
+ * cb_name = /toto/ --> true
+ */
+ purple_prefs_trigger_callback_object(cbs->data);
+ }
+ }
+}
+
void
purple_prefs_trigger_callback(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+ if (uiop && uiop->connect_callback) {
+ do_ui_callbacks(name);
+ return;
+ }
+
+ pref = find_pref(name);
if(!pref) {
purple_debug_error("prefs",
@@ -779,10 +877,15 @@ purple_prefs_trigger_callback(const char *name)
do_callbacks(name, pref);
}
+/* this function is deprecated, so it doesn't get the new UI ops */
void
purple_prefs_set_bool(const char *name, gboolean value)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(set_bool, name, value);
+
+ pref = find_pref(name);
if(pref) {
if(pref->type != PURPLE_PREF_BOOLEAN) {
@@ -803,7 +906,11 @@ purple_prefs_set_bool(const char *name, gboolean value)
void
purple_prefs_set_int(const char *name, int value)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(set_int, name, value);
+
+ pref = find_pref(name);
if(pref) {
if(pref->type != PURPLE_PREF_INT) {
@@ -824,13 +931,17 @@ purple_prefs_set_int(const char *name, int value)
void
purple_prefs_set_string(const char *name, const char *value)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
if(value != NULL && !g_utf8_validate(value, -1, NULL)) {
purple_debug_error("prefs", "purple_prefs_set_string: Cannot store invalid UTF8 for string pref %s\n", name);
return;
}
+ PURPLE_PREFS_UI_OP_CALL(set_string, name, value);
+
+ pref = find_pref(name);
+
if(pref) {
if(pref->type != PURPLE_PREF_STRING && pref->type != PURPLE_PREF_PATH) {
purple_debug_error("prefs",
@@ -851,7 +962,12 @@ purple_prefs_set_string(const char *name, const char *value)
void
purple_prefs_set_string_list(const char *name, GList *value)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(set_string_list, name, value);
+
+ pref = find_pref(name);
+
if(pref) {
GList *tmp;
@@ -886,7 +1002,11 @@ purple_prefs_set_string_list(const char *name, GList *value)
void
purple_prefs_set_path(const char *name, const char *value)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(set_string, name, value);
+
+ pref = find_pref(name);
if(pref) {
if(pref->type != PURPLE_PREF_PATH) {
@@ -908,7 +1028,12 @@ purple_prefs_set_path(const char *name, const char *value)
void
purple_prefs_set_path_list(const char *name, GList *value)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL(set_string_list, name, value);
+
+ pref = find_pref(name);
+
if(pref) {
GList *tmp;
@@ -939,7 +1064,11 @@ purple_prefs_set_path_list(const char *name, GList *value)
gboolean
purple_prefs_exists(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL_RETURN(exists, name);
+
+ pref = find_pref(name);
if (pref != NULL)
return TRUE;
@@ -950,7 +1079,11 @@ purple_prefs_exists(const char *name)
PurplePrefType
purple_prefs_get_pref_type(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_type, name);
+
+ pref = find_pref(name);
if (pref == NULL)
return PURPLE_PREF_NONE;
@@ -961,7 +1094,11 @@ purple_prefs_get_pref_type(const char *name)
gboolean
purple_prefs_get_bool(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_bool, name);
+
+ pref = find_pref(name);
if(!pref) {
purple_debug_error("prefs",
@@ -979,7 +1116,11 @@ purple_prefs_get_bool(const char *name)
int
purple_prefs_get_int(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_int, name);
+
+ pref = find_pref(name);
if(!pref) {
purple_debug_error("prefs",
@@ -997,7 +1138,11 @@ purple_prefs_get_int(const char *name)
const char *
purple_prefs_get_string(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_string, name);
+
+ pref = find_pref(name);
if(!pref) {
purple_debug_error("prefs",
@@ -1015,9 +1160,13 @@ purple_prefs_get_string(const char *name)
GList *
purple_prefs_get_string_list(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
GList *ret = NULL, *tmp;
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_string_list, name);
+
+ pref = find_pref(name);
+
if(!pref) {
purple_debug_error("prefs",
"purple_prefs_get_string_list: Unknown pref %s\n", name);
@@ -1038,7 +1187,11 @@ purple_prefs_get_string_list(const char *name)
const char *
purple_prefs_get_path(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
+
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_string, name);
+
+ pref = find_pref(name);
if(!pref) {
purple_debug_error("prefs",
@@ -1056,9 +1209,13 @@ purple_prefs_get_path(const char *name)
GList *
purple_prefs_get_path_list(const char *name)
{
- struct purple_pref *pref = find_pref(name);
+ struct purple_pref *pref;
GList *ret = NULL, *tmp;
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_string_list, name);
+
+ pref = find_pref(name);
+
if(!pref) {
purple_debug_error("prefs",
"purple_prefs_get_path_list: Unknown pref %s\n", name);
@@ -1149,6 +1306,13 @@ purple_prefs_rename(const char *oldname, const char *newname)
{
struct purple_pref *oldpref, *newpref;
+/* win32dep.h causes rename to be defined as wpurple_rename, so we need to undefine it here */
+#if defined(_WIN32) && defined(rename)
+#undef rename
+#endif
+
+ PURPLE_PREFS_UI_OP_CALL(rename, oldname, newname);
+
oldpref = find_pref(oldname);
/* it's already been renamed, call off the dogs */
@@ -1171,6 +1335,8 @@ purple_prefs_rename_boolean_toggle(const char *oldname, const char *newname)
{
struct purple_pref *oldpref, *newpref;
+ PURPLE_PREFS_UI_OP_CALL(rename_boolean_toggle, oldname, newname);
+
oldpref = find_pref(oldname);
/* it's already been renamed, call off the cats */
@@ -1213,31 +1379,103 @@ purple_prefs_rename_boolean_toggle(const char *oldname, const char *newname)
guint
purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data)
{
- struct purple_pref *pref;
- struct pref_cb *cb;
+ struct purple_pref *pref = NULL;
+ PurplePrefCallbackData *cb;
static guint cb_id = 0;
+ PurplePrefsUiOps *uiop = NULL;
g_return_val_if_fail(name != NULL, 0);
g_return_val_if_fail(func != NULL, 0);
- pref = find_pref(name);
- if (pref == NULL) {
- purple_debug_error("prefs", "purple_prefs_connect_callback: Unknown pref %s\n", name);
- return 0;
+ uiop = purple_prefs_get_ui_ops();
+
+ if (!(uiop && uiop->connect_callback)) {
+ pref = find_pref(name);
+ if (pref == NULL) {
+ purple_debug_error("prefs", "purple_prefs_connect_callback: Unknown pref %s\n", name);
+ return 0;
+ }
}
- cb = g_new0(struct pref_cb, 1);
+ cb = g_new0(PurplePrefCallbackData, 1);
cb->func = func;
cb->data = data;
cb->id = ++cb_id;
cb->handle = handle;
+ cb->name = g_strdup(name);
- pref->callbacks = g_slist_append(pref->callbacks, cb);
+ if (uiop && uiop->connect_callback) {
+ cb->ui_data = uiop->connect_callback(name, cb);
+
+ if (cb->ui_data == NULL) {
+ purple_debug_error("prefs", "purple_prefs_connect_callback: connect failed for %s\n", name);
+ g_free(cb->name);
+ g_free(cb);
+ return 0;
+ }
+
+ ui_callbacks = g_slist_append(ui_callbacks, cb);
+ } else {
+ pref->callbacks = g_slist_append(pref->callbacks, cb);
+ }
return cb->id;
}
+static void
+purple_prefs_trigger_ui_callback_object(PurplePrefCallbackData *cb)
+{
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+ gconstpointer value = NULL;
+ PurplePrefType type = PURPLE_PREF_NONE;
+
+ type = uiop->get_type(cb->name);
+
+ switch (type) {
+ case PURPLE_PREF_INT:
+ if (uiop->get_int) {
+ value = GINT_TO_POINTER(uiop->get_int(cb->name));
+ }
+ break;
+ case PURPLE_PREF_BOOLEAN:
+ if (uiop->get_bool) {
+ value = GINT_TO_POINTER(uiop->get_bool(cb->name));
+ }
+ break;
+ case PURPLE_PREF_STRING:
+ case PURPLE_PREF_PATH:
+ if (uiop->get_string) {
+ value = uiop->get_string(cb->name);
+ }
+ break;
+ case PURPLE_PREF_STRING_LIST:
+ case PURPLE_PREF_PATH_LIST:
+ if (uiop->get_string_list) {
+ value = uiop->get_string_list(cb->name);
+ }
+ break;
+ case PURPLE_PREF_NONE:
+ break;
+ default:
+ purple_debug_error("prefs", "Unexpected type = %i\n", type);
+ }
+
+ cb->func(cb->name, type, value, cb->data);
+}
+
+void
+purple_prefs_trigger_callback_object(PurplePrefCallbackData *cb)
+{
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+ if (uiop && uiop->connect_callback && uiop->get_type) {
+ purple_prefs_trigger_ui_callback_object(cb);
+ } else {
+ purple_prefs_trigger_callback(cb->name);
+ }
+}
+
static gboolean
disco_callback_helper(struct purple_pref *pref, guint callback_id)
{
@@ -1248,9 +1486,10 @@ disco_callback_helper(struct purple_pref *pref, guint callback_id)
return FALSE;
for(cbs = pref->callbacks; cbs; cbs = cbs->next) {
- struct pref_cb *cb = cbs->data;
+ PurplePrefCallbackData *cb = cbs->data;
if(cb->id == callback_id) {
pref->callbacks = g_slist_delete_link(pref->callbacks, cbs);
+ g_free(cb->name);
g_free(cb);
return TRUE;
}
@@ -1264,10 +1503,35 @@ disco_callback_helper(struct purple_pref *pref, guint callback_id)
return FALSE;
}
+static void
+disco_ui_callback_helper(guint callback_id)
+{
+ GSList *cbs;
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+ for (cbs = ui_callbacks; cbs; cbs = cbs->next) {
+ PurplePrefCallbackData *cb = cbs->data;
+ if (cb->id == callback_id) {
+ uiop->disconnect_callback(cb->name, cb->ui_data);
+
+ ui_callbacks = g_slist_delete_link(ui_callbacks, cbs);
+ g_free(cb->name);
+ g_free(cb);
+ return;
+ }
+ }
+}
+
void
purple_prefs_disconnect_callback(guint callback_id)
{
- disco_callback_helper(&prefs, callback_id);
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+ if (uiop && uiop->disconnect_callback) {
+ disco_ui_callback_helper(callback_id);
+ } else {
+ disco_callback_helper(&prefs, callback_id);
+ }
}
static void
@@ -1281,9 +1545,10 @@ disco_callback_helper_handle(struct purple_pref *pref, void *handle)
cbs = pref->callbacks;
while (cbs != NULL) {
- struct pref_cb *cb = cbs->data;
+ PurplePrefCallbackData *cb = cbs->data;
if(cb->handle == handle) {
pref->callbacks = g_slist_delete_link(pref->callbacks, cbs);
+ g_free(cb->name);
g_free(cb);
cbs = pref->callbacks;
} else
@@ -1294,21 +1559,54 @@ disco_callback_helper_handle(struct purple_pref *pref, void *handle)
disco_callback_helper_handle(child, handle);
}
+static void
+disco_ui_callback_helper_handle(void *handle)
+{
+ GSList *cbs;
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
+ cbs = ui_callbacks;
+ for (cbs = ui_callbacks; cbs; cbs = cbs->next) {
+ PurplePrefCallbackData *cb = cbs->data;
+ if (cb->handle != handle) {
+ cbs = cbs->next;
+ continue;
+ }
+
+ uiop->disconnect_callback(cb->name, cb->ui_data);
+
+ ui_callbacks = g_slist_delete_link(ui_callbacks, cbs);
+ g_free(cb->name);
+ g_free(cb);
+ cbs = ui_callbacks;
+ }
+}
+
void
purple_prefs_disconnect_by_handle(void *handle)
{
+ PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops();
+
g_return_if_fail(handle != NULL);
- disco_callback_helper_handle(&prefs, handle);
+ if (uiop && uiop->disconnect_callback) {
+ disco_ui_callback_helper_handle(handle);
+ } else {
+ disco_callback_helper_handle(&prefs, handle);
+ }
}
GList *
purple_prefs_get_children_names(const char *name)
{
GList * list = NULL;
- struct purple_pref *pref = find_pref(name), *child;
+ struct purple_pref *pref, *child;
char sep[2] = "\0\0";;
+ PURPLE_PREFS_UI_OP_CALL_RETURN(get_children_names, name);
+
+ pref = find_pref(name);
+
if (pref == NULL)
return NULL;
@@ -1435,8 +1733,7 @@ purple_prefs_uninit()
if (save_timer != 0)
{
purple_timeout_remove(save_timer);
- save_timer = 0;
- sync_prefs();
+ save_cb(NULL);
}
purple_prefs_disconnect_by_handle(purple_prefs_get_handle());
@@ -1447,3 +1744,15 @@ purple_prefs_uninit()
prefs_hash = NULL;
}
+
+void
+purple_prefs_set_ui_ops(PurplePrefsUiOps *ops)
+{
+ prefs_ui_ops = ops;
+}
+
+PurplePrefsUiOps *
+purple_prefs_get_ui_ops(void)
+{
+ return prefs_ui_ops;
+}