diff options
author | Gary Kramlich <grim@reaperworld.com> | 2016-08-19 23:03:37 -0500 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2016-08-19 23:03:37 -0500 |
commit | c7b9962bf16de217464db64fe4318f36c8a71566 (patch) | |
tree | 0a4f3f57c4561f50ddd62a649835836a14806cf3 /libpurple/prefs.c | |
parent | cd5969e35b2d75deae9e199b9289baa2096fa5f6 (diff) | |
parent | b1909cbe71f04e3b52f2718101eecf1af24cf289 (diff) | |
download | pidgin-c7b9962bf16de217464db64fe4318f36c8a71566.tar.gz |
Monster merge everything
Diffstat (limited to 'libpurple/prefs.c')
-rw-r--r-- | libpurple/prefs.c | 385 |
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; +} |