changeset 1911:db3104dda736

[gaim-migrate @ 1921] Mike Heffner's redesigned UI. I changed around a lot of things from his patch, not because they weren't good or needed or anything like that; most of the changes I made just made the patch smaller. I moved functions back to where they originally where and renamed them back to what they originally were. Granted the names aren't as... good as the changes Mike made, but eh, it made my life a lot easier when I could see the meat of the changes without all the cosmetic details. The only thing I really changed about his patch was I made the list BROWSE instead of SINGLE so that there wouldn't be need for a deselect callback. Oh yeah, and update_show_plugins is called from different places (so that plugins can call load_plugin and have the window update properly). committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 29 May 2001 09:46:05 +0000
parents 1cfc79c126fe
children 8ed70631ed15
files ChangeLog src/plugins.c
diffstat 2 files changed, 227 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue May 29 01:49:35 2001 +0000
+++ b/ChangeLog	Tue May 29 09:46:05 2001 +0000
@@ -22,6 +22,7 @@
 	* Can receive buddy icons in Oscar (requires gdk_pixbuf,
 	  which GNOME depends on. If you --disable-pixbuf, it will
 	  disable this.)
+	* Redesigned plugins dialog (thanks Mike Heffner)
 
 version 0.11.0-pre11 (04/30/2001):
 	* Zephyr updates and additions, thanks Neil Sanchala (nsanch)
--- a/src/plugins.c	Tue May 29 01:49:35 2001 +0000
+++ b/src/plugins.c	Tue May 29 09:46:05 2001 +0000
@@ -50,6 +50,15 @@
 
 #include <dlfcn.h>
 
+#include "pixmaps/gnome_add.xpm"
+#include "pixmaps/gnome_remove.xpm"
+#include "pixmaps/gnome_preferences.xpm"
+#include "pixmaps/refresh.xpm"
+#include "pixmaps/cancel.xpm"
+
+#define PATHSIZE 1024	/* XXX: stolen from dialogs.c */
+
+
 /* ------------------ Global Variables ----------------------- */
 
 GList *plugins = NULL;
@@ -59,9 +68,12 @@
 
 static GtkWidget *plugin_dialog = NULL;
 
-static GtkWidget *pluglist;
-static GtkWidget *plugtext;
-static GtkWidget *plugwindow;
+static GtkWidget *pluglist = NULL;
+static GtkWidget *plugtext = NULL;
+static GtkWidget *plugwindow = NULL;
+static GtkWidget *plugentry = NULL;
+
+static GtkTooltips *tooltips = NULL;
 
 static GtkWidget *config = NULL;
 static guint confighandle = 0;
@@ -76,6 +88,14 @@
 void gaim_signal_disconnect(GModule *, enum gaim_event, void *);
 void gaim_plugin_unload(GModule *);
 
+/* UI button callbacks */
+static void plugin_reload_cb(GtkWidget *, gpointer);
+
+static const gchar *plugin_makelistname(GModule *);
+static void plugin_remove_callbacks(GModule *);
+
+static void plugin_reload(struct gaim_plugin *p);
+
 static void destroy_plugins(GtkWidget *, gpointer);
 static void load_file(GtkWidget *, gpointer);
 static void load_which_plugin(GtkWidget *, gpointer);
@@ -163,13 +183,9 @@
 	while (filename && c) {
 		plug = (struct gaim_plugin *)c->data;
 		if (!strcmp(filename, g_module_name(plug->handle))) {
-			void (*gaim_plugin_remove)();
-			if (g_module_symbol(plug->handle, "gaim_plugin_remove",
-					    (gpointer *)&gaim_plugin_remove))
-				(*gaim_plugin_remove)();
-
-			unload_immediate(plug->handle);
-			c = plugins;
+			/* just need to reload plugin */
+			plugin_reload(plug);
+			return;
 		} else
 			c = g_list_next(c);
 	}
@@ -198,23 +214,9 @@
 	}
 
 	retval = (*gaim_plugin_init)(plug->handle);
