changeset 10087:9fdbfe832fac

[gaim-migrate @ 11098] gaim_prefs_connect_callback() now takes a handle that can be used to disconnect the callbacks later on. The callback id's remain, so people can still use those if they want, although I'm not sure if there's any need for them any more. I also switched the order for initializing the prefs subsystem and statically compiled protocol plugins so that prpl prefs can work for statically compiled prpls. committer: Tailor Script <tailor@pidgin.im>
author Stu Tomlinson <stu@nosnilmot.com>
date Tue, 12 Oct 2004 00:49:19 +0000
parents 6cd2b467e303
children 65967ba9e66d
files plugins/ChangeLog.API plugins/gestures/gestures.c src/blist.c src/conversation.c src/core.c src/gtkblist.c src/gtkconv.c src/gtkdebug.c src/gtkdebug.h src/gtkprefs.c src/gtksound.c src/gtksound.h src/log.c src/plugin.c src/prefs.c src/prefs.h src/protocols/oscar/oscar.c src/proxy.c src/proxy.h src/status.c src/status.h
diffstat 21 files changed, 194 insertions(+), 139 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/ChangeLog.API	Sun Oct 10 16:47:56 2004 +0000
+++ b/plugins/ChangeLog.API	Tue Oct 12 00:49:19 2004 +0000
@@ -2,6 +2,8 @@
 
 version 2.0.0cvs:
 	* Changed: All the status stuff. Yay!
+	* Changed: gaim_prefs_connect_callback(), added handle parameter
+	* Added: gaim_prefs_disconnect_by_handle()
 	* Removed: gaim_gtk_sound_{get,set}_mute() (replaced by the
 	           /gaim/gtk/sound/mute preference)
 
--- a/plugins/gestures/gestures.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/plugins/gestures/gestures.c	Tue Oct 12 00:49:19 2004 +0000
@@ -304,7 +304,7 @@
 	gaim_prefs_add_none("/plugins/gtk/X11/gestures");
 	gaim_prefs_add_bool("/plugins/gtk/X11/gestures/visual", FALSE);
 
-	gaim_prefs_connect_callback("/plugins/gtk/X11/gestures/visual",
+	gaim_prefs_connect_callback(plugin, "/plugins/gtk/X11/gestures/visual",
 								visual_pref_cb, NULL);
 }
 
--- a/src/blist.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/blist.c	Tue Oct 12 00:49:19 2004 +0000
@@ -197,7 +197,7 @@
 	if (gbl->ui_ops != NULL && gbl->ui_ops->new_list != NULL)
 		gbl->ui_ops->new_list(gbl);
 
