diff -r 35db38affc9f libpurple/prefs.c --- a/libpurple/prefs.c Wed Jun 15 22:40:26 2016 -0300 +++ b/libpurple/prefs.c Thu Jun 16 02:17:54 2016 -0300 @@ -44,12 +44,12 @@ static PurplePrefsUiOps *prefs_ui_ops = NULL; -struct pref_cb { +struct _PurplePrefCallbackData { PurplePrefCallback func; gpointer data; guint id; void *handle; - void *observer; + void *ui_data; char *name; }; @@ -84,7 +84,7 @@ static GHashTable *prefs_hash = NULL; static guint save_timer = 0; static gboolean prefs_loaded = FALSE; -static GSList *callbacks = NULL; +static GSList *ui_callbacks = NULL; #define PURPLE_PREFS_UI_OP_CALL(member, ...) \ { \ @@ -828,21 +828,22 @@ 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); } } } -void -purple_prefs_trigger_callback(const char *name) +static void +do_ui_callbacks(const char *name) { GSList *cbs; purple_debug_misc("prefs", "trigger callback %s\n", name); - for (cbs = callbacks; cbs; cbs = cbs->next) { - const char *cb_name = ((struct pref_cb *)cbs->data)->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] == '/' || @@ -855,11 +856,33 @@ * cb_name = /toto --> true * cb_name = /toto/ --> true */ - purple_prefs_observe(cbs->data); + purple_prefs_trigger_callback_object(cbs->data); } } } +void +purple_prefs_trigger_callback(const char *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", + "purple_prefs_trigger_callback: Unknown pref %s\n", name); + return; + } + + do_callbacks(name, pref); +} + /* this function is deprecated, so it doesn't get the new UI ops */ void purple_prefs_set_generic(const char *name, gpointer value) @@ -1372,7 +1395,8 @@ guint purple_prefs_connect_callback(void *handle, const char *name, PurplePrefCallback func, gpointer data) { - struct pref_cb *cb; + struct purple_pref *pref = NULL; + PurplePrefCallbackData *cb; static guint cb_id = 0; PurplePrefsUiOps *uiop = NULL; @@ -1380,9 +1404,16 @@ g_return_val_if_fail(func != NULL, 0); uiop = purple_prefs_get_ui_ops(); - g_return_val_if_fail(uiop, 0); - cb = g_new0(struct pref_cb, 1); + 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(PurplePrefCallbackData, 1); cb->func = func; cb->data = data; @@ -1390,47 +1421,77 @@ cb->handle = handle; cb->name = g_strdup(name); - cb->observer = uiop->add_observer(name, cb); + if (uiop && uiop->connect_callback) { + cb->ui_data = uiop->connect_callback(name, cb); - if (cb->observer == NULL) { - purple_debug_error("prefs", "purple_prefs_connect_callback: add observer failed for %s\n", name); - g_free(cb->name); - g_free(cb); - return 0; + 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); } - callbacks = g_slist_append(callbacks, cb); return cb->id; } -void purple_prefs_observe(gpointer data) +static void +purple_prefs_trigger_ui_callback_object(PurplePrefCallbackData *cb) { - struct pref_cb *cb = data; PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); gconstpointer value = NULL; PurplePrefType type = PURPLE_PREF_NONE; + type = uiop->get_type(cb->name); - purple_debug_misc("prefs", "observe name = %s\n", cb->name); - switch (type) { case PURPLE_PREF_INT: - value = GINT_TO_POINTER(uiop->get_int(cb->name)); + if (uiop->get_int) { + value = GINT_TO_POINTER(uiop->get_int(cb->name)); + } break; case PURPLE_PREF_BOOLEAN: - value = GINT_TO_POINTER(uiop->get_bool(cb->name)); + if (uiop->get_bool) { + value = GINT_TO_POINTER(uiop->get_bool(cb->name)); + } break; case PURPLE_PREF_STRING: - value = uiop->get_string(cb->name); + 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) { @@ -1441,9 +1502,10 @@ 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; } @@ -1457,18 +1519,18 @@ return FALSE; } -void -purple_prefs_disconnect_callback(guint callback_id) +static void +disco_ui_callback_helper(guint callback_id) { GSList *cbs; + PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); - for (cbs = callbacks; cbs; cbs = cbs->next) { - struct pref_cb *cb = cbs->data; + for (cbs = ui_callbacks; cbs; cbs = cbs->next) { + PurplePrefCallbackData *cb = cbs->data; if (cb->id == callback_id) { - PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); - uiop->remove_observer(cb->name, cb->observer); + uiop->disconnect_callback(cb->name, cb->ui_data); - callbacks = g_slist_delete_link(callbacks, cbs); + ui_callbacks = g_slist_delete_link(ui_callbacks, cbs); g_free(cb->name); g_free(cb); return; @@ -1476,6 +1538,18 @@ } } +void +purple_prefs_disconnect_callback(guint 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 disco_callback_helper_handle(struct purple_pref *pref, void *handle) { @@ -1487,9 +1561,10 @@ 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 @@ -1500,29 +1575,40 @@ disco_callback_helper_handle(child, handle); } -void -purple_prefs_disconnect_by_handle(void *handle) +static void +disco_ui_callback_helper_handle(void *handle) { GSList *cbs; - - g_return_if_fail(handle != NULL); + PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); - cbs = callbacks; - while (cbs != NULL) { - PurplePrefsUiOps *uiop; - struct pref_cb *cb = cbs->data; + cbs = ui_callbacks; + for (cbs = ui_callbacks; cbs; cbs = cbs->next) { + PurplePrefCallbackData *cb = cbs->data; if (cb->handle != handle) { cbs = cbs->next; continue; } - uiop = purple_prefs_get_ui_ops(); - uiop->remove_observer(cb->name, cb->observer); + uiop->disconnect_callback(cb->name, cb->ui_data); - callbacks = g_slist_delete_link(callbacks, cbs); + ui_callbacks = g_slist_delete_link(ui_callbacks, cbs); g_free(cb->name); g_free(cb); - cbs = callbacks; + cbs = ui_callbacks; + } +} + +void +purple_prefs_disconnect_by_handle(void *handle) +{ + PurplePrefsUiOps *uiop = purple_prefs_get_ui_ops(); + + g_return_if_fail(handle != NULL); + + if (uiop && uiop->disconnect_callback) { + disco_ui_callback_helper_handle(handle); + } else { + disco_callback_helper_handle(&prefs, handle); } } diff -r 35db38affc9f libpurple/prefs.h --- a/libpurple/prefs.h Wed Jun 15 22:40:26 2016 -0300 +++ b/libpurple/prefs.h Thu Jun 16 02:17:54 2016 -0300 @@ -64,6 +64,11 @@ typedef void (*PurplePrefCallback) (const char *name, PurplePrefType type, gconstpointer val, gpointer data); +/** + * Opaque type to carry callback information + */ +typedef struct _PurplePrefCallbackData PurplePrefCallbackData; + /** @copydoc _PurplePrefsUiOps */ typedef struct _PurplePrefsUiOps PurplePrefsUiOps; @@ -102,8 +107,8 @@ void (*save)(void); void (*schedule_save)(void); - void *(*add_observer)(const char *name, gpointer data); - void (*remove_observer)(const char *name, void *observer); + void *(*connect_callback)(const char *name, PurplePrefCallbackData *data); + void (*disconnect_callback)(const char *name, void *ui_data); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -410,11 +415,6 @@ gpointer data); /** - * Call the callback of the observer - */ -void purple_prefs_observe(gpointer data); - -/** * Remove a callback to a pref */ void purple_prefs_disconnect_callback(guint callback_id); @@ -430,6 +430,13 @@ void purple_prefs_trigger_callback(const char *name); /** + * Trigger callbacks as if the pref changed, taking a #PurplePrefCallbackData + * instead of a name + */ +void purple_prefs_trigger_callback_object(PurplePrefCallbackData *data); + + +/** * Read preferences */ gboolean purple_prefs_load(void); diff -r 35db38affc9f purplexpcom/src/purpleInit.cpp --- a/purplexpcom/src/purpleInit.cpp Wed Jun 15 22:40:26 2016 -0300 +++ b/purplexpcom/src/purpleInit.cpp Thu Jun 16 02:17:54 2016 -0300 @@ -123,11 +123,11 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER - prefsObserver(void *aCallback) : callback(aCallback) {} + prefsObserver(PurplePrefCallbackData *aCallback) : callback(aCallback) {} private: ~prefsObserver() {} - gpointer callback; + PurplePrefCallbackData *callback; }; NS_IMPL_ISUPPORTS(prefsObserver, nsIObserver) @@ -137,7 +137,7 @@ const char16_t *someData) { LOG(("prefsObserver::Observe topic = %s\n", aTopic)); - purple_prefs_observe(callback); + purple_prefs_trigger_callback_object(callback); return NS_OK; } @@ -357,7 +357,7 @@ return NULL; } -void *prefs_add_observer(const char *name, gpointer data) +void *prefs_add_observer(const char *name, PurplePrefCallbackData *data) { LOG(("prefs add observer %s\n", name));