-	debug_printf("loaded plugin returned %d\n", retval);
+	debug_printf("loaded plugin returned %s\n", retval ? retval : "NULL");
 	if (retval) {
-		GList *c = callbacks;
-		struct gaim_callback *g;
-		while (c) {
-			g = (struct gaim_callback *)c->data;
-			if (g->handle == plug->handle) {
-				callbacks = g_list_remove(callbacks, c->data);
-				debug_printf("Removing callback, %d remain\n", g_list_length(callbacks));
-				c = callbacks;
-				if (c == NULL) {
-					break;
-				}
-			} else {
-				c = g_list_next(c);
-			}
-		}
+		plugin_remove_callbacks(plug->handle);
 		do_error_dialog(retval, _("Plugin Error"));
 		g_module_close(plug->handle);
 		g_free(plug);
@@ -249,19 +251,19 @@
 
 void show_plugins(GtkWidget *w, gpointer data)
 {
-	/* most of this code was shamelessly stolen from prefs.c */
-	GtkWidget *page;
-	GtkWidget *topbox;
-	GtkWidget *botbox;
-	GtkWidget *sw;
+	/* most of this code was shamelessly stolen from Glade */
+	GtkWidget *mainvbox;
+	GtkWidget *tophbox;
+	GtkWidget *bothbox;
+	GtkWidget *hbox;
+	GtkWidget *vbox;
+	GtkWidget *frame;
+	GtkWidget *scrolledwindow;
 	GtkWidget *label;
-	GtkWidget *list_item;
-	GtkWidget *sw2;
 	GtkWidget *add;
+	GtkWidget *reload;
 	GtkWidget *remove;
 	GtkWidget *close;
-	GList *plugs = plugins;
-	struct gaim_plugin *p;
 
 	if (plugwindow)
 		return;
@@ -270,95 +272,110 @@
 	gtk_window_set_wmclass(GTK_WINDOW(plugwindow), "plugins", "Gaim");
 	gtk_widget_realize(plugwindow);
 	aol_icon(plugwindow->window);
-	gtk_container_border_width(GTK_CONTAINER(plugwindow), 5);
 	gtk_window_set_title(GTK_WINDOW(plugwindow), _("Gaim - Plugins"));
-	gtk_widget_set_usize(plugwindow, 400, 250);
+	gtk_widget_set_usize(plugwindow, 515, 300);
 	gtk_signal_connect(GTK_OBJECT(plugwindow), "destroy", GTK_SIGNAL_FUNC(hide_plugins), NULL);
 
-	page = gtk_vbox_new(FALSE, 5);
-	topbox = gtk_hbox_new(FALSE, 5);
-	botbox = gtk_hbox_new(FALSE, 5);
+	mainvbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(plugwindow), mainvbox);
+	gtk_widget_show(mainvbox);
+
+	/* Build the top */
+	tophbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(mainvbox), tophbox, TRUE, TRUE, 0);
+	gtk_widget_show(tophbox);
 
-	/* Left side: list of plugin file names */
-	sw2 = gtk_scrolled_window_new(NULL, NULL);
-	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw2),
-				       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	/* Left side: frame with list of plugin file names */
+	frame = gtk_frame_new(_("Plugins"));
+	gtk_box_pack_start(GTK_BOX(tophbox), frame, FALSE, FALSE, 0);
+	gtk_widget_set_usize(frame, 140, -1);
+	gtk_container_set_border_width(GTK_CONTAINER(frame), 6);
+	gtk_frame_set_label_align(GTK_FRAME(frame), 0.05, 0.5);
+	gtk_widget_show(frame);
+
+	scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
+	gtk_container_add(GTK_CONTAINER(frame), scrolledwindow);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_widget_show(scrolledwindow);
 
 	pluglist = gtk_list_new();
-	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), pluglist);
-	gtk_box_pack_start(GTK_BOX(topbox), sw2, TRUE, TRUE, 0);
+	gtk_list_set_selection_mode(GTK_LIST(pluglist), GTK_SELECTION_BROWSE);
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), pluglist);
+	gtk_widget_show(pluglist);
 
-	/* Right side: the text description of the plugin */
-	sw = gtk_scrolled_window_new(NULL, NULL);
-	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
-				       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	/* Right side: frame with description and the filepath of plugin */
+	frame = gtk_frame_new(_("Description"));
+	gtk_box_pack_start(GTK_BOX(tophbox), frame, TRUE, TRUE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(frame), 6);
+	gtk_frame_set_label_align(GTK_FRAME(frame), 0.05, 0.5);
+	gtk_widget_show(frame);
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(frame), vbox);
+	gtk_widget_show(vbox);
+
+	scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
+	gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_widget_show(scrolledwindow);
 
 	plugtext = gtk_text_new(NULL, NULL);
-	gtk_container_add(GTK_CONTAINER(sw), plugtext);
-	gtk_box_pack_start(GTK_BOX(topbox), sw, TRUE, TRUE, 0);
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), plugtext);
 	gtk_text_set_word_wrap(GTK_TEXT(plugtext), TRUE);
 	gtk_text_set_editable(GTK_TEXT(plugtext), FALSE);