-	gaim_prefs_connect_callback("/core/buddies/use_server_alias",
+	gaim_prefs_connect_callback(gaim_blist_get_handle(), "/core/buddies/use_server_alias",
 								blist_pref_cb, NULL);
 
 	return gbl;
--- a/src/conversation.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/conversation.c	Tue Oct 12 00:49:19 2004 +0000
@@ -2731,9 +2731,9 @@
 	gaim_prefs_add_bool("/core/conversations/im/send_typing", TRUE);
 
 	/* Connect callbacks for changed preferences */
-	gaim_prefs_connect_callback("/core/conversations/use_alias_for_title",
+	gaim_prefs_connect_callback(handle, "/core/conversations/use_alias_for_title",
 			update_titles_pref_cb, NULL);
-	gaim_prefs_connect_callback("/core/buddies/use_server_alias",
+	gaim_prefs_connect_callback(handle, "/core/buddies/use_server_alias",
 			update_titles_pref_cb, NULL);
 
 
--- a/src/core.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/core.c	Tue Oct 12 00:49:19 2004 +0000
@@ -70,11 +70,13 @@
 
 	gaim_signal_register(core, "quitting", gaim_marshal_VOID, NULL, 0);
 
+	/* The prefs subsystem needs to be initialized before static protocols
+	 * for protocol prefs to work. */
+	gaim_prefs_init();
+
 	/* Initialize all static protocols. */
 	static_proto_init();
 
-	gaim_prefs_init();
-
 	if (ops != NULL)
 	{
 		if (ops->ui_prefs_init != NULL)
--- a/src/gtkblist.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtkblist.c	Tue Oct 12 00:49:19 2004 +0000
@@ -439,8 +439,6 @@
 /**************** END WEIRD DROP SHADOW STUFF ***********************************/
 #endif
 
-static GSList *blist_prefs_callbacks = NULL;
-
 /***************************************************
  *              Callbacks                          *
  ***************************************************/
@@ -3096,6 +3094,7 @@
 
 static void gaim_gtk_blist_show(GaimBuddyList *list)
 {
+	void *handle;
 	GtkCellRenderer *rend;
 	GtkTreeViewColumn *column;
 	GtkWidget *sw;
@@ -3184,7 +3183,7 @@
 										 dte, 5,
 										 GDK_ACTION_COPY | GDK_ACTION_MOVE);
 
-  	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL);
+ 	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(gaim_gtk_blist_drag_data_rcv_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(gaim_gtk_blist_drag_data_get_cb), NULL);
 
 	/* Tooltips */
@@ -3266,61 +3265,39 @@
 				(GSourceFunc)gaim_gtk_blist_refresh_timer, list);
 	}
 
+	handle = gaim_gtk_blist_get_handle();
+
 	/* things that affect how buddies are displayed */
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/grey_idle_buddies",
-					_prefs_change_redo_list, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_buddy_icons",
-					_prefs_change_redo_list, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_warning_level",
-					_prefs_change_redo_list, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_idle_time",
-					_prefs_change_redo_list, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_empty_groups",
-					_prefs_change_redo_list, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_offline_buddies",
-					_prefs_change_redo_list, NULL)));
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/grey_idle_buddies",
+			_prefs_change_redo_list, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_buddy_icons",
+			_prefs_change_redo_list, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_warning_level",
+			_prefs_change_redo_list, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_idle_time",
+			_prefs_change_redo_list, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_empty_groups",
+			_prefs_change_redo_list, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_offline_buddies",
+			_prefs_change_redo_list, NULL);
 
 	/* sorting */
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/sort_type",
-					_prefs_change_sort_method, NULL)));
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/sort_type",
+			_prefs_change_sort_method, NULL);
 
 	/* things that affect what columns are displayed */
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_buddy_icons",
-					gaim_gtk_blist_update_columns, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_idle_time",
-					gaim_gtk_blist_update_columns, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/blist/show_warning_level",
-					gaim_gtk_blist_update_columns, NULL)));
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_buddy_icons",
+			gaim_gtk_blist_update_columns, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_idle_time",
+			gaim_gtk_blist_update_columns, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/blist/show_warning_level",
+			gaim_gtk_blist_update_columns, NULL);
 
 	/* menus */
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/sound/mute",
-					gaim_gtk_blist_mute_pref_cb, NULL)));
-	blist_prefs_callbacks = g_slist_prepend(blist_prefs_callbacks,
-			GINT_TO_POINTER(
-				gaim_prefs_connect_callback("/gaim/gtk/sound/method",
-					gaim_gtk_blist_sound_method_pref_cb, NULL)));
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/sound/mute",
+			gaim_gtk_blist_mute_pref_cb, NULL);
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/sound/method",
+			gaim_gtk_blist_sound_method_pref_cb, NULL);
 
 	/* Setup some gaim signal handlers. */
 	gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
@@ -3334,7 +3311,7 @@
 			gtkblist, GAIM_CALLBACK(plugin_changed_cb), NULL);
 
 	/* emit our created signal */
-	gaim_signal_emit(gaim_gtk_blist_get_handle(), "gtkblist-created", list);
+	gaim_signal_emit(handle, "gtkblist-created", list);
 }
 
 /* XXX: does this need fixing? */
@@ -3823,10 +3800,7 @@
 	awaymenu = NULL;
 	gtkblist = NULL;
 
-	while(blist_prefs_callbacks) {
-		gaim_prefs_disconnect_callback(GPOINTER_TO_INT(blist_prefs_callbacks->data));
-		blist_prefs_callbacks = g_slist_remove(blist_prefs_callbacks, blist_prefs_callbacks->data);
-	}
+	gaim_prefs_disconnect_by_handle(gaim_gtk_blist_get_handle());
 }
 
 static void gaim_gtk_blist_set_visible(GaimBuddyList *list, gboolean show)