+	gtk_widget_show(plugtext);
+
+	hbox = gtk_hbox_new(FALSE, 5);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
+	gtk_widget_show(hbox);
+
+	label = gtk_label_new(_("Filepath:"));
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	gtk_widget_show(label);
+
+	plugentry = gtk_entry_new();
+	gtk_box_pack_start(GTK_BOX(hbox), plugentry, TRUE, TRUE, 0);
+	gtk_entry_set_editable(GTK_ENTRY(plugentry), FALSE);
+	gtk_widget_show(plugentry);
 
 	/* Build the bottom button bar */
-	add = gtk_button_new_with_label(_("Load Plugin"));
-	gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC(load_file), NULL);
-	gtk_box_pack_start(GTK_BOX(botbox), add, TRUE, TRUE, 0);
-	if (display_options & OPT_DISP_COOL_LOOK)
-		gtk_button_set_relief(GTK_BUTTON(add), GTK_RELIEF_NONE);
-
-	config = gtk_button_new_with_label(_("Configure Plugin"));
-	gtk_widget_set_sensitive(config, 0);
-	gtk_box_pack_start(GTK_BOX(botbox), config, TRUE, TRUE, 0);
-	if (display_options & OPT_DISP_COOL_LOOK)
-		gtk_button_set_relief(GTK_BUTTON(config), GTK_RELIEF_NONE);
+	bothbox = gtk_hbox_new(TRUE, 10);
+	gtk_box_pack_start(GTK_BOX(mainvbox), bothbox, FALSE, FALSE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
+	gtk_widget_show(bothbox);
 
-	remove = gtk_button_new_with_label(_("Unload Plugin"));
-	gtk_signal_connect(GTK_OBJECT(remove), "clicked", GTK_SIGNAL_FUNC(unload), pluglist);
-	gtk_box_pack_start(GTK_BOX(botbox), remove, TRUE, TRUE, 0);
-	if (display_options & OPT_DISP_COOL_LOOK)
-		gtk_button_set_relief(GTK_BUTTON(remove), GTK_RELIEF_NONE);
+	if (!tooltips)
+		tooltips = gtk_tooltips_new();
 
-	close = gtk_button_new_with_label(_("Close"));
-	gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(hide_plugins), NULL);
-	gtk_box_pack_start(GTK_BOX(botbox), close, TRUE, TRUE, 0);
-	if (display_options & OPT_DISP_COOL_LOOK)
-		gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE);
-
-	gtk_box_pack_start(GTK_BOX(page), topbox, TRUE, TRUE, 0);
-	gtk_box_pack_start(GTK_BOX(page), botbox, FALSE, FALSE, 0);
+	add = picture_button(plugwindow, _("Load"), gnome_add_xpm);
+	gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC(load_file), NULL);
+	gtk_box_pack_start(GTK_BOX(bothbox), add, TRUE, TRUE, 0);
+	gtk_tooltips_set_tip(tooltips, add, _("Load a plugin from a file"), "");
 
-	while (plugs) {
-		p = (struct gaim_plugin *)plugs->data;
-		label = gtk_label_new(g_module_name(p->handle));
-		list_item = gtk_list_item_new();
-		gtk_container_add(GTK_CONTAINER(list_item), label);
-		gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p);
-		gtk_object_set_user_data(GTK_OBJECT(list_item), p);
+	config = picture_button(plugwindow, _("Configure"), gnome_preferences_xpm);
+	gtk_widget_set_sensitive(config, FALSE);
+	gtk_box_pack_start(GTK_BOX(bothbox), config, TRUE, TRUE, 0);
+	gtk_tooltips_set_tip(tooltips, config, _("Configure settings of the selected plugin"), "");
 
-		gtk_widget_show(label);
-		gtk_container_add(GTK_CONTAINER(pluglist), list_item);
-		gtk_widget_show(list_item);
-
-		plugs = g_list_next(plugs);
-	}
+	reload = picture_button(plugwindow, _("Reload"), refresh_xpm);
+	gtk_signal_connect(GTK_OBJECT(reload), "clicked", GTK_SIGNAL_FUNC(plugin_reload_cb), NULL);
+	gtk_box_pack_start(GTK_BOX(bothbox), reload, TRUE, TRUE, 0);
+	gtk_tooltips_set_tip(tooltips, reload, _("Reload the selected plugin"), "");
 
-	/* Make the first item selected */
-	if (plugins != NULL)
-		gtk_list_select_item(GTK_LIST(pluglist), 0);
+	remove = picture_button(plugwindow, _("Unload"), gnome_remove_xpm);
+	gtk_signal_connect(GTK_OBJECT(remove), "clicked", GTK_SIGNAL_FUNC(unload), pluglist);
+	gtk_box_pack_start(GTK_BOX(bothbox), remove, TRUE, TRUE, 0);
+	gtk_tooltips_set_tip(tooltips, remove, _("Unload the selected plugin"), "");
 
-	gtk_widget_show(page);
-	gtk_widget_show(topbox);
-	gtk_widget_show(botbox);
-	gtk_widget_show(sw);
-	gtk_widget_show(sw2);
-	gtk_widget_show(pluglist);
-	gtk_widget_show(plugtext);
-	gtk_widget_show(add);
-	gtk_widget_show(config);
-	gtk_widget_show(remove);
-	gtk_widget_show(close);
+	close = picture_button(plugwindow, _("Close"), cancel_xpm);
+	gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(hide_plugins), NULL);
+	gtk_box_pack_start(GTK_BOX(bothbox), close, TRUE, TRUE, 0);
+	gtk_tooltips_set_tip(tooltips, close, _("Close this window"), "");
 
-	gtk_container_add(GTK_CONTAINER(plugwindow), page);
+	update_show_plugins();
 	gtk_widget_show(plugwindow);
 }
 
@@ -368,6 +385,7 @@
 	struct gaim_plugin *p;
 	GtkWidget *label;
 	GtkWidget *list_item;
+	GtkWidget *hbox;
 
 	if (plugwindow == NULL)
 		return;
@@ -375,23 +393,22 @@
 	gtk_list_clear_items(GTK_LIST(pluglist), 0, -1);
 	while (plugs) {
 		p = (struct gaim_plugin *)plugs->data;
-		label = gtk_label_new(g_module_name(p->handle));
+		label = gtk_label_new(plugin_makelistname(p->handle));
+		hbox = gtk_hbox_new(FALSE, 0);	/* for left justification */
+		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
 		list_item = gtk_list_item_new();
-		gtk_container_add(GTK_CONTAINER(list_item), label);
+		gtk_container_add(GTK_CONTAINER(list_item), hbox);
 		gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p);
 		gtk_object_set_user_data(GTK_OBJECT(list_item), p);
 
+		gtk_widget_show(hbox);
 		gtk_widget_show(label);
 		gtk_container_add(GTK_CONTAINER(pluglist), list_item);
 		gtk_widget_show(list_item);
+
 		plugs = g_list_next(plugs);
 	}
-	if (plugins != NULL)
-		gtk_list_select_item(GTK_LIST(pluglist), 0);
-	else {
-		gtk_text_set_point(GTK_TEXT(plugtext), 0);
-		gtk_text_forward_delete(GTK_TEXT(plugtext), gtk_text_get_length(GTK_TEXT(plugtext)));
-	}
 }
 
 void unload(GtkWidget *w, gpointer data)
@@ -412,14 +429,13 @@
 		(*gaim_plugin_remove)();
 
 	unload_immediate(p->handle);
+	update_show_plugins();
 }
 
 static void unload_for_real(void *handle)
 {
 	GList *i;
 	struct gaim_plugin *p = NULL;
-	GList *c = callbacks;
-	struct gaim_callback *g;
 
 	i = plugins;
 	while (i) {
@@ -435,27 +451,10 @@
 
 	debug_printf("Unloading %s\n", g_module_name(p->handle));
 
-	debug_printf("%d callbacks to search\n", g_list_length(callbacks));
-
-	while (c) {
-		g = (struct gaim_callback *)c->data;
-		if (g->handle == p->handle) {
-			callbacks = g_list_remove(callbacks, c->data);
-			g_free(g);
-			debug_printf("Removing callback, %d remain\n", g_list_length(callbacks));
-			c = callbacks;
-			if (c == NULL) {
-				break;
-			}
-		} else {
-			c = g_list_next(c);
-		}
-	}
+	plugin_remove_callbacks(p->handle);
 
 	plugins = g_list_remove(plugins, p);
 	g_free(p);
-	if (config)
-		gtk_widget_set_sensitive(config, 0);
 	update_show_plugins();
 	save_prefs();
 }
@@ -478,6 +477,52 @@
 	gtk_timeout_add(5000, (GtkFunction)unload_timeout, handle);
 }
 