--- a/src/gtkconv.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtkconv.c	Tue Oct 12 00:49:19 2004 +0000
@@ -6397,34 +6397,34 @@
 	gaim_prefs_add_bool("/gaim/gtk/conversations/im/show_buddy_icons", TRUE);
 
 	/* Connect callbacks. */
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/escape_closes",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/escape_closes",
 								escape_closes_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/close_on_tabs",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/close_on_tabs",
 								close_on_tabs_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/show_timestamps",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/show_timestamps",
 								show_timestamps_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/html_shortcuts",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/html_shortcuts",
 								html_shortcuts_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/smiley_shortcuts",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/smiley_shortcuts",
 								smiley_shortcuts_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/show_formatting_toolbar",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/show_formatting_toolbar",
 								show_formatting_toolbar_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/spellcheck",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/spellcheck",
 								spellcheck_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/tab_side",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/tab_side",
 								tab_side_pref_cb, NULL);
 
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/placement",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/placement",
 			conv_placement_pref_cb, NULL);
 	gaim_prefs_trigger_callback("/gaim/gtk/conversations/placement");
 
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/button_type",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/button_type",
 								button_type_pref_cb, NULL);
 
 	/* IM callbacks */
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/im/animate_buddy_icons",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/im/animate_buddy_icons",
 								animate_buddy_icons_pref_cb, NULL);
-	gaim_prefs_connect_callback("/gaim/gtk/conversations/im/show_buddy_icons",
+	gaim_prefs_connect_callback(handle, "/gaim/gtk/conversations/im/show_buddy_icons",
 								show_buddy_icons_pref_cb, NULL);
 
 
--- a/src/gtkdebug.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtkdebug.c	Tue Oct 12 00:49:19 2004 +0000
@@ -47,8 +47,6 @@
 	gboolean timestamps;
 	gboolean paused;
 
-	guint timestamps_handle;
-
 } DebugWindow;
 
 static char debug_fg_colors[][8] = {
@@ -70,8 +68,7 @@
 static gint
 debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused)
 {
-	if (debug_win->timestamps_handle != 0)
-		gaim_prefs_disconnect_callback(debug_win->timestamps_handle);
+	gaim_prefs_disconnect_by_handle(gaim_gtk_debug_get_handle());
 
 	/* If the "Save Log" dialog is open then close it */
 	gaim_request_close_with_handle(debug_win);
@@ -298,9 +295,8 @@
 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
 						gaim_prefs_get_bool("/gaim/gtk/debug/timestamps"));
 
-		win->timestamps_handle =
-			gaim_prefs_connect_callback("/gaim/gtk/debug/timestamps",
-										timestamps_pref_cb, button);
+		gaim_prefs_connect_callback(gaim_gtk_debug_get_handle(), "/gaim/gtk/debug/timestamps",
+									timestamps_pref_cb, button);
 	}
 
 	/* Now our scrolled window... */
@@ -404,7 +400,7 @@
 	gaim_prefs_add_int("/gaim/gtk/debug/width",  450);
 	gaim_prefs_add_int("/gaim/gtk/debug/height", 250);
 