+static void plugin_reload_cb(GtkWidget *w, gpointer data)
+{
+	GList *i;
+
+	i = GTK_LIST(pluglist)->selection;
+	if (i == NULL)
+		return;
+
+	/* Just pass off plugin to the actual function */
+	plugin_reload(gtk_object_get_user_data(GTK_OBJECT(i->data)));
+}
+
+/* Do unload/load cycle of plugin. */
+static void plugin_reload(struct gaim_plugin *p)
+{
+	char file[PATHSIZE];
+	void (*gaim_plugin_remove)();
+	GModule *handle = p->handle;
+	struct gaim_plugin *plug;
+	GList *plugs;
+
+	strncpy(file, g_module_name(handle), sizeof(file));
+	file[sizeof(file) - 1] = '\0';
+
+	debug_printf("Reloading %s\n", file);
+
+	/* Unload */
+	if (g_module_symbol(handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove))
+		(*gaim_plugin_remove)();
+	unload_immediate(handle);
+
+	/* Load */
+	load_plugin(file);
+
+	/* Try and reselect the plugin in list */
+	plugs = plugins;
+	while (plugs) {
+		plug = plugs->data;
+		if (!strcmp(file, g_module_name(plug->handle))) {
+			gtk_list_select_item(GTK_LIST(pluglist), g_list_index(plugins, plug));
+			return;
+		}
+		plugs = plugs->next;
+	}
+}
+
 void list_clicked(GtkWidget *w, struct gaim_plugin *p)
 {
 	gchar *temp;
@@ -486,22 +531,26 @@
 
 	if (confighandle != 0)
 		gtk_signal_disconnect(GTK_OBJECT(config), confighandle);
+
 	text_len = gtk_text_get_length(GTK_TEXT(plugtext));
 	gtk_text_set_point(GTK_TEXT(plugtext), 0);
 	gtk_text_forward_delete(GTK_TEXT(plugtext), text_len);
 
-	temp = g_strdup_printf("%s\n%s", p->name, p->description);
+	temp = g_strdup_printf("Name:   %s\n\nDescription:\n%s",
+			       (p->name != NULL) ? p->name : "",
+			       (p->description != NULL) ? p->description : "");
 	gtk_text_insert(GTK_TEXT(plugtext), NULL, NULL, NULL, temp, -1);
 	g_free(temp);
+	gtk_entry_set_text(GTK_ENTRY(plugentry), g_module_name(p->handle));
 
 	/* Find out if this plug-in has a configuration function */
 	if (g_module_symbol(p->handle, "gaim_plugin_config", (gpointer *)&gaim_plugin_config)) {
 		confighandle = gtk_signal_connect(GTK_OBJECT(config), "clicked",
 						  GTK_SIGNAL_FUNC(gaim_plugin_config), NULL);
-		gtk_widget_set_sensitive(config, 1);
+		gtk_widget_set_sensitive(config, TRUE);
 	} else {
 		confighandle = 0;
-		gtk_widget_set_sensitive(config, 0);
+		gtk_widget_set_sensitive(config, FALSE);
 	}
 }
 
@@ -514,6 +563,48 @@
 	confighandle = 0;
 }
 
+static const gchar *plugin_makelistname(GModule *module)
+{
+	static gchar filename[PATHSIZE];
+	gchar *filepath = g_module_name(module);
+	char *cp;
+
+	if (filepath == NULL || strlen(filepath) == 0)
+		return NULL;
+	
+	if ((cp = strrchr(filepath, '/')) == NULL || *++cp == '\0')
+		cp = filepath;
+
+	strncpy(filename, cp, sizeof(filename));
+	filename[sizeof(filename) - 1] = '\0';
+
+	/* Try to pretty name by removing any trailing ".so" */
+	if (strlen(filename) > 3 &&
+	    strncmp(filename + strlen(filename) - 3, ".so", 3) == 0)
+		filename[strlen(filename) - 3] = '\0';
+
+	return filename;
+}		
+		
+/* Remove all callbacks associated with plugin handle */
+static void plugin_remove_callbacks(GModule *handle)
+{
+	GList *c = callbacks;
+	struct gaim_callback *g;
+
+	debug_printf("%d callbacks to search\n", g_list_length(callbacks));
+
+	while (c) {
+		g = (struct gaim_callback *)c->data;
+		if (g->handle == handle) {
+			c = g_list_next(c);
+			callbacks = g_list_remove(callbacks, (gpointer)g);
+			debug_printf("Removing callback, %d remain\n", g_list_length(callbacks));
+		} else
+			c = g_list_next(c);
+	}
+}
+
 void gaim_signal_connect(GModule *handle, enum gaim_event which, void *func, void *data)
 {
 	struct gaim_callback *call = g_new0(struct gaim_callback, 1);