-	gaim_prefs_connect_callback("/gaim/gtk/debug/enabled",
+	gaim_prefs_connect_callback(NULL, "/gaim/gtk/debug/enabled",
 								debug_enabled_cb, NULL);
 
 #define REGISTER_G_LOG_HANDLER(name) \
@@ -535,3 +531,11 @@
 {
 	return &ops;
 }
+
+void *
+gaim_gtk_debug_get_handle() {
+	static int handle;
+
+	return &handle;
+}
+
--- a/src/gtkdebug.h	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtkdebug.h	Tue Oct 12 00:49:19 2004 +0000
@@ -33,6 +33,13 @@
 void gaim_gtk_debug_init(void);
 
 /**
+ * Get the handle for the GTK+ debug system.
+ *
+ * @return the handle to the debug system
+ */
+void *gaim_gtk_debug_get_handle();
+
+/**
  * Shows the debug window.
  */
 void gaim_gtk_debug_window_show(void);
--- a/src/gtkprefs.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtkprefs.c	Tue Oct 12 00:49:19 2004 +0000
@@ -74,15 +74,6 @@
 static int notebook_page = 0;
 static GtkTreeIter proto_iter, plugin_iter;
 
-static guint browser_pref1_id = 0;
-static guint browser_pref2_id = 0;
-static guint proxy_pref_id = 0;
-static guint sound_pref1_id = 0;
-static guint sound_pref2_id = 0;
-static guint sound_pref3_id = 0;
-static guint auto_resp_pref_id = 0;
-static guint placement_pref_id = 0;
-
 /*
  * PROTOTYPES
  */
@@ -368,6 +359,9 @@
 
 	gaim_plugins_unregister_probe_notify_cb(update_plugin_list);
 
+	/* Unregister callbacks. */
+	gaim_prefs_disconnect_by_handle(prefs);
+
 	prefs = NULL;
 	tree_v = NULL;
 	sound_entry = NULL;
@@ -378,16 +372,6 @@
 	g_object_unref(G_OBJECT(prefs_away_store));
 	prefs_away_store = NULL;
 
-	/* Unregister callbacks. */
-	gaim_prefs_disconnect_callback(browser_pref1_id);
-	gaim_prefs_disconnect_callback(browser_pref2_id);
-	gaim_prefs_disconnect_callback(proxy_pref_id);
-	gaim_prefs_disconnect_callback(sound_pref1_id);
-	gaim_prefs_disconnect_callback(sound_pref2_id);
-	gaim_prefs_disconnect_callback(sound_pref3_id);
-	gaim_prefs_disconnect_callback(auto_resp_pref_id);
-	gaim_prefs_disconnect_callback(placement_pref_id);
-
 	for (l = gaim_plugins_get_loaded(); l != NULL; l = l->next) {
 		plug = l->data;
 
@@ -1027,9 +1011,8 @@
 	 */
 	vbox2 = gtk_vbox_new(FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0);
-	placement_pref_id = gaim_prefs_connect_callback("/gaim/gtk/conversations/tabs",
-	                                                conversation_usetabs_cb,
-	                                                vbox2);
+	gaim_prefs_connect_callback(prefs, "/gaim/gtk/conversations/tabs",
+	                            conversation_usetabs_cb, vbox2);
 	if (!gaim_prefs_get_bool("/gaim/gtk/conversations/tabs"))
 		gtk_widget_set_sensitive(vbox2, FALSE);
 
@@ -1172,8 +1155,8 @@
 
 		gtk_widget_set_sensitive(GTK_WIDGET(prefs_proxy_frame), FALSE);
 	}
-	proxy_pref_id = gaim_prefs_connect_callback("/core/proxy/type",
-						    proxy_changed_cb, prefs_proxy_frame);
+	gaim_prefs_connect_callback(prefs, "/core/proxy/type",
+								proxy_changed_cb, prefs_proxy_frame);
 
 	table = gtk_table_new(4, 2, FALSE);
 	gtk_container_set_border_width(GTK_CONTAINER(table), 5);
@@ -1367,8 +1350,8 @@
 
 		if (!strcmp(gaim_prefs_get_string("/gaim/gtk/browsers/browser"), "custom"))
 			gtk_widget_set_sensitive(hbox, FALSE);
-		browser_pref1_id = gaim_prefs_connect_callback("/gaim/gtk/browsers/browser",
-													  browser_changed1_cb, hbox);
+		gaim_prefs_connect_callback(prefs, "/gaim/gtk/browsers/browser",
+									browser_changed1_cb, hbox);
 	}
 
 	hbox = gtk_hbox_new(FALSE, 5);
@@ -1383,8 +1366,8 @@
 
 	if (strcmp(gaim_prefs_get_string("/gaim/gtk/browsers/browser"), "custom"))
 		gtk_widget_set_sensitive(hbox, FALSE);
-	browser_pref2_id = gaim_prefs_connect_callback("/gaim/gtk/browsers/browser",
-												  browser_changed2_cb, hbox);
+	gaim_prefs_connect_callback(prefs, "/gaim/gtk/browsers/browser",
+								browser_changed2_cb, hbox);
 
 	gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
 
@@ -1674,8 +1657,8 @@
 	gtk_widget_set_sensitive(hbox,
 			!strcmp(gaim_prefs_get_string("/gaim/gtk/sound/method"),
 					"custom"));
-	sound_pref1_id = gaim_prefs_connect_callback("/gaim/gtk/sound/method",
-												  sound_changed1_cb, hbox);
+	gaim_prefs_connect_callback(prefs, "/gaim/gtk/sound/method",
+								sound_changed1_cb, hbox);
 
 	gaim_set_accessible_label (entry, label);
 #endif /* _WIN32 */
@@ -1689,8 +1672,8 @@
 #ifndef _WIN32
 	gtk_widget_set_sensitive(vbox,
 			strcmp(gaim_prefs_get_string("/gaim/gtk/sound/method"), "none"));
-	sound_pref2_id = gaim_prefs_connect_callback("/gaim/gtk/sound/method",
-												  sound_changed2_cb, vbox);
+	gaim_prefs_connect_callback(prefs, "/gaim/gtk/sound/method",
+								sound_changed2_cb, vbox);
 #endif
 
 	vbox = gaim_gtk_make_frame(ret, _("Sound Events"));
@@ -1786,8 +1769,8 @@
 #ifndef _WIN32
 	gtk_widget_set_sensitive(vbox,
 			strcmp(gaim_prefs_get_string("/gaim/gtk/sound/method"), "none"));
-	sound_pref3_id = gaim_prefs_connect_callback("/gaim/gtk/sound/method",
-												  sound_changed2_cb, vbox);
+	gaim_prefs_connect_callback(prefs, "/gaim/gtk/sound/method",
+								sound_changed2_cb, vbox);
 #endif
 
 	return ret;
@@ -2682,7 +2665,7 @@
 	gaim_prefs_add_string("/gaim/gtk/smileys/theme", "default");
 
 	/* Smiley Callbacks */
-	gaim_prefs_connect_callback("/gaim/gtk/smileys/theme",
+	gaim_prefs_connect_callback(prefs, "/gaim/gtk/smileys/theme",
 								smiley_theme_pref_cb, NULL);
 }
 
--- a/src/gtksound.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtksound.c	Tue Oct 12 00:49:19 2004 +0000
@@ -118,7 +118,7 @@
 	ao_initialize();
 #endif /* USE_AO */
 
-	gaim_prefs_connect_callback("/gaim/gtk/sound/method",
+	gaim_prefs_connect_callback(gaim_gtk_sound_get_handle(), "/gaim/gtk/sound/method",
 			_pref_sound_method_changed, NULL);
 }
 
@@ -405,3 +405,10 @@
 
 	return sounds[event].label;
 }
+
+void *gaim_gtk_sound_get_handle()
+{
+	static int handle;
+
+	return &handle;
+}
--- a/src/gtksound.h	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/gtksound.h	Tue Oct 12 00:49:19 2004 +0000
@@ -30,6 +30,13 @@
 /*@{*/
 
 /**
+ * Get the handle for the GTK+ sound system.
+ *
+ * @return the handle to the sound system
+ */
+void *gaim_gtk_sound_get_handle();
+
+/**
  * Gets GTK Sound UI opsA
  *
  * @return UI operations struct
--- a/src/log.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/log.c	Tue Oct 12 00:49:19 2004 +0000
@@ -346,7 +346,7 @@
 	gaim_log_logger_add(&html_logger);
 	gaim_log_logger_add(&txt_logger);
 	gaim_log_logger_add(&old_logger);
-	gaim_prefs_connect_callback("/core/logging/format",
+	gaim_prefs_connect_callback(NULL, "/core/logging/format",
 				    logger_pref_cb, NULL);
 	gaim_prefs_trigger_callback("/core/logging/format");
 
--- a/src/plugin.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/plugin.c	Tue Oct 12 00:49:19 2004 +0000
@@ -443,6 +443,8 @@
 	/* I suppose this is the right place to call this... */
 	gaim_signal_emit(gaim_plugins_get_handle(), "plugin-unload", plugin);
 
+	gaim_prefs_disconnect_by_handle(plugin);
+
 	return TRUE;
 #else
 	return TRUE;
--- a/src/prefs.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/prefs.c	Tue Oct 12 00:49:19 2004 +0000
@@ -44,6 +44,7 @@
 	GaimPrefCallback func;
 	gpointer data;
 	guint id;
+	void *handle;
 };
 
 struct gaim_pref {
@@ -96,7 +97,7 @@
 void gaim_prefs_init() {
 	prefs_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 
-	gaim_prefs_connect_callback("/", prefs_save_cb, NULL);
+	gaim_prefs_connect_callback(NULL, "/", prefs_save_cb, NULL);
 
 	gaim_prefs_add_none("/core");
 	gaim_prefs_add_none("/plugins");
@@ -634,7 +635,7 @@
 
 void gaim_prefs_rename_boolean_toggle(const char *oldname, const char *newname) {
 		struct gaim_pref *oldpref, *newpref;
-		
+
 		gaim_debug_info("prefs", "Attempting to rename and toggle %s to %s\n", oldname, newname);
 
 		oldpref = find_pref(oldname);
@@ -648,14 +649,14 @@
 		g_return_if_fail(oldpref->type == newpref->type);
 		g_return_if_fail(oldpref->type == GAIM_PREF_BOOLEAN);
 		g_return_if_fail(oldpref->first_child == NULL); /* can't rename parents */
-		
+
 		gaim_prefs_set_bool(newname, !(oldpref->value.boolean));
 
 		remove_pref(oldpref);
 
 }
 
-guint gaim_prefs_connect_callback(const char *name, GaimPrefCallback func, gpointer data)
+guint gaim_prefs_connect_callback(void *handle, const char *name, GaimPrefCallback func, gpointer data)
 {
 	struct gaim_pref *pref;
 	struct pref_cb *cb;
@@ -670,13 +671,14 @@
 	cb->func = func;
 	cb->data = data;
 	cb->id = ++cb_id;
+	cb->handle = handle;
 
 	pref->callbacks = g_slist_append(pref->callbacks, cb);
 
 	return cb->id;
 }
 
-gboolean disco_callback_helper(struct gaim_pref *pref, guint callback_id) {
+static gboolean disco_callback_helper(struct gaim_pref *pref, guint callback_id) {
 	GSList *cbs;
 	struct gaim_pref *child;
 
@@ -704,6 +706,33 @@
 	disco_callback_helper(&prefs, callback_id);
 }
 
+static void disco_callback_helper_handle(struct gaim_pref *pref, void *handle) {
+	GSList *cbs;
+	struct gaim_pref *child;
+
+	if(!pref)
+		return;
+
+	cbs = pref->callbacks;
+	while (cbs != NULL) {
+		struct pref_cb *cb = cbs->data;
+		if(cb->handle == handle) {
+			pref->callbacks = g_slist_remove(pref->callbacks, cb);
+			g_free(cb);
+			cbs = pref->callbacks;
+		} else
+			cbs = cbs->next;
+	}
+
+	for(child = pref->first_child; child; child = child->sibling)
+		disco_callback_helper_handle(child, handle);
+}
+
+void gaim_prefs_disconnect_by_handle(void *handle) {
+	g_return_if_fail(handle != NULL);
+	disco_callback_helper_handle(&prefs, handle);
+}
+
 static void gaim_prefs_write(FILE *f, struct gaim_pref *pref, int depth) {
 	struct gaim_pref *tmp;
 	char *esc;
--- a/src/prefs.h	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/prefs.h	Tue Oct 12 00:49:19 2004 +0000
@@ -225,7 +225,7 @@
 /**
  * Add a callback to a pref (and its children)
  */
-guint gaim_prefs_connect_callback(const char *name, GaimPrefCallback cb,
+guint gaim_prefs_connect_callback(void *handle, const char *name, GaimPrefCallback cb,
 		gpointer data);
 
 /**
@@ -234,6 +234,11 @@
 void gaim_prefs_disconnect_callback(guint callback_id);
 
 /**
+ * Remove all pref callbacks by handle
+ */
+void gaim_prefs_disconnect_by_handle(void *handle);
+
+/**
  * Trigger callbacks as if the pref changed
  */
 void gaim_prefs_trigger_callback(const char *name);
--- a/src/protocols/oscar/oscar.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/protocols/oscar/oscar.c	Tue Oct 12 00:49:19 2004 +0000
@@ -107,7 +107,6 @@
 	guint icontimer;
 	guint getblisttimer;
 	guint getinfotimer;
-	guint recentbuddies_cbid;
 
 	struct {
 		guint maxwatchers; /* max users who can watch you */
@@ -1731,7 +1730,7 @@
 	sess->aux_data = gc;
 
 	/* Connect to core Gaim signals */
-	od->recentbuddies_cbid = gaim_prefs_connect_callback("/plugins/prpl/oscar/recent_buddies", recent_buddies_cb, gc);
+	gaim_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_cb, gc);
 
 	conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
 	if (conn == NULL) {
@@ -1813,7 +1812,7 @@
 		gaim_timeout_remove(od->getblisttimer);
 	if (od->getinfotimer > 0)
 		gaim_timeout_remove(od->getinfotimer);
-	gaim_prefs_disconnect_callback(od->recentbuddies_cbid);
+	gaim_prefs_disconnect_by_handle(gc);
 
 	aim_session_kill(od->sess);
 	g_free(od->sess);
--- a/src/proxy.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/proxy.c	Tue Oct 12 00:49:19 2004 +0000
@@ -1601,6 +1601,8 @@
 void
 gaim_proxy_init(void)
 {
+	void *handle;
+
 	/* Initialize a default proxy info struct. */
 	global_proxy_info = gaim_proxy_info_new();
 
@@ -1613,14 +1615,23 @@
 	gaim_prefs_add_string("/core/proxy/password", "");
 
 	/* Setup callbacks for the preferences. */
-	gaim_prefs_connect_callback("/core/proxy/type",
+	handle = gaim_proxy_get_handle();
+	gaim_prefs_connect_callback(handle, "/core/proxy/type",
 								proxy_pref_cb, NULL);
-	gaim_prefs_connect_callback("/core/proxy/host",
+	gaim_prefs_connect_callback(handle, "/core/proxy/host",
 								proxy_pref_cb, NULL);
-	gaim_prefs_connect_callback("/core/proxy/port",
+	gaim_prefs_connect_callback(handle, "/core/proxy/port",
 								proxy_pref_cb, NULL);
-	gaim_prefs_connect_callback("/core/proxy/username",
+	gaim_prefs_connect_callback(handle, "/core/proxy/username",
 								proxy_pref_cb, NULL);
-	gaim_prefs_connect_callback("/core/proxy/password",
+	gaim_prefs_connect_callback(handle, "/core/proxy/password",
 								proxy_pref_cb, NULL);
 }
+
+void *
+gaim_proxy_get_handle()
+{
+	static int handle;
+
+	return &handle;
+}
--- a/src/proxy.h	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/proxy.h	Tue Oct 12 00:49:19 2004 +0000
@@ -69,6 +69,13 @@
 /*@{*/
 
 /**
+ * Get the handle for the proxy system.
+ *
+ * @return the handle to the proxy system
+ */
+void *gaim_proxy_get_handle();
+
+/**
  * Creates a proxy information structure.
  *
  * @return The proxy information structure.
--- a/src/status.c	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/status.c	Tue Oct 12 00:49:19 2004 +0000
@@ -1533,9 +1533,18 @@
 		return FALSE;
 }
 
+void *
+gaim_statuses_get_handle() {
+	static int handle;
+
+	return &handle;
+}
+
 void
 gaim_statuses_init(void)
 {
+	void *handle = gaim_statuses_get_handle;
+
 	gaim_prefs_add_none("/core/status");
 	gaim_prefs_add_none("/core/status/scores");
 
@@ -1552,22 +1561,22 @@
 	gaim_prefs_add_int("/core/status/scores/idle",
 			primitive_scores[SCORE_IDLE]);
 
-	gaim_prefs_connect_callback("/core/status/scores/offline",
+	gaim_prefs_connect_callback(handle, "/core/status/scores/offline",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(GAIM_STATUS_OFFLINE));
-	gaim_prefs_connect_callback("/core/status/scores/available",
+	gaim_prefs_connect_callback(handle, "/core/status/scores/available",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(GAIM_STATUS_AVAILABLE));
-	gaim_prefs_connect_callback("/core/status/scores/hidden",
+	gaim_prefs_connect_callback(handle, "/core/status/scores/hidden",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(GAIM_STATUS_HIDDEN));
-	gaim_prefs_connect_callback("/core/status/scores/away",
+	gaim_prefs_connect_callback(handle, "/core/status/scores/away",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(GAIM_STATUS_AWAY));
-	gaim_prefs_connect_callback("/core/status/scores/extended_away",
+	gaim_prefs_connect_callback(handle, "/core/status/scores/extended_away",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(GAIM_STATUS_EXTENDED_AWAY));
-	gaim_prefs_connect_callback("/core/status/scores/idle",
+	gaim_prefs_connect_callback(handle, "/core/status/scores/idle",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(SCORE_IDLE));
 
--- a/src/status.h	Sun Oct 10 16:47:56 2004 +0000
+++ b/src/status.h	Tue Oct 12 00:49:19 2004 +0000
@@ -889,6 +889,13 @@
 									  const char *id);
 
 /**
+ * Get the handle for the status subsystem.
+ *
+ * @return the handle to the status subsystem
+ */
+void *gaim_statuses_get_handle();
+
+/**
  * Initializes the status subsystem.
  */
 void gaim_statuses_init(void);