changeset 6485:70d5122bc3ff

[gaim-migrate @ 6999] Removed the old event system and replaced it with a much better signal system. There will most likely be some bugs in this, but it seems to be working for now. Plugins can now generate their own signals, and other plugins can find those plugins and connect to them. This could give plugins a form of IPC. It's also useful for other things. It's rather flexible, except for the damn marshalling, but there's no way around that that I or the glib people can see. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Mon, 18 Aug 2003 01:03:43 +0000
parents 5ced8e111473
children fab81e4b885c
files ChangeLog plugins/Makefile.am plugins/autorecon.c plugins/docklet/docklet.c plugins/events.c plugins/gaiminc.c plugins/gestures/gestures.c plugins/history.c plugins/iconaway.c plugins/mailchk.c plugins/notify.c plugins/perl/perl.c plugins/signals-test.c plugins/spellchk.c plugins/statenotify.c plugins/ticker/ticker.c plugins/timestamp.c src/Makefile.am src/account.c src/account.h src/blist.c src/blist.h src/connection.c src/connection.h src/conversation.c src/conversation.h src/core.c src/event.c src/event.h src/gtkaccount.c src/gtkconv.c src/gtkutils.c src/idle.c src/plugin.c src/plugin.h src/server.c src/session.c src/signals.c src/signals.h
diffstat 39 files changed, 2135 insertions(+), 1139 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Aug 17 17:55:46 2003 +0000
+++ b/ChangeLog	Mon Aug 18 01:03:43 2003 +0000
@@ -1,5 +1,9 @@
 Gaim: The Pimpin' Penguin IM Clone that's good for the soul!
 
+version 0.68:
+	* Removed the old event system and replaced it with a much better
+	  signal system.
+
 version 0.67 (08/14/2003):
 	* Brought back the message notification plugin (Brian Tarricone)
 	  You'll need to reconfigure your settings for this plugin
--- a/plugins/Makefile.am	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/Makefile.am	Mon Aug 18 01:03:43 2003 +0000
@@ -46,7 +46,7 @@
 	mailchk.c \
 	gtik.c \
 	raw.c \
-	events.c \
+	signals-test.c \
 	simple.c \
 	gaim.pl \
 	fortuneprofile.pl
--- a/plugins/autorecon.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/autorecon.c	Mon Aug 18 01:03:43 2003 +0000
@@ -3,6 +3,7 @@
 #include "connection.h"
 #include "debug.h"
 #include "prpl.h"
+#include "signals.h"
 
 #define AUTORECON_PLUGIN_ID "core-autorecon"
 
@@ -72,9 +73,11 @@
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
-	hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free_auto_recon);
+	hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
+								 free_auto_recon);
 
-	gaim_signal_connect(plugin, event_signoff, reconnect, NULL);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
+						plugin, GAIM_CALLBACK(reconnect), NULL);
 
 	return TRUE;
 }
@@ -82,8 +85,6 @@
 static gboolean
 plugin_unload(GaimPlugin *plugin)
 {
-	gaim_signal_disconnect(plugin, event_signoff, reconnect);
-
 	g_hash_table_destroy(hash);
 	hash = NULL;
 
@@ -103,11 +104,11 @@
 	N_("Auto-Reconnect"),                             /**< name           */
 	VERSION,                                          /**< version        */
 	                                                  /**  summary        */
-	N_("When you are kicked offline, this reconnects you."), 
+	N_("When you are kicked offline, this reconnects you."),
 	                                                  /**  description    */
-	N_("When you are kicked offline, this reconnects you."), 
+	N_("When you are kicked offline, this reconnects you."),
 	"Eric Warmenhoven <eric@warmenhoven.org>",        /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
+	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
 	plugin_unload,                                    /**< unload         */
--- a/plugins/docklet/docklet.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/docklet/docklet.c	Mon Aug 18 01:03:43 2003 +0000
@@ -1,11 +1,11 @@
-/* 
+/*
  * System tray icon (aka docklet) plugin for Gaim
- * 
+ *
  * Copyright (C) 2002-3 Robert McQueen <robot101@debian.org>
  * Copyright (C) 2003 Herman Bloggs <hermanator12002@yahoo.com>
  * Inspired by a similar plugin by:
  *  John (J5) Palmieri <johnp@martianrock.com>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -15,7 +15,7 @@
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -35,6 +35,7 @@
 #include "core.h"
 #include "debug.h"
 #include "prefs.h"
+#include "signals.h"
 #include "sound.h"
 
 #include "gtkaccount.h"
@@ -372,24 +373,27 @@
 }
 
 static void
-gaim_away(GaimConnection *gc, char *state, char *message, void *data)
+gaim_away(GaimAccount *account, char *state, char *message, void *data)
 {
 	/* we only support global away. this is the way it is, ok? */
 	docklet_update_status();
 }
 
-static void
-gaim_im_recv(GaimConnection *gc, char **who, char **what, void *data)
+static gboolean
+gaim_im_recv(GaimAccount *account, GaimConversation *conv, char **who,
+			 char **what, int *flags, void *data)
 {
 	/* if message queuing while away is enabled, this event could be the first
 	   message so we need to see if the status (and hence icon) needs changing.
 	   do this when idle so that all message processing is completed, queuing
 	   etc, before we run. */
 	g_idle_add(docklet_update_status, &handle);
+
+	return FALSE;
 }
 
 static void
-gaim_new_conversation(char *who, void *data)
+gaim_new_conversation(GaimConversation *conv, void *data)
 {
 	/* queue a callback here so if the queue is being
 	   flushed, we stop flashing. thanks javabsp. */
@@ -415,6 +419,10 @@
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
+	void *conn_handle = gaim_connections_get_handle();
+	void *conv_handle = gaim_conversations_get_handle();
+	void *accounts_handle = gaim_accounts_get_handle();
+
 	gaim_debug(GAIM_DEBUG_INFO, "tray icon", "plugin loaded\n");
 
 	handle = plugin;
@@ -423,12 +431,19 @@
 	if (ui_ops->create)
 		ui_ops->create();
 
-	gaim_signal_connect(plugin, event_signon, gaim_signon, NULL);
-	gaim_signal_connect(plugin, event_signoff, gaim_signoff, NULL);
-	gaim_signal_connect(plugin, event_connecting, gaim_connecting, NULL);
-	gaim_signal_connect(plugin, event_away, gaim_away, NULL);
-	gaim_signal_connect(plugin, event_im_recv, gaim_im_recv, NULL);
-	gaim_signal_connect(plugin, event_new_conversation, gaim_new_conversation, NULL);
+	gaim_signal_connect(conn_handle, "signed-on",
+						plugin, GAIM_CALLBACK(gaim_signon), NULL);
+	gaim_signal_connect(conn_handle, "signed-off",
+						plugin, GAIM_CALLBACK(gaim_signoff), NULL);
+	gaim_signal_connect(accounts_handle, "account-connecting",
+						plugin, GAIM_CALLBACK(gaim_connecting), NULL);
+	gaim_signal_connect(accounts_handle, "account-away",
+						plugin, GAIM_CALLBACK(gaim_away), NULL);
+	gaim_signal_connect(conv_handle, "received-im-msg",
+						plugin, GAIM_CALLBACK(gaim_im_recv), NULL);
+	gaim_signal_connect(conv_handle, "conversation-created",
+						plugin, GAIM_CALLBACK(gaim_new_conversation), NULL);
+
 /*	gaim_signal_connect(plugin, event_buddy_signon, gaim_buddy_signon, NULL);
 	gaim_signal_connect(plugin, event_buddy_signoff, gaim_buddy_signoff, NULL);
 	gaim_signal_connect(plugin, event_buddy_away, gaim_buddy_away, NULL);
--- a/plugins/events.c	Sun Aug 17 17:55:46 2003 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/* events.c
- *
- * test every callback, print to stdout
- *
- * by EW
- *
- * GPL and all that jazz
- *
- */
-
-#define EVENTTEST_PLUGIN_ID "core-eventtest"
-
-#include <stdio.h>
-
-#include "gtkplugin.h"
-#include "connection.h"
-#include "conversation.h"
-#include "internal.h"
-
-static void evt_signon(GaimConnection *gc, void *data)
-{
-	printf("event_signon\n");
-}
-
-static void evt_signoff(GaimConnection *gc, void *data)
-{
-	printf("event_signoff\n");
-}
-
-static void evt_away(GaimConnection *gc, char *state, char *message, void *data)
-{
-	printf("event_away: %s %s %s\n", gaim_account_get_username(gaim_connection_get_account(gc)),
-		state, message);
-}
-
-static void evt_back(void *data)
-{
-	printf("event_back\n");
-}
-
-static void evt_im_recv(GaimConnection *gc, char **who, char **what, guint *flags, void *data)
-{
-	printf("event_im_recv: %s %s\n", *who, *what);
-}
-
-static void evt_im_send(GaimConnection *gc, char *who, char **what, void *data)
-{
-	printf("event_im_send: %s %s\n", who, *what);
-}
-
-static void evt_buddy_signon(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_buddy_signon: %s\n", who);
-}
-
-static void evt_buddy_signoff(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_buddy_signoff: %s\n", who);
-}
-
-static void evt_buddy_away(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_buddy_away: %s\n", who);
-}
-
-static void evt_buddy_back(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_buddy_back: %s\n", who);
-}
-
-static void evt_buddy_idle(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_buddy_idle: %s\n", who);
-}
-
-static void evt_buddy_unidle(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_buddy_unidle: %s\n", who);
-}
-
-static void evt_blist_update(void *data)
-{
-	printf("event_blist_update\n");
-}
-
-static void evt_chat_invited(GaimConnection *gc, char *who, char *room, char *message, void *data)
-{
-	printf("event_chat_invited: %s %s %s\n", who, room, message);
-}
-
-static void evt_chat_join(GaimConnection *gc, int id, void *data)
-{
-	printf("event_chat_join: %d\n", id);
-}
-
-static void evt_chat_leave(GaimConnection *gc, int id, void *data)
-{
-	printf("event_chat_leave: %d\n", id);
-}
-
-static void evt_chat_buddy_join(GaimConnection *gc, int id, char *who, void *data)
-{
-	printf("event_chat_buddy_join: %d %s\n", id, who);
-}
-
-static void evt_chat_buddy_leave(GaimConnection *gc, int id, char *who, void *data)
-{
-	printf("event_chat_buddy_leave: %d %s\n", id, who);
-}
-
-static void evt_chat_recv(GaimConnection *gc, int id, char *who, char *text, void *data)
-{
-	printf("event_chat_recv: %d %s %s\n", id, who, text);
-}
-
-static void evt_chat_send(GaimConnection *gc, int id, char **what, void *data)
-{
-	printf("event_chat_send: %d %s\n", id, *what);
-}
-
-static void evt_warned(GaimConnection *gc, char *who, int level, void *data)
-{
-	printf("event_warned: %s %d\n", who, level);
-}
-
-static void evt_error(int error, void *data)
-{
-	printf("event_error: %d\n", error);
-}
-
-static void evt_quit(void *data)
-{
-	printf("event_quit\n");
-}
-
-static void evt_new_conversation(char *who, void *data)
-{
-	printf("event_new_conversation: %s\n", who);
-}
-
-static void evt_set_info(GaimConnection *gc, char *info, void *data)
-{
-	printf("event_set_info: %s\n", info);
-}
-
-static void evt_draw_menu(GtkWidget *menu, char *name, void *data)
-{
-	printf("event_draw_menu: %s\n", name);
-}
-
-static void evt_im_displayed_sent(GaimConnection *gc, char *who, char **what, void *data)
-{
-	printf("event_im_displayed_sent: %s %s\n", who, *what);
-}
-
-static void evt_im_displayed_rcvd(GaimConnection *gc, char *who, char *what, guint32 flags, time_t time, void *data)
-{
-	printf("event_im_displayed_rcvd: %s %s %u %u\n", who, what, flags, time);
-}
-
-static void evt_chat_send_invite(GaimConnection *gc, int id, char *who, char **msg, void *data)
-{
-	printf("event_chat_send_invite: %d %s %s\n", id, who, *msg);
-}
-
-static void evt_got_typing(GaimConnection *gc, char *who, void *data)
-{
-	printf("event_got_typing: %s\n", who);
-}
-
-static void evt_del_conversation(GaimConversation *c, void *data)
-{
-	printf("event_del_conversation\n");
-}
-
-static void evt_connecting(GaimAccount *u, void *data)
-{
-	printf("event_connecting\n");
-}
-
-static void evt_change(GaimConversation *c)
-{
-	printf("event_conversation_switch\n");
-}
-
-/*
- *  EXPORTED FUNCTIONS
- */
-
-static gboolean
-plugin_load(GaimPlugin *plugin)
-{
-	gaim_signal_connect(plugin, event_signon,		evt_signon, NULL);
-	gaim_signal_connect(plugin, event_signoff,		evt_signoff, NULL);
-	gaim_signal_connect(plugin, event_away,		evt_away, NULL);
-	gaim_signal_connect(plugin, event_back,		evt_back, NULL);
-	gaim_signal_connect(plugin, event_im_recv,		evt_im_recv, NULL);
-	gaim_signal_connect(plugin, event_im_send,		evt_im_send, NULL);
-	gaim_signal_connect(plugin, event_buddy_signon,	evt_buddy_signon, NULL);
-	gaim_signal_connect(plugin, event_buddy_signoff,	evt_buddy_signoff, NULL);
-	gaim_signal_connect(plugin, event_buddy_away,	evt_buddy_away, NULL);
-	gaim_signal_connect(plugin, event_buddy_back,	evt_buddy_back, NULL);
-	gaim_signal_connect(plugin, event_chat_invited,	evt_chat_invited, NULL);
-	gaim_signal_connect(plugin, event_chat_join,		evt_chat_join, NULL);
-	gaim_signal_connect(plugin, event_chat_leave,	evt_chat_leave, NULL);
-	gaim_signal_connect(plugin, event_chat_buddy_join,	evt_chat_buddy_join, NULL);
-	gaim_signal_connect(plugin, event_chat_buddy_leave,	evt_chat_buddy_leave, NULL);
-	gaim_signal_connect(plugin, event_chat_recv,		evt_chat_recv, NULL);
-	gaim_signal_connect(plugin, event_chat_send,		evt_chat_send, NULL);
-	gaim_signal_connect(plugin, event_warned,		evt_warned, NULL);
-	gaim_signal_connect(plugin, event_error,		evt_error, NULL);
-	gaim_signal_connect(plugin, event_quit,		evt_quit, NULL);
-	gaim_signal_connect(plugin, event_new_conversation,	evt_new_conversation, NULL);
-	gaim_signal_connect(plugin, event_set_info,		evt_set_info, NULL);
-	gaim_signal_connect(plugin, event_draw_menu,		evt_draw_menu, NULL);
-	gaim_signal_connect(plugin, event_im_displayed_sent,	evt_im_displayed_sent, NULL);
-	gaim_signal_connect(plugin, event_im_displayed_rcvd, evt_im_displayed_rcvd, NULL);
-	gaim_signal_connect(plugin, event_chat_send_invite,	evt_chat_send_invite, NULL);
-	gaim_signal_connect(plugin, event_got_typing, 	evt_got_typing, NULL);
-	gaim_signal_connect(plugin, event_del_conversation,	evt_del_conversation, NULL);
-	gaim_signal_connect(plugin, event_connecting,	evt_connecting, NULL);
-	gaim_signal_connect(plugin, event_conversation_switch, evt_change, NULL);
-	return TRUE;
-}
-
-static GaimPluginInfo info =
-{
-	2,                                                /**< api_version    */
-	GAIM_PLUGIN_STANDARD,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	GAIM_PRIORITY_DEFAULT,                            /**< priority       */
-
-	EVENTTEST_PLUGIN_ID,                              /**< id             */
-	N_("Event Test"),                                 /**< name           */
-	VERSION,                                          /**< version        */
-	                                                  /**  summary        */
-	N_("Test to see that all events are working properly."),
-	                                                  /**  description    */
-	N_("Test to see that all events are working properly."),
-	"Eric Warmenhoven <eric@warmenhoven.org>",        /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
-
-	plugin_load,                                      /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
-
-	NULL,                                             /**< ui_info        */
-	NULL                                              /**< extra_info     */
-};
-
-static void
-init_plugin(GaimPlugin *plugin)
-{
-}
-
-GAIM_INIT_PLUGIN(eventtester, init_plugin, info)
--- a/plugins/gaiminc.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/gaiminc.c	Mon Aug 18 01:03:43 2003 +0000
@@ -7,12 +7,16 @@
 
 #define GAIMINC_PLUGIN_ID "core-gaiminc"
 
-void echo_hi(void *m) {
+static void
+echo_hi(void *m)
+{
 	/* this doesn't do much, just lets you know who we are :) */
 	show_about(NULL, NULL);
 }
 
-void reverse(struct gaim_connection *gc, char **who, char **message, void *m) {
+static void
+reverse(struct gaim_connection *gc, char **who, char **message, void *m)
+{
 	/* this will drive you insane. whenever you receive a message,
 	 * the text of the message (HTML and all) will be reversed. */
 	int i, l;
@@ -34,7 +38,9 @@
 	}
 }
 
-void bud(struct gaim_connection *gc, char *who, void *m) {
+static void
+bud(struct gaim_connection *gc, char *who, void *m)
+{
 	/* whenever someone comes online, it sends them a message. if i
 	 * cared more, i'd make it so it popped up on your screen too */
 	serv_send_im(gc, who, "Hello!", -1, 0);
@@ -48,13 +54,16 @@
 plugin_load(GaimPlugin *plugin)
 {
 	/* this is for doing something fun when we sign on */
-	gaim_signal_connect(plugin, event_signon, echo_hi, NULL);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
+						plugin, GAIM_CALLBACK(echo_hi), NULL);
 
 	/* this is for doing something fun when we get a message */
-	gaim_signal_connect(plugin, event_im_recv, reverse, NULL);
+	gaim_signal_connect(gaim_conversations_get_handle(), "received-im",
+						plugin, GAIM_CALLBACK(reverse), NULL);
 
 	/* this is for doing something fun when a buddy comes online */
-	gaim_signal_connect(plugin, event_buddy_signon, bud, NULL);
+	gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on",
+						plugin, GAIM_CALLBACK(bud), NULL);
 
 	return TRUE;
 }
@@ -80,10 +89,10 @@
 	   "- It sends a message to people on your list immediately"
 	   " when they sign on"),
 	"Eric Warmenhoven <eric@warmenhoven.org>",        /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
+	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
-	NULL,                                    /**< unload         */
+	NULL,                                             /**< unload         */
 	NULL,                                             /**< destroy        */
 
 	NULL,                                             /**< ui_info        */
--- a/plugins/gestures/gestures.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/gestures/gestures.c	Mon Aug 18 01:03:43 2003 +0000
@@ -2,7 +2,7 @@
  * Mouse gestures plugin for Gaim
  *
  * Copyright (C) 2003 Christian Hammond.
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -12,7 +12,7 @@
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -23,6 +23,7 @@
 
 #include "debug.h"
 #include "prefs.h"
+#include "signals.h"
 
 #include "gtkconv.h"
 #include "gtkplugin.h"
@@ -127,16 +128,10 @@
 }
 
 static void
-new_conv_cb(char *who)
+new_conv_cb(GaimConversation *conv)
 {
-	GaimConversation *conv;
-
-	conv = gaim_find_conversation(who);
-
-	if (conv == NULL || !GAIM_IS_GTK_CONVERSATION(conv))
-		return;
-
-	attach_signals(conv);
+	if (GAIM_IS_GTK_CONVERSATION(conv))
+		attach_signals(conv);
 }
 
 #if 0
@@ -178,7 +173,9 @@
 		attach_signals(conv);
 	}
 
-	gaim_signal_connect(plugin, event_new_conversation, new_conv_cb, NULL);
+	gaim_signal_connect(gaim_conversations_get_handle(),
+						"conversation-created",
+						plugin, GAIM_CALLBACK(new_conv_cb), NULL);
 
 	return TRUE;
 }
--- a/plugins/history.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/history.c	Mon Aug 18 01:03:43 2003 +0000
@@ -6,6 +6,7 @@
 #include "conversation.h"
 #include "debug.h"
 #include "prefs.h"
+#include "signals.h"
 #include "util.h"
 
 #include "gtkconv.h"
@@ -16,10 +17,10 @@
 
 #define HISTORY_SIZE (4 * 1024)
 
-void historize (char *name, void *data)
+static void historize(GaimConversation *c)
 {
-	GaimConversation *c = gaim_find_conversation(name);
 	GaimGtkConversation *gtkconv;
+	const char *name = gaim_conversation_get_name(c);
 	struct stat st;
 	FILE *fd;
 	char *userdir = g_strdup(gaim_user_dir());
@@ -30,7 +31,7 @@
 	int size;
 	GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS;
 
-	if (stat(path, &st) || S_ISDIR(st.st_mode) || st.st_size == 0 || 
+	if (stat(path, &st) || S_ISDIR(st.st_mode) || st.st_size == 0 ||
 	    !(fd = fopen(path, "r"))) {
 		g_free(userdir);
 		g_free(logfile);
@@ -70,7 +71,9 @@
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
-	gaim_signal_connect(plugin, event_new_conversation, historize, NULL);
+	gaim_signal_connect(gaim_conversations_get_handle(),
+						"conversation-created",
+						plugin, GAIM_CALLBACK(historize), NULL);
 
 	return TRUE;
 }
--- a/plugins/iconaway.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/iconaway.c	Mon Aug 18 01:03:43 2003 +0000
@@ -1,6 +1,7 @@
 #include "gtkinternal.h"
 
 #include "conversation.h"
+#include "signals.h"
 
 #include "gtkconv.h"
 #include "gtkplugin.h"
@@ -17,10 +18,14 @@
 extern void applet_destroy_buddy();
 #endif
 
-void iconify_windows(GaimConnection *gc, char *state,
-					 char *message, void *data) {
+static void
+iconify_windows(GaimAccount *account, char *state, char *message, void *data)
+{
 	GaimWindow *win;
 	GList *windows;
+	GaimConnection *gc;
+
+	gc = gaim_account_get_connection(account);
 
 	if (!imaway || !gc->away)
 		return;
@@ -51,7 +56,8 @@
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
-	gaim_signal_connect(plugin, event_away, iconify_windows, NULL);
+	gaim_signal_connect(gaim_accounts_get_handle(), "account-away",
+						plugin, GAIM_CALLBACK(iconify_windows), NULL);
 
 	return TRUE;
 }
@@ -78,7 +84,7 @@
 	                                                  /**  description    */
 	N_("Iconifies the buddy list and your conversations when you go away."),
 	"Eric Warmenhoven <eric@warmenhoven.org>",        /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
+	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
 	NULL,                                             /**< unload         */
--- a/plugins/mailchk.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/mailchk.c	Mon Aug 18 01:03:43 2003 +0000
@@ -113,6 +113,8 @@
 plugin_load(GaimPlugin *plugin)
 {
 	struct gaim_buddy_list *list = gaim_get_blist();
+	void *conn_handle = gaim_connections_get_handle();
+
 	if (!check_timeout(NULL)) {
 		gaim_debug(GAIM_DEBUG_WARNING, "mailchk", "Could not read $MAIL or /var/spool/mail/$USER");
 		return FALSE;
@@ -121,8 +123,10 @@
 	if (list && GAIM_IS_GTK_BLIST(list) && GAIM_GTK_BLIST(list)->vbox)
 		timer = g_timeout_add(2000, check_timeout, NULL);
 
-	gaim_signal_connect(plugin, event_signon, signon_cb, NULL);
-	gaim_signal_connect(plugin, event_signoff, signoff_cb, NULL);
+	gaim_signal_connect(conn_handle, "signed-on",
+						plugin, GAIM_CALLBACK(signon_cb), NULL);
+	gaim_signal_connect(conn_handle, "signed-off",
+						plugin, GAIM_CALLBACK(signoff_cb), NULL);
 
 	return TRUE;
 }
--- a/plugins/notify.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/notify.c	Mon Aug 18 01:03:43 2003 +0000
@@ -36,12 +36,12 @@
  *  -Added apply button to change the denotification methods for
  *   open conversation windows
  *  -Fixed apply to conversations, count now keeps count across applies
- *  -Fixed(?) memory leak, and in the process fixed some stupidities 
+ *  -Fixed(?) memory leak, and in the process fixed some stupidities
  *  -Hit enter when done editing the title string entry box to save it
  *
  * Thanks to Carles Pina i Estany <carles@pinux.info>
  *   for count of new messages option
- * 
+ *
  * From Brian, 20 July 2003:
  *  -Use new xml prefs
  *  -Better handling of notification states tracking
@@ -57,12 +57,12 @@
 #include "debug.h"
 #include "notify.h"
 #include "prefs.h"
+#include "signals.h"
 
 #include "gtkconv.h"
 #include "gtkplugin.h"
 #include "gtkutils.h"
 
-
 #include "gtkplugin.h"
 
 #include <string.h>
@@ -151,7 +151,7 @@
 
 	XGetInputFocus(GDK_WINDOW_XDISPLAY(gtkwin->window->window), &focus_return, &revert_to_return);
 
-	if ((notify_opts & OPT_NOTIFY_IN_FOCUS) || 
+	if ((notify_opts & OPT_NOTIFY_IN_FOCUS) ||
 		(focus_return != GDK_WINDOW_XWINDOW(gtkwin->window->window))) {
 		if (notify_opts & OPT_METHOD_STRING)
 			string_add(gtkwin->window);
@@ -199,36 +199,34 @@
 	return 0;
 }
 
-static void chat_recv_im(GaimConnection *gc, int id, char **who, char **text) {
-	GaimConversation *c = gaim_find_chat(gc, id);
+static gboolean
+chat_recv_im(GaimAccount *account, GaimConversation *conv, char **who,
+			 char **text)
+{
+	if (conv)
+		notify(conv);
 
-	if (c)
-		notify(c);
-	return;
+	return FALSE;
 }
 
-static void chat_sent_im(GaimConnection *gc, int id, char **text) {
-	GaimConversation *c = gaim_find_chat(gc, id);
-
+static void chat_sent_im(GaimConversation *c, char **text) {
 	if (c)
 		unnotify(c);
-	return;
 }
 
-static int im_recv_im(GaimConnection *gc, char **who, char **what, void *m) {
-	GaimConversation *c = gaim_find_conversation(*who);
+static gboolean
+im_recv_im(GaimAccount *account, GaimConversation *conv, char **who,
+		   char **what, int *flags, void *m)
+{
+	if (conv)
+		notify(conv);
 
-	if (c)
-		notify(c);
-	return 0;
+	return FALSE;
 }
 
-static int im_sent_im(GaimConnection *gc, char *who, char **what, void *m) {
-	GaimConversation *c = gaim_find_conversation(who);
-
-	if (c)
-		unnotify(c);
-	return 0;
+static void im_sent_im(GaimConversation *conv, char **what, void *m) {
+	if (conv)
+		unnotify(conv);
 }
 
 static int attach_signals(GaimConversation *c) {
@@ -258,10 +256,10 @@
 static void detach_signals(GaimConversation *c) {
 	GaimGtkConversation *gtkconv;
 	GaimGtkWindow *gtkwin;
-	
+
 	gtkconv = GAIM_GTK_CONVERSATION(c);
 	gtkwin  = GAIM_GTK_WINDOW(gaim_conversation_get_window(c));
-	
+
 	if (notify_opts & OPT_NOTIFY_FOCUS) {
 		g_signal_handlers_disconnect_by_func(G_OBJECT(gtkwin->window), unnotify_cb, NULL);
 	}
@@ -277,8 +275,8 @@
 	}
 }
 
-static void new_conv(char *who) {
-	GaimConversation *c = gaim_find_conversation(who);
+static void new_conv(GaimConversation *c)
+{
 	GaimGtkWindow *gtkwin  = GAIM_GTK_WINDOW(gaim_conversation_get_window(c));
 
 	g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0));
@@ -288,8 +286,7 @@
 		attach_signals(c);
 }
 
-static void chat_join(GaimConnection *gc, int id, char *room) {
-	GaimConversation *c = gaim_find_chat(gc, id);
+static void chat_join(GaimConversation *c) {
 	GaimGtkWindow *gtkwin  = GAIM_GTK_WINDOW(gaim_conversation_get_window(c));
 
 	g_object_set_data(G_OBJECT(gtkwin->window), GDATASTR, GINT_TO_POINTER((guint)0));
@@ -358,10 +355,10 @@
 			strncpy(newtitle+len1, curtitle+len1+strlen(title_string), sizeof(newtitle)-len1);
 		} else if (opts & OPT_METHOD_QUOTE) {
 			g_snprintf(newtitle, sizeof(newtitle), "\"%s", curtitle+strlen(title_string)+1);
-		} else 
+		} else
 			strncpy(newtitle, curtitle+strlen(title_string), sizeof(newtitle));
 		}
-		
+
 		gtk_window_set_title(win, newtitle);
 		gaim_debug(GAIM_DEBUG_INFO, "notify.c", "removed string from window title (title now %s)\n", newtitle);
 }
@@ -534,7 +531,7 @@
 	gaim_prefs_set_bool("/plugins/gtk/X11/notify/type_chat", notify_opts & OPT_TYPE_CHAT);
 	gaim_prefs_set_bool("/plugins/gtk/X11/notify/type_focused", notify_opts & OPT_NOTIFY_IN_FOCUS);
 	gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_focus", notify_opts & OPT_NOTIFY_FOCUS);
-	gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_click", notify_opts & OPT_NOTIFY_CLICK);	
+	gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_click", notify_opts & OPT_NOTIFY_CLICK);
 	gaim_prefs_set_bool("/plugins/gtk/X11/notify/notify_type", notify_opts & OPT_NOTIFY_TYPE);
 	gaim_prefs_set_bool("/plugins/gtk/X11/notify/method_string", notify_opts & OPT_METHOD_STRING);
 	gaim_prefs_set_bool("/plugins/gtk/X11/notify/method_quote", notify_opts & OPT_METHOD_QUOTE);
@@ -546,12 +543,12 @@
 
 static void load_notify_prefs() {
 	notify_opts = 0;
-	
+
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_im") ? OPT_TYPE_IM : 0);
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_chat") ? OPT_TYPE_CHAT : 0);
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/type_focused") ? OPT_NOTIFY_IN_FOCUS : 0);
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_focus") ? OPT_NOTIFY_FOCUS : 0);
-	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_click") ? OPT_NOTIFY_CLICK : 0);	
+	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_click") ? OPT_NOTIFY_CLICK : 0);
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/notify_type") ? OPT_NOTIFY_TYPE : 0);
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_string") ? OPT_METHOD_STRING : 0);
 	notify_opts |= (gaim_prefs_get_bool("/plugins/gtk/X11/notify/method_quote") ? OPT_METHOD_QUOTE : 0);
@@ -625,7 +622,7 @@
 				(gaim_conversation_get_type(c)==GAIM_CONV_CHAT && (notify_opts & OPT_TYPE_CHAT))) {
 				Window focus_return;
 				int revert_to_return;
-				
+
 				XGetInputFocus(GDK_WINDOW_XDISPLAY(gtkwin->window->window),
 						&focus_return, &revert_to_return);
 				if ((notify_opts & OPT_NOTIFY_IN_FOCUS) ||
@@ -778,17 +775,24 @@
 plugin_load(GaimPlugin *plugin)
 {
 	GList *cnv = gaim_get_conversations();
+	void *conv_handle = gaim_conversations_get_handle();
 
 	my_plugin = plugin;
 
 	load_notify_prefs();
 
-	gaim_signal_connect(plugin, event_im_recv, im_recv_im, NULL);
-	gaim_signal_connect(plugin, event_chat_recv, chat_recv_im, NULL);
-	gaim_signal_connect(plugin, event_im_send, im_sent_im, NULL);
-	gaim_signal_connect(plugin, event_chat_send, chat_sent_im, NULL);
-	gaim_signal_connect(plugin, event_new_conversation, new_conv, NULL);
-	gaim_signal_connect(plugin, event_chat_join, chat_join, NULL);
+	gaim_signal_connect(conv_handle, "received-im-msg",
+						plugin, GAIM_CALLBACK(im_recv_im), NULL);
+	gaim_signal_connect(conv_handle, "received-chat-msg",
+						plugin, GAIM_CALLBACK(chat_recv_im), NULL);
+	gaim_signal_connect(conv_handle, "sent-im-msg",
+						plugin, GAIM_CALLBACK(im_sent_im), NULL);
+	gaim_signal_connect(conv_handle, "sent-chat-msg",
+						plugin, GAIM_CALLBACK(chat_sent_im), NULL);
+	gaim_signal_connect(conv_handle, "conversation-created",
+						plugin, GAIM_CALLBACK(new_conv), NULL);
+	gaim_signal_connect(conv_handle, "chat-joined",
+						plugin, GAIM_CALLBACK(chat_join), NULL);
 
 	while (cnv) {
 		GaimConversation *c = (GaimConversation *)cnv->data;
@@ -850,7 +854,7 @@
 	N_("Provides a variety of ways of notifying you of unread messages."),
 	"Etan Reisner <deryni@eden.rutgers.edu>\n\t\t\tBrian Tarricone <bjt23@cornell.edu",
 	                                                  /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
+	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
 	plugin_unload,                                    /**< unload         */
--- a/plugins/perl/perl.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/perl/perl.c	Mon Aug 18 01:03:43 2003 +0000
@@ -190,6 +190,70 @@
 	newXS ("GAIM::play_sound", XS_GAIM_play_sound, "GAIM");
 }
 
+#if 0
+#define COMPARE_EVENT(evt, sig, h) \
+	if (!strcmp(event_name, (evt))) \
+	{ \
+		*signal_name = (sig); \
+		*handle = (h); \
+		return TRUE; \
+	}
+
+static gboolean
+convert_event_to_signal(const char *event_name, const char **signal_name,
+						void **handle)
+{
+	void *conn_handle    = gaim_connections_get_handle();
+	void *account_handle = gaim_accounts_get_handle();
+	void *conv_handle    = gaim_conversations_get_handle();
+	void *blist_handle   = gaim_get_blist();
+
+	COMPARE_EVENT("event_signon",  "signed-on",   conn_handle);
+	COMPARE_EVENT("event_signoff", "signed-off",  conn_handle);
+
+	COMPARE_EVENT("event_away",       "account-away",       account_handle);
+	COMPARE_EVENT("event_back",       "account-back",       account_handle);
+	COMPARE_EVENT("event_warned",     "account-warned",     account_handle);
+	COMPARE_EVENT("event_set_info",   "account-set-info",   account_handle);
+	COMPARE_EVENT("event_connecting", "account-connecting", account_handle);
+
+	COMPARE_EVENT("event_im_recv",          "received-im-msg",   conv_handle);
+	COMPARE_EVENT("event_im_send",          "sent-im-msg",       conv_handle);
+	COMPARE_EVENT("event_chat_invited",     "chat-invited",      conv_handle);
+	COMPARE_EVENT("event_chat_join",        "chat-joined",       conv_handle);
+	COMPARE_EVENT("event_chat_leave",       "chat-left",         conv_handle);
+	COMPARE_EVENT("event_chat_buddy_join",  "chat-buddy-joined", conv_handle);
+	COMPARE_EVENT("event_chat_buddy_leave", "chat-buddy-left",   conv_handle);
+	COMPARE_EVENT("event_chat_recv",        "received-chat-msg", conv_handle);
+	COMPARE_EVENT("event_chat_send",        "sent-chat-msg",     conv_handle);
+	COMPARE_EVENT("event_new_conversation", "conversation-created",
+				  conv_handle);
+	COMPARE_EVENT("event_im_displayed_sent", "sending-im-msg", conv_handle);
+	COMPARE_EVENT("event_im_displayed_rcvd", NULL, NULL);
+	COMPARE_EVENT("event_chat_send_invite", "chat-inviting-user", conv_handle);
+	COMPARE_EVENT("event_got_typing", "buddy-typing", conv_handle);
+	COMPARE_EVENT("event_del_conversation", "deleting-conversation",
+				  conv_handle);
+	COMPARE_EVENT("event_conversation_switch", "conversation-switched",
+				  conv_handle);
+
+	COMPARE_EVENT("event_buddy_signon",  "buddy-signed-on",  blist_handle);
+	COMPARE_EVENT("event_buddy_signoff", "buddy-signed-off", blist_handle);
+	COMPARE_EVENT("event_buddy_away",    "buddy-away",       blist_handle);
+	COMPARE_EVENT("event_buddy_back",    "buddy-back",       blist_handle);
+	COMPARE_EVENT("event_buddy_idle",    "buddy-idle",       blist_handle);
+	COMPARE_EVENT("event_buddy_unidle",  "buddy-unidle",     blist_handle);
+	COMPARE_EVENT("event_blist_update",  "update-idle",      blist_handle);
+
+	COMPARE_EVENT("event_quit", "quitting", gaim_get_core());
+
+	*signal_name = NULL;
+	*handle = NULL;
+
+	return FALSE;
+}
+#endif
+
 static char *
 escape_quotes(const char *buf)
 {
@@ -216,9 +280,9 @@
 
 /*
   2003/02/06: execute_perl modified by Mark Doliner <mark@kingant.net>
-		Pass parameters by pushing them onto the stack rather than 
-		passing an array of strings.  This way, perl scripts can 
-		modify the parameters and we can get the changed values 
+		Pass parameters by pushing them onto the stack rather than
+		passing an array of strings.  This way, perl scripts can
+		modify the parameters and we can get the changed values
 		and then shoot ourselves.  I mean, uh, use them.
 
   2001/06/14: execute_perl replaced by Martin Persson <mep@passagen.se>
@@ -227,10 +291,10 @@
 
   30/11/2002: execute_perl modified by Eric Timme <timothy@voidnet.com>
 		args changed to char** so that we can have preparsed
-  		arguments again, and many headaches ensued! This essentially 
-		means we replaced one hacked method with a messier hacked 
-		method out of perceived necessity. Formerly execute_perl 
-		required a single char_ptr, and it would insert it into an 
+  		arguments again, and many headaches ensued! This essentially
+		means we replaced one hacked method with a messier hacked
+		method out of perceived necessity. Formerly execute_perl
+		required a single char_ptr, and it would insert it into an
 		array of character pointers and NULL terminate the new array.
 		Now we have to pass in pre-terminated character pointer arrays
 		to accomodate functions that want to pass in multiple arguments.
@@ -238,7 +302,7 @@
 		Previously arguments were preparsed because an argument list
 		was constructed in the form 'arg one','arg two' and was
 		executed via a call like &funcname(arglist) (see .59.x), so
-		the arglist was magically pre-parsed because of the method. 
+		the arglist was magically pre-parsed because of the method.
 		With Martin Persson's change to perl_call we now need to
 		use a null terminated list of character pointers for arguments
 		if we wish them to be parsed. Lacking a better way to allow
@@ -255,7 +319,7 @@
 		of time.
 */
 
-static int 
+static int
 execute_perl(const char *function, int argc, char **args)
 {
 	int count = 0, i, ret_value = 1;
@@ -263,7 +327,7 @@
 	STRLEN na;
 
 	/*
-	 * Set up the perl environment, push arguments onto the 
+	 * Set up the perl environment, push arguments onto the
 	 * perl stack, then call the given function
 	 */
 	dSP;
@@ -351,7 +415,7 @@
 			g_free(scp->name);
 			g_free(scp->version);
 			g_free(scp->shutdowncallback);
-			g_free(scp);	
+			g_free(scp);
 
 			break;
 		}
@@ -414,7 +478,7 @@
 
 		return 0;
 	}
-	
+
 	return ret;
 }
 
@@ -432,7 +496,7 @@
 		   execute the string obtained from the first and holding
 		   the file conents. This allows to have a realy local $/
 		   without introducing temp variables to hold the old
-		   value. Just a question of style:) */ 
+		   value. Just a question of style:) */
 		"sub load_file{"
 		  "my $f_name=shift;"
 		  "local $/=undef;"
@@ -550,7 +614,7 @@
 		scp->name = g_strdup(name);
 		scp->version = g_strdup(ver);
 		scp->shutdowncallback = g_strdup(callback);
-		scp->plug = plug; 
+		scp->plug = plug;
 		perl_list = g_list_append(perl_list, scp);
 		XST_mPV(0, plug->path);
 	}
@@ -823,15 +887,15 @@
 	send = SvIV(ST(1));
 	what = SvPV(ST(2), junk);
 	who = SvPV(ST(3), junk);
-	
+
 	if (!*who) who=NULL;
-	
+
 	switch (send) {
 		case 0: wflags=WFLAG_SEND; break;
 		case 1: wflags=WFLAG_RECV; break;
 		case 2: wflags=WFLAG_SYSTEM; break;
 		default: wflags=WFLAG_RECV;
-	}	
+	}
 
 	c = gaim_find_conversation(nick);
 
@@ -890,14 +954,14 @@
 	else
 		gaim_conversation_set_account(c, gc->account);
 
-	gaim_conversation_write(c, NULL, what, -1, 
+	gaim_conversation_write(c, NULL, what, -1,
 				(WFLAG_SEND | (isauto ? WFLAG_AUTO : 0)), time(NULL));
 	serv_send_im(gc, nick, what, -1, isauto ? IM_FLAG_AWAY : 0);
 	XSRETURN(0);
 }
 
 
-	
+
 XS (XS_GAIM_print_to_chat)
 {
 	GaimConnection *gc;
@@ -931,6 +995,7 @@
 	XSRETURN(0);
 }
 
+#if 0
 static int
 perl_event(GaimEvent event, void *unused, va_list args)
 {
@@ -1146,6 +1211,7 @@
 
 	return 0;
 }
+#endif
 
 XS (XS_GAIM_add_event_handler)
 {
@@ -1156,9 +1222,13 @@
 	GList *p;
 	dXSARGS;
 	items = 0;
-	
+
 	handle = SvPV(ST(0), junk);
 
+	gaim_debug(GAIM_DEBUG_ERROR, "perl",
+			   "Ay, sorry matey. Ye perl scripts are getting "
+			   "events no more. Argh.\n");
+
 	for (p = gaim_plugins_get_all(); p != NULL; p = p->next) {
 		plug = p->data;
 
@@ -1180,7 +1250,7 @@
 				   "Invalid handle (%s) registering perl event handler\n",
 				   handle);
 	}
-	
+
 	XSRETURN_EMPTY;
 }
 
@@ -1234,10 +1304,10 @@
 	char *handle;
 	GaimPlugin *plug;
 	GList *p;
-	
+
 	dXSARGS;
 	items = 0;
-	
+
 	handle = SvPV(ST(0), junk);
 
 	for (p = gaim_plugins_get_all(); p != NULL; p = p->next) {
@@ -1293,7 +1363,7 @@
 
 	perl_construct(prober);
 	perl_parse(prober, xs_init, 2, argv, NULL);
-	
+
 	{
 		dSP;
 		ENTER;
@@ -1382,8 +1452,7 @@
 	probe_perl_plugin,                                /**< probe          */
 	load_perl_plugin,                                 /**< load           */
 	unload_perl_plugin,                               /**< unload         */
-	destroy_perl_plugin,                              /**< destroy        */
-	perl_event                                        /**< broadcast      */
+	destroy_perl_plugin                               /**< destroy        */
 };
 
 static GaimPluginInfo info =
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/signals-test.c	Mon Aug 18 01:03:43 2003 +0000
@@ -0,0 +1,524 @@
+/*
+ * Signals test plugin.
+ *
+ * Copyright (C) 2003 Christian Hammond.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#define SIGNAL_TEST_PLUGIN_ID "core-signals-test"
+
+#include <stdio.h>
+
+#include "internal.h"
+#include "connection.h"
+#include "conversation.h"
+#include "core.h"
+#include "debug.h"
+#include "signals.h"
+
+/**************************************************************************
+ * Account subsystem signal callbacks
+ **************************************************************************/
+static void
+account_connecting_cb(GaimAccount *account, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test", "account-connecting (%s)\n",
+			   gaim_account_get_username(account));
+}
+
+static void
+account_away_cb(GaimAccount *account, const char *state,
+				const char *message, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "account-away (%s, %s, %s)\n",
+			   gaim_account_get_username(account), state, message);
+}
+
+static void
+account_setting_info_cb(GaimAccount *account, const char *info, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "account-setting-info (%s, %s)\n",
+			   gaim_account_get_username(account), info);
+}
+
+static void
+account_set_info_cb(GaimAccount *account, const char *info, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "account-set-info (%s, %s)\n",
+			   gaim_account_get_username(account), info);
+}
+
+static void
+account_warned_cb(GaimAccount *account, const char *warner, int level,
+				  void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "account-warned (%s, %s, %d)\n",
+			   gaim_account_get_username(account), warner, level);
+}
+
+/**************************************************************************
+ * Buddy List subsystem signal callbacks
+ **************************************************************************/
+static void
+buddy_away_cb(struct buddy *buddy, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-away (%s)\n", buddy->name);
+}
+
+static void
+buddy_back_cb(struct buddy *buddy, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-back (%s)\n", buddy->name);
+}
+
+static void
+buddy_idle_cb(struct buddy *buddy, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-idle (%s)\n", buddy->name);
+}
+
+static void
+buddy_unidle_cb(struct buddy *buddy, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-unidle (%s)\n", buddy->name);
+}
+
+static void
+buddy_signed_on_cb(struct buddy *buddy, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-signed-on (%s)\n", buddy->name);
+}
+
+static void
+buddy_signed_off_cb(struct buddy *buddy, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-signed-off (%s)\n", buddy->name);
+}
+
+/**************************************************************************
+ * Connection subsystem signal callbacks
+ **************************************************************************/
+static void
+signing_on_cb(GaimConnection *gc, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "signing-on (%s)\n",
+			   gaim_account_get_username(gaim_connection_get_account(gc)));
+}
+
+static void
+signed_on_cb(GaimConnection *gc, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "signed-on (%s)\n",
+			   gaim_account_get_username(gaim_connection_get_account(gc)));
+}
+
+static void
+signing_off_cb(GaimConnection *gc, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "signing-off (%s)\n",
+			   gaim_account_get_username(gaim_connection_get_account(gc)));
+}
+
+static void
+signed_off_cb(GaimConnection *gc, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "signed-off (%s)\n",
+			   gaim_account_get_username(gaim_connection_get_account(gc)));
+}
+
+/**************************************************************************
+ * Conversation subsystem signal callbacks
+ **************************************************************************/
+static gboolean
+displaying_im_msg_cb(GaimConversation *conv, char **buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "displaying-im-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), *buffer);
+
+	return FALSE;
+}
+
+static void
+displayed_im_msg_cb(GaimConversation *conv, const char *buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "displayed-im-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), buffer);
+}
+
+static gboolean
+sending_im_msg_cb(GaimConversation *conv, char **buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "sending-im-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), *buffer);
+
+	return FALSE;
+}
+
+static void
+sent_im_msg_cb(GaimConversation *conv, const char *buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "sent-im-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), buffer);
+}
+
+static gboolean
+received_im_msg_cb(GaimAccount *account, GaimConversation *conv,
+				   char **sender, char **buffer, int *flags, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "received-im-msg (%s, %s, %s, %s, %d)\n",
+			   gaim_account_get_username(account),
+			   gaim_conversation_get_name(conv), *sender, *buffer, *flags);
+
+	return FALSE;
+}
+
+static gboolean
+displaying_chat_msg_cb(GaimConversation *conv, char **buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "displaying-chat-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), *buffer);
+
+	return FALES;
+}
+
+static void
+displayed_chat_msg_cb(GaimConversation *conv, const char *buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "displayed-chat-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), buffer);
+}
+
+static gboolean
+sending_chat_msg_cb(GaimConversation *conv, char **buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "sending-chat-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), *buffer);
+
+	return FALSE;
+}
+
+static void
+sent_chat_msg_cb(GaimConversation *conv, const char *buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "sent-chat-msg (%s, %s)\n",
+			   gaim_conversation_get_name(conv), buffer);
+}
+
+static gboolean
+received_chat_msg_cb(GaimAccount *account, GaimConversation *conv,
+					 char **sender, char **buffer, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "received-chat-msg (%s, %s, %s, %s)\n",
+			   gaim_account_get_username(account),
+			   gaim_conversation_get_name(conv), *sender, *buffer);
+
+	return FALSE;
+}
+
+static void
+conversation_switching_cb(GaimConversation *old_conv,
+						  GaimConversation *new_conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "conversation-switching (%s, %s)\n",
+			   gaim_conversation_get_name(old_conv),
+			   gaim_conversation_get_name(new_conv));
+}
+
+static void
+conversation_switched_cb(GaimConversation *old_conv,
+						 GaimConversation *new_conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "conversation-switched (%s, %s)\n",
+			   gaim_conversation_get_name(old_conv),
+			   gaim_conversation_get_name(new_conv));
+}
+
+static void
+conversation_created_cb(GaimConversation *conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "conversation-created (%s)\n",
+			   gaim_conversation_get_name(conv));
+}
+
+static void
+deleting_conversation_cb(GaimConversation *conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "deleting-conversation (%s)\n",
+			   gaim_conversation_get_name(conv));
+}
+
+static void
+buddy_typing_cb(GaimConversation *conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "buddy-typing (%s)\n",
+			   gaim_conversation_get_name(conv));
+}
+
+static void
+chat_buddy_joining_cb(GaimConversation *conv, const char *user, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-buddy-joining (%s, %s)\n",
+			   gaim_conversation_get_name(conv), user);
+}
+
+static void
+chat_buddy_joined_cb(GaimConversation *conv, const char *user, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-buddy-joined (%s, %s)\n",
+			   gaim_conversation_get_name(conv), user);
+}
+
+static void
+chat_buddy_leaving_cb(GaimConversation *conv, const char *user,
+					  const char *reason, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-buddy-leaving (%s, %s, %s)\n",
+			   gaim_conversation_get_name(conv), user, reason);
+}
+
+static void
+chat_buddy_left_cb(GaimConversation *conv, const char *user,
+				   const char *reason, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-buddy-left (%s, %s, %s)\n",
+			   gaim_conversation_get_name(conv), user, reason);
+}
+
+static void
+chat_inviting_user_cb(GaimConversation *conv, const char *name,
+					  const char *reason, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-inviting-user (%s, %s, %s)\n",
+			   gaim_conversation_get_name(conv), name, reason);
+}
+
+static void
+chat_invited_user_cb(GaimConversation *conv, const char *name,
+					  const char *reason, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-invited-user (%s, %s, %s)\n",
+			   gaim_conversation_get_name(conv), name, reason);
+}
+
+static void
+chat_invited_cb(GaimAccount *account, const char *inviter,
+				const char *room_name, const char *message, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-invited (%s, %s, %s, %s)\n",
+			   gaim_account_get_username(account), inviter,
+			   room_name, message);
+}
+
+static void
+chat_joined_cb(GaimConversation *conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-joined (%s)\n",
+			   gaim_conversation_get_name(conv));
+}
+
+static void
+chat_left_cb(GaimConversation *conv, void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "chat-left (%s)\n",
+			   gaim_conversation_get_name(conv));
+}
+
+/**************************************************************************
+ * Core signal callbacks
+ **************************************************************************/
+static void
+quitting_cb(void *data)
+{
+	gaim_debug(GAIM_DEBUG_MISC, "signals test",
+			   "quitting ()\n");
+}
+
+/**************************************************************************
+ * Plugin stuff
+ **************************************************************************/
+static gboolean
+plugin_load(GaimPlugin *plugin)
+{
+	void *core_handle = gaim_get_core();
+	void *blist_handle = gaim_blist_get_handle();
+	void *conn_handle = gaim_connections_get_handle();
+	void *conv_handle = gaim_conversations_get_handle();
+	void *accounts_handle = gaim_accounts_get_handle();
+
+	/* Accounts subsystem signals */
+	gaim_signal_connect(accounts_handle, "account-connecting",
+						plugin, GAIM_CALLBACK(account_connecting_cb), NULL);
+	gaim_signal_connect(accounts_handle, "account-away",
+						plugin, GAIM_CALLBACK(account_away_cb), NULL);
+	gaim_signal_connect(accounts_handle, "account-setting-info",
+						plugin, GAIM_CALLBACK(account_setting_info_cb), NULL);
+	gaim_signal_connect(accounts_handle, "account-set-info",
+						plugin, GAIM_CALLBACK(account_set_info_cb), NULL);
+	gaim_signal_connect(accounts_handle, "account-warned",
+						plugin, GAIM_CALLBACK(account_warned_cb), NULL);
+
+	/* Buddy List subsystem signals */
+	gaim_signal_connect(blist_handle, "buddy-away",
+						plugin, GAIM_CALLBACK(buddy_away_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-back",
+						plugin, GAIM_CALLBACK(buddy_back_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-idle",
+						plugin, GAIM_CALLBACK(buddy_idle_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-unidle",
+						plugin, GAIM_CALLBACK(buddy_unidle_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-signed-on",
+						plugin, GAIM_CALLBACK(buddy_signed_on_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-signed-off",
+						plugin, GAIM_CALLBACK(buddy_signed_off_cb), NULL);
+
+	/* Connection subsystem signals */
+	gaim_signal_connect(conn_handle, "signing-on",
+						plugin, GAIM_CALLBACK(signing_on_cb), NULL);
+	gaim_signal_connect(conn_handle, "signed-on",
+						plugin, GAIM_CALLBACK(signed_on_cb), NULL);
+	gaim_signal_connect(conn_handle, "signing-off",
+						plugin, GAIM_CALLBACK(signing_off_cb), NULL);
+	gaim_signal_connect(conn_handle, "signed-off",
+						plugin, GAIM_CALLBACK(signed_off_cb), NULL);
+
+	/* Conversations subsystem signals */
+	gaim_signal_connect(conv_handle, "displaying-im-msg",
+						plugin, GAIM_CALLBACK(displaying_im_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "displayed-img-msg",
+						plugin, GAIM_CALLBACK(displayed_im_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "sending-im-msg",
+						plugin, GAIM_CALLBACK(sending_im_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "sent-im-msg",
+						plugin, GAIM_CALLBACK(sent_im_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "received-im-msg",
+						plugin, GAIM_CALLBACK(received_im_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "displaying-chat-msg",
+						plugin, GAIM_CALLBACK(displaying_chat_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "displayed-chat-msg",
+						plugin, GAIM_CALLBACK(displayed_chat_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "sending-chat-msg",
+						plugin, GAIM_CALLBACK(sending_chat_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "sent-chat-msg",
+						plugin, GAIM_CALLBACK(sent_chat_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "received-chat-msg",
+						plugin, GAIM_CALLBACK(received_chat_msg_cb), NULL);
+	gaim_signal_connect(conv_handle, "conversation-switching",
+						plugin, GAIM_CALLBACK(conversation_switching_cb), NULL);
+	gaim_signal_connect(conv_handle, "conversation-switched",
+						plugin, GAIM_CALLBACK(conversation_switched_cb), NULL);
+	gaim_signal_connect(conv_handle, "conversation-created",
+						plugin, GAIM_CALLBACK(conversation_created_cb), NULL);
+	gaim_signal_connect(conv_handle, "deleting-conversation",
+						plugin, GAIM_CALLBACK(deleting_conversation_cb), NULL);
+	gaim_signal_connect(conv_handle, "buddy-typing",
+						plugin, GAIM_CALLBACK(buddy_typing_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-buddy-joining",
+						plugin, GAIM_CALLBACK(chat_buddy_joining_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-buddy-joined",
+						plugin, GAIM_CALLBACK(chat_buddy_joined_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-buddy-leaving",
+						plugin, GAIM_CALLBACK(chat_buddy_leaving_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-buddy-left",
+						plugin, GAIM_CALLBACK(chat_buddy_left_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-inviting-user",
+						plugin, GAIM_CALLBACK(chat_inviting_user_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-invited-user",
+						plugin, GAIM_CALLBACK(chat_invited_user_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-invited",
+						plugin, GAIM_CALLBACK(chat_invited_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-joined",
+						plugin, GAIM_CALLBACK(chat_joined_cb), NULL);
+	gaim_signal_connect(conv_handle, "chat-left",
+						plugin, GAIM_CALLBACK(chat_left_cb), NULL);
+
+	/* Core signals */
+	gaim_signal_connect(core_handle, "quitting",
+						plugin, GAIM_CALLBACK(quitting_cb), NULL);
+
+	return TRUE;
+}
+
+static GaimPluginInfo info =
+{
+	2,                                                /**< api_version    */
+	GAIM_PLUGIN_STANDARD,                             /**< type           */
+	NULL,                                             /**< ui_requirement */
+	0,                                                /**< flags          */
+	NULL,                                             /**< dependencies   */
+	GAIM_PRIORITY_DEFAULT,                            /**< priority       */
+
+	SIGNAL_TEST_PLUGIN_ID,                            /**< id             */
+	N_("Signals Test"),                               /**< name           */
+	VERSION,                                          /**< version        */
+	                                                  /**  summary        */
+	N_("Test to see that all signals are working properly."),
+	                                                  /**  description    */
+	N_("Test to see that all signals are working properly."),
+	"Christian Hammond <chipx86@gnupdate.org>",       /**< author         */
+	GAIM_WEBSITE,                                     /**< homepage       */
+
+	plugin_load,                                      /**< load           */
+	NULL,                                             /**< unload         */
+	NULL,                                             /**< destroy        */
+
+	NULL,                                             /**< ui_info        */
+	NULL                                              /**< extra_info     */
+};
+
+static void
+init_plugin(GaimPlugin *plugin)
+{
+}
+
+GAIM_INIT_PLUGIN(signalstest, init_plugin, info)
--- a/plugins/spellchk.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/spellchk.c	Mon Aug 18 01:03:43 2003 +0000
@@ -5,6 +5,7 @@
 #include "internal.h"
 
 #include "debug.h"
+#include "signals.h"
 #include "util.h"
 
 #include "gtkplugin.h"
@@ -24,7 +25,10 @@
 static void substitute(char **, int, int, const char *);
 static GtkListStore *model;
 
-static void substitute_words(GaimConnection *gc, char *who, char **message, void *m) {
+static void
+substitute_words(GaimAccount *account, GaimConversation *conv,
+				 char **message, void *data)
+{
 	int i, l;
 	int word;
 	char *tmp;
@@ -258,7 +262,7 @@
 	GSList **list = (GSList **)data;
 	*list = g_slist_append(*list, gtk_tree_path_copy(path) );
 }
-	
+
 
 static void remove_row(void *data1, gpointer data2)
 {
@@ -328,7 +332,7 @@
 		g_free(name);
 		return;
 	}
-	rename(tempfilename, name);	
+	rename(tempfilename, name);
 	g_free(name);
 }
 
@@ -368,10 +372,14 @@
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
+	void *conv_handle = gaim_conversations_get_handle();
+
 	load_conf();
 
-	gaim_signal_connect(plugin, event_im_send, substitute_words, NULL);
-	gaim_signal_connect(plugin, event_chat_send, substitute_words, NULL);
+	gaim_signal_connect(conv_handle, "sending-im-msg",
+						plugin, GAIM_CALLBACK(substitute_words), NULL);
+	gaim_signal_connect(conv_handle, "sending-chat-msg",
+						plugin, GAIM_CALLBACK(substitute_words), NULL);
 
 	return TRUE;
 }
@@ -390,7 +398,7 @@
 
 	ret = gtk_vbox_new(FALSE, 18);
 	gtk_container_set_border_width (GTK_CONTAINER (ret), 12);
-	
+
 	vbox = gaim_gtk_make_frame(ret, _("Text Replacements"));
 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
 	gtk_widget_set_size_request(vbox, 300, -1);
@@ -408,7 +416,7 @@
 	tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
 	/* gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); */
 	gtk_widget_set_size_request(tree, 260,200);
-	
+
 	renderer = gtk_cell_renderer_text_new ();
 	g_object_set (G_OBJECT (renderer),
 		"editable", TRUE,
@@ -459,7 +467,7 @@
 	hbox = gtk_hbox_new(FALSE, 2);
 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 	gtk_widget_show(hbox);
-	
+
 	label = gtk_label_new_with_mnemonic(_("You _type:"));
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
--- a/plugins/statenotify.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/statenotify.c	Mon Aug 18 01:03:43 2003 +0000
@@ -3,21 +3,21 @@
 #include "blist.h"
 #include "conversation.h"
 #include "debug.h"
+#include "signals.h"
 
 static void
-write_status(GaimConnection *gc, char *who, const char *message)
+write_status(struct buddy *buddy, const char *message)
 {
 	GaimConversation *conv;
-	struct buddy *b;
+	const char *who;
 	char buf[256];
 
-	conv = gaim_find_conversation_with_account(who, gc->account);
+	conv = gaim_find_conversation_with_account(buddy->name, buddy->account);
 
 	if (conv == NULL)
 		return;
 
-	if ((b = gaim_find_buddy(gc->account, who)) != NULL)
-		who = gaim_get_buddy_alias(b);
+	who = gaim_get_buddy_alias(buddy);
 
 	g_snprintf(buf, sizeof(buf), "%s %s", who, message);
 
@@ -25,36 +25,42 @@
 }
 
 static void
-buddy_away_cb(GaimConnection *gc, char *who, void *data)
+buddy_away_cb(struct buddy *buddy, void *data)
 {
-	write_status(gc, who, _("has gone away."));
+	write_status(buddy, _("has gone away."));
 }
 
 static void
-buddy_unaway_cb(GaimConnection *gc, char *who, void *data)
+buddy_unaway_cb(struct buddy *buddy, void *data)
 {
-	write_status(gc, who, _("is no longer away."));
+	write_status(buddy, _("is no longer away."));
 }
 
 static void
-buddy_idle_cb(GaimConnection *gc, char *who, void *data)
+buddy_idle_cb(struct buddy *buddy, void *data)
 {
-	write_status(gc, who, _("has become idle."));
+	write_status(buddy, _("has become idle."));
 }
 
 static void
-buddy_unidle_cb(GaimConnection *gc, char *who, void *data)
+buddy_unidle_cb(struct buddy *buddy, void *data)
 {
-	write_status(gc, who, _("is no longer idle."));
+	write_status(buddy, _("is no longer idle."));
 }
 
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
-	gaim_signal_connect(plugin, event_buddy_away,   buddy_away_cb,   NULL);
-	gaim_signal_connect(plugin, event_buddy_back,   buddy_unaway_cb, NULL);
-	gaim_signal_connect(plugin, event_buddy_idle,   buddy_idle_cb,   NULL);
-	gaim_signal_connect(plugin, event_buddy_unidle, buddy_unidle_cb, NULL);
+	void *blist_handle = gaim_blist_get_handle();
+
+	gaim_signal_connect(blist_handle, "buddy-away",
+						plugin, GAIM_CALLBACK(buddy_away_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-back",
+						plugin, GAIM_CALLBACK(buddy_unaway_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-idle",
+						plugin, GAIM_CALLBACK(buddy_idle_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-unidle",
+						plugin, GAIM_CALLBACK(buddy_unidle_cb), NULL);
 
 	return TRUE;
 }
@@ -78,7 +84,7 @@
 	N_("Notifies in a conversation window when a buddy goes or returns from "
 	   "away or idle."),
 	"Christian Hammond <chipx86@gnupdate.org>",       /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
+	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
 	NULL,                                             /**< unload         */
--- a/plugins/ticker/ticker.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/ticker/ticker.c	Mon Aug 18 01:03:43 2003 +0000
@@ -31,6 +31,7 @@
 #include "conversation.h"
 #include "debug.h"
 #include "prpl.h"
+#include "signals.h"
 
 #include "gtkblist.h"
 #include "gtkplugin.h"
@@ -204,7 +205,9 @@
 	}
 }
 
-void signoff_cb(GaimConnection *gc) {
+static void
+signoff_cb(GaimConnection *gc)
+{
 	TickerData *td;
 	if (!gaim_connections_get_all()) {
 		while (tickerbuds) {
@@ -232,23 +235,26 @@
 	}
 }
 
-void buddy_signon_cb(GaimConnection *gc, char *who) {
-	struct buddy *b = gaim_find_buddy(gc->account, who);
+static void
+buddy_signon_cb(struct buddy *b)
+{
 	if(buddy_ticker_find_buddy(b))
 		buddy_ticker_set_pixmap(b);
 	else
 		buddy_ticker_add_buddy(b);
 }
 
-void buddy_signoff_cb(GaimConnection *gc, char *who) {
-	struct buddy *b = gaim_find_buddy(gc->account, who);
+static void
+buddy_signoff_cb(struct buddy *b)
+{
 	buddy_ticker_remove_buddy(b);
 	if(!tickerbuds)
 		gtk_widget_hide(tickerwindow);
 }
 
-void away_cb(GaimConnection *gc, char *who) {
-	struct buddy *b = gaim_find_buddy(gc->account, who);
+static void
+away_cb(struct buddy *b)
+{
 	if(buddy_ticker_find_buddy(b))
 		buddy_ticker_set_pixmap(b);
 	else
@@ -262,11 +268,18 @@
 static gboolean
 plugin_load(GaimPlugin *plugin)
 {
-	gaim_signal_connect(plugin, event_signoff, signoff_cb, NULL);
-	gaim_signal_connect(plugin, event_buddy_signon, buddy_signon_cb, NULL);
-	gaim_signal_connect(plugin, event_buddy_signoff, buddy_signoff_cb, NULL);
-	gaim_signal_connect(plugin, event_buddy_away, away_cb, NULL);
-	gaim_signal_connect(plugin, event_buddy_back, away_cb, NULL);
+	void *blist_handle = gaim_blist_get_handle();
+
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
+						plugin, GAIM_CALLBACK(signoff_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-signed-on",
+						plugin, GAIM_CALLBACK(buddy_signon_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-signed-off",
+						plugin, GAIM_CALLBACK(buddy_signoff_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-away",
+						plugin, GAIM_CALLBACK(away_cb), NULL);
+	gaim_signal_connect(blist_handle, "buddy-back",
+						plugin, GAIM_CALLBACK(away_cb), NULL);
 
 	if (gaim_connections_get_all())
 		buddy_ticker_show();
--- a/plugins/timestamp.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/plugins/timestamp.c	Mon Aug 18 01:03:43 2003 +0000
@@ -7,6 +7,7 @@
 
 #include "conversation.h"
 #include "debug.h"
+#include "signals.h"
 
 #include "gtkimhtml.h"
 #include "gtkplugin.h"
@@ -19,7 +20,7 @@
 
 static GSList *timestamp_timeouts;
 
-gboolean do_timestamp (gpointer data)
+static gboolean do_timestamp (gpointer data)
 {
 	GaimConversation *c = (GaimConversation *)data;
 	char *buf;
@@ -36,24 +37,23 @@
 	return TRUE;
 }
 
-void timestamp_new_convo(char *name)
+static void timestamp_new_convo(GaimConversation *conv)
 {
-	GaimConversation *c = gaim_find_conversation(name);
-	do_timestamp(c);
+	do_timestamp(conv);
 
 	timestamp_timeouts = g_slist_append(timestamp_timeouts,
-			GINT_TO_POINTER(g_timeout_add(timestamp, do_timestamp, c)));
+			GINT_TO_POINTER(g_timeout_add(timestamp, do_timestamp, conv)));
 
 }
 
 static void set_timestamp(GtkWidget *button, GtkWidget *spinner) {
 	int tm;
-       
+
 	tm = 0;
-	
+
 	tm = CLAMP(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner)), 1, G_MAXINT);
 	gaim_debug(GAIM_DEBUG_MISC, "timestamp", "setting  time to %d mins\n", tm);
-	
+
 	tm = tm * 60 * 1000;
 
 	timestamp = tm;
@@ -67,7 +67,7 @@
 	GtkWidget *vbox, *hbox;
 	GtkAdjustment *adj;
 	GtkWidget *spinner, *button;
-	
+
 	ret = gtk_vbox_new(FALSE, 18);
 	gtk_container_set_border_width (GTK_CONTAINER (ret), 12);
 
@@ -80,21 +80,22 @@
 
 	label = gtk_label_new(_("Delay"));
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
-	
+
 	adj = (GtkAdjustment *)gtk_adjustment_new(timestamp/(60*1000), 1, G_MAXINT, 1, 0, 0);
 	spinner = gtk_spin_button_new(adj, 0, 0);
-        gtk_box_pack_start(GTK_BOX(hbox), spinner, TRUE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(hbox), spinner, TRUE, TRUE, 0);
 
-        label = gtk_label_new(_("minutes."));
-        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+	label = gtk_label_new(_("minutes."));
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
 
-        hbox = gtk_hbox_new(TRUE, 5);
-        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+	hbox = gtk_hbox_new(TRUE, 5);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
 
-        button = gtk_button_new_with_mnemonic(_("_Apply"));
-        gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
-	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(set_timestamp), spinner);
-	
+	button = gtk_button_new_with_mnemonic(_("_Apply"));
+	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
+	g_signal_connect(G_OBJECT(button), "clicked",
+					 G_CALLBACK(set_timestamp), spinner);
+
 	gtk_widget_show_all(ret);
 	return ret;
 }
@@ -108,11 +109,12 @@
 	timestamp_timeouts = NULL;
 	for (cnvs = gaim_get_conversations(); cnvs != NULL; cnvs = cnvs->next) {
 		c = cnvs->data;
-		timestamp_new_convo(c->name);
+		timestamp_new_convo(c);
 	}
 
-	gaim_signal_connect(plugin, event_new_conversation,
-						timestamp_new_convo, NULL);
+	gaim_signal_connect(gaim_conversations_get_handle(),
+						"conversation-created",
+						plugin, GAIM_CALLBACK(timestamp_new_convo), NULL);
 
 	return TRUE;
 }
@@ -152,7 +154,7 @@
 	                                                  /**  description    */
 	N_("Adds iChat-style timestamps to conversations every N minutes."),
 	"Sean Egan <bj91704@binghamton.edu>",             /**< author         */
-	GAIM_WEBSITE,                                          /**< homepage       */
+	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
 	plugin_unload,                                    /**< unload         */
--- a/src/Makefile.am	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/Makefile.am	Mon Aug 18 01:03:43 2003 +0000
@@ -55,8 +55,6 @@
 	core.h \
 	debug.c \
 	debug.h \
-	event.c \
-	event.h \
 	ft.c \
 	ft.h \
 	html.c \
@@ -82,6 +80,8 @@
 	request.h \
 	server.c \
 	server.h \
+	signals.c \
+	signals.h \
 	status.c \
 	status.h \
 	sound.c \
--- a/src/account.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/account.c	Mon Aug 18 01:03:43 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -25,6 +25,7 @@
 #include "debug.h"
 #include "prefs.h"
 #include "prpl.h"
+#include "signals.h"
 #include "server.h"
 #include "util.h"
 
@@ -1413,3 +1414,37 @@
 
 	return account;
 }
+
+void *
+gaim_accounts_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
+}
+
+void
+gaim_accounts_init(void)
+{
+	void *handle = gaim_accounts_get_handle();
+
+	gaim_signal_register(handle, "account-connecting",
+						 gaim_marshal_VOID__POINTER);
+
+	gaim_signal_register(handle, "account-away",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER);
+
+	gaim_signal_register(handle, "account-setting-info",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "account-set-info",
+						 gaim_marshal_VOID__POINTER_POINTER);
+
+	gaim_signal_register(handle, "account-warned",
+						 gaim_marshal_VOID__POINTER_POINTER_UINT);
+}
+
+void
+gaim_accounts_uninit(void)
+{
+	gaim_signals_unregister_by_instance(gaim_accounts_get_handle());
+}
--- a/src/account.h	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/account.h	Mon Aug 18 01:03:43 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -578,6 +578,30 @@
 
 /*@}*/
 
+/**************************************************************************/
+/** @name Accounts Subsystem                                              */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the accounts subsystem handle.
+ *
+ * @return The accounts subsystem handle.
+ */
+void *gaim_accounts_get_handle(void);
+
+/**
+ * Initializes the accounts subsystem.
+ */
+void gaim_accounts_init(void);
+
+/**
+ * Uninitializes the accounts subsystem.
+ */
+void gaim_accounts_uninit(void);
+
+/*@}*/
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/blist.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/blist.c	Mon Aug 18 01:03:43 2003 +0000
@@ -29,6 +29,7 @@
 #include "privacy.h"
 #include "prpl.h"
 #include "server.h"
+#include "signals.h"
 #include "util.h"
 
 #define PATHSIZE 1024
@@ -100,13 +101,15 @@
 
 	gbl->ui_ops = gaim_get_blist_ui_ops();
 
-	gbl->buddies = g_hash_table_new ((GHashFunc)_gaim_blist_hbuddy_hash, 
+	gbl->buddies = g_hash_table_new ((GHashFunc)_gaim_blist_hbuddy_hash,
 					 (GEqualFunc)_gaim_blist_hbuddy_equal);
 
 	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", blist_pref_cb, NULL);
+	gaim_prefs_connect_callback("/core/buddies/use_server_alias",
+								blist_pref_cb, NULL);
+
 
 	return gbl;
 }
@@ -155,9 +158,9 @@
 
 	if((status & UC_UNAVAILABLE) != (buddy->uc & UC_UNAVAILABLE)) {
 		if(status & UC_UNAVAILABLE)
-			gaim_event_broadcast(event_buddy_away, buddy->account->gc, buddy->name);
+			gaim_signal_emit(gaim_blist_get_handle(), "buddy-away", buddy);
 		else
-			gaim_event_broadcast(event_buddy_back, buddy->account->gc, buddy->name);
+			gaim_signal_emit(gaim_blist_get_handle(), "buddy-back", buddy);
 	}
 
 	buddy->uc = status;
@@ -196,12 +199,12 @@
 
 	if (!GAIM_BUDDY_IS_ONLINE(buddy) && presence) {
 		buddy->present = GAIM_BUDDY_SIGNING_ON;
-		gaim_event_broadcast(event_buddy_signon, buddy->account->gc, buddy->name);
+		gaim_signal_emit(gaim_blist_get_handle(), "buddy-signed-on", buddy);
 		do_timer = TRUE;
 		((struct group *)((GaimBlistNode *)buddy)->parent)->online++;
 	} else if(GAIM_BUDDY_IS_ONLINE(buddy) && !presence) {
 		buddy->present = GAIM_BUDDY_SIGNING_OFF;
-		gaim_event_broadcast(event_buddy_signoff, buddy->account->gc, buddy->name);
+		gaim_signal_emit(gaim_blist_get_handle(), "buddy-signed-off", buddy);
 		do_timer = TRUE;
 		((struct group *)((GaimBlistNode *)buddy)->parent)->online--;
 	}
@@ -1792,9 +1795,9 @@
 			g_free(msg);
 		}
 	} else if(g_list_length(gaim_accounts_get_all())) {
+#if 0
 		GMainContext *ctx;
 
-#if 0
 		/* rob wants to inform the user that their buddy lists are
 		 * being converted */
 		msg = g_strdup_printf(_("Gaim is converting your old buddy lists "
@@ -2087,4 +2090,37 @@
 	return group->online;
 }
 
+void *
+gaim_blist_get_handle(void)
+{
+	static int handle;
 
+	return &handle;
+}
+
+void
+gaim_blist_init(void)
+{
+	void *handle = gaim_blist_get_handle();
+
+	gaim_signal_register(handle, "buddy-away", gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "buddy-back", gaim_marshal_VOID__POINTER);
+
+	gaim_signal_register(handle, "buddy-idle",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "buddy-unidle",
+						 gaim_marshal_VOID__POINTER_POINTER);
+
+	gaim_signal_register(handle, "buddy-signed-on",
+						 gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "buddy-signed-off",
+						 gaim_marshal_VOID__POINTER);
+
+	gaim_signal_register(handle, "update-idle", gaim_marshal_VOID);
+}
+
+void
+gaim_blist_uninit(void)
+{
+	gaim_signals_unregister_by_instance(gaim_blist_get_handle());
+}
--- a/src/blist.h	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/blist.h	Mon Aug 18 01:03:43 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003, Sean Egan <sean.egan@binghamton.edu>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -613,6 +613,30 @@
 
 /*@}*/
 
+/**************************************************************************/
+/** @name Buddy List Subsystem                                            */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the handle for the buddy list subsystem.
+ *
+ * @return The buddy list subsystem handle.
+ */
+void *gaim_blist_get_handle(void);
+
+/**
+ * Initializes the buddy list subsystem.
+ */
+void gaim_blist_init(void);
+
+/**
+ * Uninitializes the buddy list subsystem.
+ */
+void gaim_blist_uninit(void);
+
+/*@}*/
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/connection.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/connection.c	Mon Aug 18 01:03:43 2003 +0000
@@ -29,6 +29,7 @@
 #include "prefs.h"
 #include "request.h"
 #include "server.h"
+#include "signals.h"
 #include "sound.h"
 #include "util.h"
 
@@ -36,6 +37,7 @@
 static GList *connections_connecting = NULL;
 static GaimConnectionUiOps *connection_ui_ops = NULL;
 
+static int connections_handle;
 
 GaimConnection *
 gaim_connection_new(GaimAccount *account)
@@ -151,6 +153,8 @@
 
 	gaim_connection_set_state(gc, GAIM_CONNECTING);
 
+	gaim_signal_emit(gaim_connections_get_handle(), "signing-on", gc);
+
 	gaim_debug(GAIM_DEBUG_INFO, "connection", "Calling serv_login\n");
 
 	connections = g_list_append(connections, gc);
@@ -180,13 +184,16 @@
 		if (gaim_connection_get_state(gc) != GAIM_CONNECTING)
 			gaim_blist_remove_account(gaim_connection_get_account(gc));
 
+		gaim_signal_emit(gaim_connections_get_handle(), "signing-off", gc);
+
 		serv_close(gc);
 
 		connections = g_list_remove(connections, gc);
 
 		gaim_connection_set_state(gc, GAIM_DISCONNECTED);
 
-		gaim_event_broadcast(event_signoff, gc);
+		gaim_signal_emit(gaim_connections_get_handle(), "signed-off", gc);
+
 		system_log(log_signoff, gc, NULL,
 				   OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON);
 
@@ -274,7 +281,8 @@
 									 GAIM_CONV_ACCOUNT_ONLINE);
 		}
 
-		gaim_event_broadcast(event_signon, gc);
+		gaim_signal_emit(gaim_connections_get_handle(), "signed-on", gc);
+
 		system_log(log_signon, gc, NULL,
 				   OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON);
 
@@ -447,6 +455,29 @@
 }
 
 void
+gaim_connections_init(void)
+{
+	void *handle = gaim_connections_get_handle();
+
+	gaim_signal_register(handle, "signing-on",  gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "signed-on",   gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "signing-off", gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "signed-off",  gaim_marshal_VOID__POINTER);
+}
+
+void
+gaim_connections_uninit(void)
+{
+	gaim_signals_unregister_by_instance(gaim_connections_get_handle());
+}
+
+void *
+gaim_connections_get_handle(void)
+{
+	return &connections_handle;
+}
+
+void
 gaim_set_connection_ui_ops(GaimConnectionUiOps *ops)
 {
 	connection_ui_ops = ops;
@@ -457,4 +488,3 @@
 {
 	return connection_ui_ops;
 }
-
--- a/src/connection.h	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/connection.h	Mon Aug 18 01:03:43 2003 +0000
@@ -233,6 +233,23 @@
  */
 GList *gaim_connections_get_connecting(void);
 
+/**
+ * Initializes the connections subsystem.
+ */
+void gaim_connections_init(void);
+
+/**
+ * Uninitializes the connections subsystem.
+ */
+void gaim_connections_uninit(void);
+
+/**
+ * Returns the handle to the connections subsystem.
+ *
+ * @return The connections subsystem handle.
+ */
+void *gaim_connections_get_handle(void);
+
 /*@}*/
 
 /**************************************************************************/
--- a/src/conversation.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/conversation.c	Mon Aug 18 01:03:43 2003 +0000
@@ -2,7 +2,7 @@
  * gaim
  *
  * Copyright (C) 2002-2003, Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -25,6 +25,7 @@
 #include "notify.h"
 #include "prefs.h"
 #include "prpl.h"
+#include "signals.h"
 #include "util.h"
 
 /* XXX CORE/UI */
@@ -226,13 +227,12 @@
 	else
 		buffy = g_strdup(buf);
 
-	plugin_return = gaim_event_broadcast(
-			(type == GAIM_CONV_IM ? event_im_send : event_chat_send),
-			gc,
+	plugin_return =
+		GPOINTER_TO_INT(gaim_signal_emit_return_1(
+			gaim_conversations_get_handle(),
 			(type == GAIM_CONV_IM
-			 ? gaim_conversation_get_name(conv)
-			 : GINT_TO_POINTER(gaim_chat_get_id(GAIM_CHAT(conv)))),
-			&buffy);
+			 ? "displaying-im-msg" : "displaying-chat-msg"),
+			conv, &buffy));
 
 	if (buffy == NULL) {
 		g_free(buf2);
@@ -250,12 +250,16 @@
 	strncpy(buf, buffy, limit);
 	g_free(buffy);
 
+	gaim_signal_emit(gaim_conversations_get_handle(),
+		(type == GAIM_CONV_IM ? "displayed-im-msg" : "displayed-chat-msg"),
+		conv, buffy);
+
 	if (type == GAIM_CONV_IM) {
 		GaimIm *im = GAIM_IM(conv);
 
 		buffy = g_strdup(buf);
-		gaim_event_broadcast(event_im_displayed_sent, gc,
-					 gaim_conversation_get_name(conv), &buffy);
+		gaim_signal_emit(gaim_conversations_get_handle(), "sending-im-msg",
+						 conv, &buffy);
 
 		if (buffy != NULL) {
 			int imflags = 0;
@@ -387,11 +391,26 @@
 					gaim_im_write(im, NULL, buf, -1, WFLAG_SEND, time(NULL));
 			}
 
+			gaim_signal_emit(gaim_conversations_get_handle(), "sent-im-msg",
+							 conv, buffy);
+
 			g_free(buffy);
 		}
 	}
 	else {
-		err = serv_chat_send(gc, gaim_chat_get_id(GAIM_CHAT(conv)), buf);
+		buffy = g_strdup(buf);
+
+		gaim_signal_emit(gaim_conversations_get_handle(), "sending-chat-msg",
+						 conv, &buffy);
+
+		if (buffy != NULL) {
+			err = serv_chat_send(gc, gaim_chat_get_id(GAIM_CHAT(conv)), buffy);
+
+			gaim_signal_emit(gaim_conversations_get_handle(), "sent-chat-msg",
+							 conv, buf);
+
+			g_free(buffy);
+		}
 	}
 
 	g_free(buf2);
@@ -747,21 +766,27 @@
 gaim_window_switch_conversation(GaimWindow *win, unsigned int index)
 {
 	GaimWindowUiOps *ops;
-	GaimConversation *conv;
+	GaimConversation *old_conv, *conv;
 
 	g_return_if_fail(win != NULL);
 	g_return_if_fail(index >= 0 &&
 					 index < gaim_window_get_conversation_count(win));
 
+	old_conv = gaim_window_get_active_conversation(win);
+	conv = gaim_window_get_conversation_at(win, index);
+
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "conversation-switching", old_conv, conv);
+
 	ops = gaim_window_get_ui_ops(win);
 
 	if (ops != NULL && ops->switch_conversation != NULL)
 		ops->switch_conversation(win, index);
 
-	conv = gaim_window_get_conversation_at(win, index);
 	gaim_conversation_set_unseen(conv, GAIM_UNSEEN_NONE);
-	gaim_event_broadcast(event_conversation_switch, conv);
-
+
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "conversation-switched", old_conv, conv);
 }
 
 GaimConversation *
@@ -924,12 +949,14 @@
 			gaim_prefs_set_string("/core/conversations/placement", "last");
 
 		if (!place_conv)
-			gaim_debug(GAIM_DEBUG_ERROR, "conversation", "This is about to suck.\n");
+			gaim_debug(GAIM_DEBUG_ERROR, "conversation",
+					   "This is about to suck.\n");
 
 		place_conv(conv);
 	}
 
-	gaim_event_broadcast(event_new_conversation, name);
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "conversation-created", conv);
 
 	return conv;
 }
@@ -989,7 +1016,8 @@
 		}
 	}
 
-	gaim_event_broadcast(event_del_conversation, conv);
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "deleting-conversation", conv);
 
 	if (conv->name  != NULL) g_free(conv->name);
 	if (conv->title != NULL) g_free(conv->title);
@@ -1908,14 +1936,13 @@
 	conv = gaim_chat_get_conversation(chat);
 	ops  = gaim_conversation_get_ui_ops(conv);
 
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "chat-buddy-joining", conv, user);
+
 	gaim_chat_set_users(chat,
 		g_list_insert_sorted(gaim_chat_get_users(chat), g_strdup(user),
 							 insertname_compare));
 
-	gaim_event_broadcast(event_chat_buddy_join,
-				 gaim_conversation_get_gc(conv), gaim_chat_get_id(chat),
-				 user);
-
 	if (ops != NULL && ops->chat_add_user != NULL)
 		ops->chat_add_user(conv, user);
 
@@ -1929,6 +1956,9 @@
 
 		gaim_conversation_write(conv, NULL, tmp, -1, WFLAG_SYSTEM, time(NULL));
 	}
+
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "chat-buddy-joined", conv, user);
 }
 
 void
@@ -1945,14 +1975,18 @@
 	ops  = gaim_conversation_get_ui_ops(conv);
 
 	for (l = users; l != NULL; l = l->next) {
+		const char *user = (const char *)l->data;
+
+		gaim_signal_emit(gaim_conversations_get_handle(),
+						 "chat-buddy-joining", conv, user);
+
 		gaim_chat_set_users(chat,
 				g_list_insert_sorted(gaim_chat_get_users(chat),
 									 g_strdup((char *)l->data),
 									 insertname_compare));
 
-		gaim_event_broadcast(event_chat_buddy_join,
-				gaim_conversation_get_gc(conv), gaim_chat_get_id(chat),
-				(char *)l->data);
+		gaim_signal_emit(gaim_conversations_get_handle(),
+						 "chat-buddy-joined", conv, user);
 	}
 
 	if (ops != NULL && ops->chat_add_users != NULL)
@@ -2022,8 +2056,8 @@
 	conv = gaim_chat_get_conversation(chat);
 	ops  = gaim_conversation_get_ui_ops(conv);
 
-	gaim_event_broadcast(event_chat_buddy_leave, gaim_conversation_get_gc(conv),
-				 gaim_chat_get_id(chat), user);
+	gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-leaving",
+					 conv, user, reason);
 
 	if (ops != NULL && ops->chat_remove_user != NULL)
 		ops->chat_remove_user(conv, user);
@@ -2050,6 +2084,9 @@
 
 		gaim_conversation_write(conv, NULL, tmp, -1, WFLAG_SYSTEM, time(NULL));
 	}
+
+	gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-left",
+					 conv, user, reason);
 }
 
 void
@@ -2067,26 +2104,33 @@
 	ops  = gaim_conversation_get_ui_ops(conv);
 
 	for (l = users; l != NULL; l = l->next) {
-		gaim_event_broadcast(event_chat_buddy_leave,
-							 gaim_conversation_get_gc(conv),
-							 gaim_chat_get_id(chat), l->data);
+		const char *user = (const char *)l->data;
+
+		gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-leaving",
+						 conv, user, reason);
 	}
 
 	if (ops != NULL && ops->chat_remove_users != NULL)
 		ops->chat_remove_users(conv, users);
 
 	for (l = users; l != NULL; l = l->next) {
+		const char *user = (const char *)l->data;
+
 		for (names = gaim_chat_get_users(chat);
 			 names != NULL;
 			 names = names->next) {
 
-			if (!gaim_utf8_strcasecmp((char *)names->data, (char *)l->data)) {
+			if (!gaim_utf8_strcasecmp((char *)names->data, user))
+			{
 				gaim_chat_set_users(chat,
 					g_list_remove(gaim_chat_get_users(chat), names->data));
 
 				break;
 			}
 		}
+
+		gaim_signal_emit(gaim_conversations_get_handle(), "chat-buddy-left",
+						 conv, user, reason);
 	}
 
 	/* NOTE: Don't remove them from ignored in case they re-enter. */
@@ -2142,9 +2186,10 @@
 
 		l_next = l->next;
 
-		gaim_event_broadcast(event_chat_buddy_leave,
-							 gaim_conversation_get_gc(conv),
-							 gaim_chat_get_id(chat), user);
+		gaim_signal_emit(gaim_conversations_get_handle(),
+						 "chat-buddy-leaving", conv, user, NULL);
+		gaim_signal_emit(gaim_conversations_get_handle(),
+						 "chat-buddy-left", conv, user, NULL);
 
 		g_free(user);
 	}
@@ -2525,9 +2570,21 @@
 	return win_ui_ops;
 }
 
+void *
+gaim_conversations_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
+}
+
 void
-gaim_conversation_init(void)
+gaim_conversations_init(void)
 {
+	void *handle = gaim_conversations_get_handle();
+
+	/* Register preferences */
+
 	/* Conversations */
 	gaim_prefs_add_none("/core/conversations");
 	gaim_prefs_add_bool("/core/conversations/send_urls_as_links", TRUE);
@@ -2554,4 +2611,69 @@
 			update_titles_pref_cb, NULL);
 	gaim_prefs_connect_callback("/core/buddies/use_server_alias",
 			update_titles_pref_cb, NULL);
+
+
+	/* Register signals */
+	gaim_signal_register(handle, "displaying-im-msg",
+						 gaim_marshal_BOOLEAN__POINTER_POINTER);
+	gaim_signal_register(handle, "displayed-im-msg",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "sending-im-msg",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "sent-im-msg",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "received-im-msg",
+			gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER);
+
+	gaim_signal_register(handle, "displaying-chat-msg",
+						 gaim_marshal_BOOLEAN__POINTER_POINTER);
+	gaim_signal_register(handle, "displayed-chat-msg",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "sending-chat-msg",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "sent-chat-msg",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "received-chat-msg",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER);
+
+	gaim_signal_register(handle, "conversation-switching",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "conversation-switched",
+						 gaim_marshal_VOID__POINTER_POINTER);
+
+	gaim_signal_register(handle, "conversation-created",
+						 gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "deleting-conversation",
+						 gaim_marshal_VOID__POINTER);
+
+	gaim_signal_register(handle, "buddy-typing",
+						 gaim_marshal_VOID__POINTER);
+
+	gaim_signal_register(handle, "chat-buddy-joining",
+						 gaim_marshal_VOID__POINTER_POINTER);
+	gaim_signal_register(handle, "chat-buddy-joined",
+						 gaim_marshal_VOID__POINTER_POINTER);
+
+	gaim_signal_register(handle, "chat-buddy-leaving",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER);
+	gaim_signal_register(handle, "chat-buddy-left",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER);
+
+	gaim_signal_register(handle, "chat-inviting-user",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER);
+	gaim_signal_register(handle, "chat-invited-user",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER);
+
+	gaim_signal_register(handle, "chat-invited",
+						 gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER);
+	gaim_signal_register(handle, "chat-joined",
+						 gaim_marshal_VOID__POINTER);
+	gaim_signal_register(handle, "chat-left",
+						 gaim_marshal_VOID__POINTER);
 }
+
+void
+gaim_conversations_uninit(void)
+{
+	gaim_signals_unregister_by_instance(gaim_conversations_get_handle());
+}
--- a/src/conversation.h	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/conversation.h	Mon Aug 18 01:03:43 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2002-2003, Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -20,7 +20,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-
 #ifndef _GAIM_CONVERSATION_H_
 #define _GAIM_CONVERSATION_H_
 
@@ -1210,10 +1209,29 @@
  */
 GaimWindowUiOps *gaim_get_win_ui_ops(void);
 
+/*@}*/
+
+/**************************************************************************/
+/** @name Conversations Subsystem                                         */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Returns the conversation subsystem handle.
+ *
+ * @return The conversation subsystem handle.
+ */
+void *gaim_conversations_get_handle(void);
+
 /**
  * Initializes the conversation subsystem.
  */
-void gaim_conversation_init(void);
+void gaim_conversations_init(void);
+
+/**
+ * Uninitializes the conversation subsystem.
+ */
+void gaim_conversations_uninit(void);
 
 /*@}*/
 
--- a/src/core.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/core.c	Mon Aug 18 01:03:43 2003 +0000
@@ -31,6 +31,7 @@
 #include "prefs.h"
 #include "privacy.h"
 #include "proxy.h"
+#include "signals.h"
 #include "sound.h"
 
 struct GaimCore
@@ -60,6 +61,11 @@
 
 	ops = gaim_get_core_ui_ops();
 
+	/* The signals subsystem is important and should be first. */
+	gaim_signals_init();
+
+	gaim_signal_register(core, "quitting", gaim_marshal_VOID);
+
 	/* Initialize all static protocols. */
 	static_proto_init();
 
@@ -73,7 +79,10 @@
 			ops->debug_ui_init();
 	}
 
-	gaim_conversation_init();
+	gaim_accounts_init();
+	gaim_connections_init();
+	gaim_conversations_init();
+	gaim_blist_init();
 	gaim_privacy_init();
 	gaim_pounces_init();
 	gaim_proxy_init();
@@ -100,7 +109,7 @@
 		ops->quit();
 
 	/* The self destruct sequence has been initiated */
-	gaim_event_broadcast(event_quit);
+	gaim_signal_emit(gaim_get_core(), "quitting");
 
 	/* Transmission ends */
 	gaim_connections_disconnect_all();
@@ -112,6 +121,13 @@
 	gaim_debug(GAIM_DEBUG_INFO, "main", "Unloading all plugins\n");
 	gaim_plugins_destroy_all();
 
+	gaim_blist_uninit();
+	gaim_conversations_uninit();
+	gaim_connections_uninit();
+	gaim_accounts_uninit();
+
+	gaim_signals_uninit();
+
 	if (core->ui != NULL) {
 		g_free(core->ui);
 		core->ui = NULL;
--- a/src/event.c	Sun Aug 17 17:55:46 2003 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,422 +0,0 @@
-/**
- * @file event.c Event API
- * @ingroup core
- *
- * gaim
- *
- * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include "event.h"
-#include "debug.h"
-
-#include <sys/time.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifdef _WIN32
-#include "win32dep.h"
-#endif
-
-/**
- * A signal callback.
- */
-typedef struct
-{
-	void *handle;                /**< The plugin module handle.         */
-	GaimEvent event;             /**< The event type.                   */
-	void *function;              /**< The function to call.             */
-	void *data;                  /**< The data to pass to the function. */
-
-} GaimSignalCallback;
-
-/**
- * A broadcast function.
- */
-typedef struct
-{
-	GaimSignalBroadcastFunc func;
-	void *data;
-
-} GaimSignalBroadcaster;
-
-static GList *callbacks = NULL;
-static GList *broadcasters = NULL;
-
-void
-gaim_signal_connect(void *handle, GaimEvent event,
-					void *func, void *data)
-{
-	GaimSignalCallback *call;
-
-	g_return_if_fail(func != NULL);
-
-	call = g_new0(GaimSignalCallback, 1);
-	call->handle   = handle;
-	call->event    = event;
-	call->function = func;
-	call->data     = data;
-
-	callbacks = g_list_append(callbacks, call);
-
-	gaim_debug(GAIM_DEBUG_INFO, "signals",
-			   "Adding callback %d\n", g_list_length(callbacks));
-}
-
-void
-gaim_signal_disconnect(void *handle, GaimEvent event, void *func)
-{
-	GList *c, *next_c;
-	GaimSignalCallback *g = NULL;
-
-	g_return_if_fail(func != NULL);
-
-	for (c = callbacks; c != NULL; c = next_c) {
-		next_c = c->next;
-		g = (GaimSignalCallback *)c->data;
-
-		if (handle == g->handle && func == g->function) {
-			callbacks = g_list_remove(callbacks, c->data);
-			g_free(g);
-		}
-	}
-}
-
-void
-gaim_signals_disconnect_by_handle(void *handle)
-{
-	GList *c, *c_next;
-	GaimSignalCallback *g;
-
-	g_return_if_fail(handle != NULL);
-
-	gaim_debug(GAIM_DEBUG_INFO, "signals",
-			   "Disconnecting callbacks. %d to search.\n",
-			   g_list_length(callbacks));
-
-	for (c = callbacks; c != NULL; c = c_next) {
-		c_next = c->next;
-		g = (GaimSignalCallback *)c->data;
-
-		if (g->handle == handle) {
-			callbacks = g_list_remove(callbacks, c->data);
-			g_free(g);
-
-			gaim_debug(GAIM_DEBUG_INFO, "signals",
-					   "Removing callback. %d remain.\n",
-					   g_list_length(callbacks));
-		}
-	}
-}
-
-void
-gaim_signals_register_broadcast_func(GaimSignalBroadcastFunc func,
-									 void *data)
-{
-	GaimSignalBroadcaster *broadcaster;
-
-	g_return_if_fail(func != NULL);
-
-	broadcaster = g_new0(GaimSignalBroadcaster, 1);
-
-	broadcaster->func = func;
-	broadcaster->data = data;
-
-	broadcasters = g_list_append(broadcasters, broadcaster);
-}
-
-void
-gaim_signals_unregister_broadcast_func(GaimSignalBroadcastFunc func)
-{
-	GList *l;
-	GaimSignalBroadcaster *broadcaster;
-
-	g_return_if_fail(func != NULL);
-
-	for (l = broadcasters; l != NULL; l = l->next) {
-		broadcaster = l->data;
-
-		if (broadcaster->func == func) {
-			broadcasters = g_list_remove(broadcasters, broadcaster);
-
-			g_free(broadcaster);
-
-			break;
-		}
-	}
-}
-
-GList *
-gaim_signals_get_callbacks(void)
-{
-	return callbacks;
-}
-
-int
-gaim_event_broadcast(GaimEvent event, ...)
-{
-	GList *c;
-	GList *l;
-	GaimSignalCallback *g;
-	GaimSignalBroadcaster *broadcaster;
-	int retval = 0;
-	va_list arrg;
-	void    *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL;
-
-	for (c = callbacks; c != NULL; c = c->next) {
-		void (*cbfunc)(void *, ...);
-
-		g = (GaimSignalCallback *)c->data;
-
-		if (g->event == event && g->function != NULL) {
-			time_t time;
-			int id;
-			cbfunc = g->function;
-
-			va_start(arrg, event);
-
-			switch (event) {
-				/* no args */
-				case event_blist_update:
-				case event_quit:
-					cbfunc(g->data);
-					break;
-
-				/* one arg */
-				case event_signon:
-				case event_signoff:
-				case event_new_conversation:
-				case event_del_conversation:
-			        case event_conversation_switch:
-				case event_error:
-				case event_connecting:
-					arg1 = va_arg(arrg, void *);
-					cbfunc(arg1, g->data);
-					break;
-
-				/* two args */
-				case event_buddy_signon:
-				case event_buddy_signoff:
-				case event_buddy_away:
-				case event_buddy_back:
-				case event_buddy_idle:
-				case event_buddy_unidle:
-				case event_set_info:
-				case event_draw_menu:
-				case event_got_typing:
-					arg1 = va_arg(arrg, void *);
-					arg2 = va_arg(arrg, void *);
-					cbfunc(arg1, arg2, g->data);
-					break;
-
-				case event_chat_leave:
-					arg1 = va_arg(arrg, void*);
-					id = va_arg(arrg, int);
-					cbfunc(arg1, id, g->data);
-					break;
-
-				/* three args */
-				case event_im_send:
-				case event_im_displayed_sent:
-				case event_away:
-					arg1 = va_arg(arrg, void *);
-					arg2 = va_arg(arrg, void *);
-					arg3 = va_arg(arrg, void *);
-					cbfunc(arg1, arg2, arg3, g->data);
-					break;
-
-				case event_chat_buddy_join:
-				case event_chat_buddy_leave:
-				case event_chat_send:
-				case event_chat_join:
-					arg1 = va_arg(arrg, void*);
-					id = va_arg(arrg, int);
-					arg3 = va_arg(arrg, void*);
-					cbfunc(arg1, id, arg3, g->data);
-					break;
-
-				case event_warned:
-					arg1 = va_arg(arrg, void*);
-					arg2 = va_arg(arrg, void*);
-					id = va_arg(arrg, int);
-					cbfunc(arg1, arg2, id, g->data);
-					break;
-
-				/* four args */
-				case event_im_recv:
-				case event_chat_invited:
-					arg1 = va_arg(arrg, void *);
-					arg2 = va_arg(arrg, void *);
-					arg3 = va_arg(arrg, void *);
-					arg4 = va_arg(arrg, void *);
-					cbfunc(arg1, arg2, arg3, arg4, g->data);
-					break;
-
-				case event_chat_recv:
-				case event_chat_send_invite:
-					arg1 = va_arg(arrg, void *);
-					id = va_arg(arrg, int);
-
-					arg3 = va_arg(arrg, void *);
-					arg4 = va_arg(arrg, void *);
-					cbfunc(arg1, id, arg3, arg4, g->data);
-					break;
-
-				/* five args */
-				case event_im_displayed_rcvd:
-					arg1 = va_arg(arrg, void *);
-					arg2 = va_arg(arrg, void *);
-					arg3 = va_arg(arrg, void *);
-					arg4 = va_arg(arrg, void *);
-					time = va_arg(arrg, time_t);
-					cbfunc(arg1, arg2, arg3, arg4, time, g->data);
-					break;
-
-				default:
-					gaim_debug(GAIM_DEBUG_WARNING, "events",
-							   "Unknown event %d\n", event);
-					break;
-			}
-
-			va_end(arrg);
-		}
-	}
-
-	for (l = broadcasters; l != NULL && retval == 0; l = l->next) {
-		broadcaster = l->data;
-
-		va_start(arrg, event);
-		retval = broadcaster->func(event, broadcaster->data, arrg);
-	}
-
-	return retval;
-}
-
-const char *
-gaim_event_get_name(GaimEvent event)
-{
-	static char buf[128];
-
-	switch (event) {
-		case event_signon:
-			snprintf(buf, sizeof(buf), "event_signon");
-			break;
-		case event_signoff:
-			snprintf(buf, sizeof(buf), "event_signoff");
-			break;
-		case event_away:
-			snprintf(buf, sizeof(buf), "event_away");
-			break;
-		case event_back:
-			snprintf(buf, sizeof(buf), "event_back");
-			break;
-		case event_im_recv:
-			snprintf(buf, sizeof(buf), "event_im_recv");
-			break;
-		case event_im_send:
-			snprintf(buf, sizeof(buf), "event_im_send");
-			break;
-		case event_buddy_signon:
-			snprintf(buf, sizeof(buf), "event_buddy_signon");
-			break;
-		case event_buddy_signoff:
-			snprintf(buf, sizeof(buf), "event_buddy_signoff");
-			break;
-		case event_buddy_away:
-			snprintf(buf, sizeof(buf), "event_buddy_away");
-			break;
-		case event_buddy_back:
-			snprintf(buf, sizeof(buf), "event_buddy_back");
-			break;
-		case event_buddy_idle:
-			snprintf(buf, sizeof(buf), "event_buddy_idle");
-			break;
-		case event_buddy_unidle:
-			snprintf(buf, sizeof(buf), "event_buddy_unidle");
-			break;
-		case event_blist_update:
-			snprintf(buf, sizeof(buf), "event_blist_update");
-			break;
-		case event_chat_invited:
-			snprintf(buf, sizeof(buf), "event_chat_invited");
-			break;
-		case event_chat_join:
-			snprintf(buf, sizeof(buf), "event_chat_join");
-			break;
-		case event_chat_leave:
-			snprintf(buf, sizeof(buf), "event_chat_leave");
-			break;
-		case event_chat_buddy_join:
-			snprintf(buf, sizeof(buf), "event_chat_buddy_join");
-			break;
-		case event_chat_buddy_leave:
-			snprintf(buf, sizeof(buf), "event_chat_buddy_leave");
-			break;
-		case event_chat_recv:
-			snprintf(buf, sizeof(buf), "event_chat_recv");
-			break;
-		case event_chat_send:
-			snprintf(buf, sizeof(buf), "event_chat_send");
-			break;
-		case event_warned:
-			snprintf(buf, sizeof(buf), "event_warned");
-			break;
-		case event_error:
-			snprintf(buf, sizeof(buf), "event_error");
-			break;
-		case event_quit:
-			snprintf(buf, sizeof(buf), "event_quit");
-			break;
-		case event_new_conversation:
-			snprintf(buf, sizeof(buf), "event_new_conversation");
-			break;
-		case event_set_info:
-			snprintf(buf, sizeof(buf), "event_set_info");
-			break;
-		case event_draw_menu:
-			snprintf(buf, sizeof(buf), "event_draw_menu");
-			break;
-		case event_im_displayed_sent:
-			snprintf(buf, sizeof(buf), "event_im_displayed_sent");
-			break;
-		case event_im_displayed_rcvd:
-			snprintf(buf, sizeof(buf), "event_im_displayed_rcvd");
-			break;
-		case event_chat_send_invite:
-			snprintf(buf, sizeof(buf), "event_chat_send_invite");
-			break;
-		case event_got_typing:
-			snprintf(buf, sizeof(buf), "event_got_typing");
-			break;
-		case event_del_conversation:
-			snprintf(buf, sizeof(buf), "event_del_conversation");
-			break;
-		case event_connecting:
-			snprintf(buf, sizeof(buf), "event_connecting");
-			break;
-		case event_conversation_switch:
-			snprintf(buf, sizeof(buf), "event_conversation_switch");
-			break;				
-		default:
-			snprintf(buf, sizeof(buf), "event_unknown");
-			break;
-	}
-
-	return buf;
-}
-
-
--- a/src/event.h	Sun Aug 17 17:55:46 2003 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/**
- * @file event.h Event API
- * @ingroup core
- *
- * gaim
- *
- * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef _GAIM_EVENT_H_
-#define _GAIM_EVENT_H_
-
-#include <glib.h>
-
-/**
- * Event types
- */
-typedef enum gaim_event
-{
-	event_signon = 0,
-	event_signoff,
-	event_away,
-	event_back,
-	event_im_recv,
-	event_im_send,
-	event_buddy_signon,
-	event_buddy_signoff,
-	event_buddy_away,
-	event_buddy_back,
-	event_buddy_idle,
-	event_buddy_unidle,
-	event_blist_update,
-	event_chat_invited,
-	event_chat_join,
-	event_chat_leave,
-	event_chat_buddy_join,
-	event_chat_buddy_leave,
-	event_chat_recv,
-	event_chat_send,
-	event_warned,
-	event_error,
-	event_quit,
-	event_new_conversation,
-	event_set_info,
-	event_draw_menu,
-	event_im_displayed_sent,
-	event_im_displayed_rcvd,
-	event_chat_send_invite,
-	event_got_typing,
-	event_del_conversation,
-	event_connecting,
-	event_conversation_switch
-	/* any others? it's easy to add... */
-
-} GaimEvent;
-
-typedef int (*GaimSignalBroadcastFunc)(GaimEvent event, void *data,
-									   va_list args);
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**************************************************************************/
-/** @name  Signal API                                                     */
-/**************************************************************************/
-/**
- * Connects a signal handler to a gaim event.
- *
- * @param module The optional module handle.
- * @param event  The event to connect to.
- * @param func   The callback function.
- * @param data   The data to pass to the callback function.
- *
- * @see gaim_signal_disconnect()
- */
-void gaim_signal_connect(void *module, GaimEvent event,
-						 void *func, void *data);
-
-/**
- * Disconnects a signal handler from a gaim event.
- *
- * @param module The optional module handle.
- * @param event  The event to disconnect from.
- * @param func   The registered function to disconnect.
- *
- * @see gaim_signal_connect()
- */
-void gaim_signal_disconnect(void *module, GaimEvent event,
-							void *func);
-
-/**
- * Removes all callbacks associated with a handle.
- *
- * @param handle The handle.
- */
-void gaim_signals_disconnect_by_handle(void *handle);
-
-/**
- * Registers a function that re-broadcasts events.
- *
- * @param func The function.
- * @param data Data to be passed to the callback.
- */
-void gaim_signals_register_broadcast_func(GaimSignalBroadcastFunc func,
-										  void *data);
-
-/**
- * Unregisters a function that re-broadcasts events.
- *
- * @param func The function.
- */
-void gaim_signals_unregister_broadcast_func(GaimSignalBroadcastFunc func);
-
-/**
- * Returns a list of all signal callbacks.
- *
- * @return A list of all signal callbacks.
- */
-GList *gaim_signals_get_callbacks(void);
-
-/**
- * Broadcasts an event to all registered signal handlers.
- *
- * @param event The event to broadcast
- *
- * @see gaim_signal_connect()
- * @see gaim_signal_disconnect()
- */
-int gaim_event_broadcast(GaimEvent event, ...);
-
-/**
- * Returns a human-readable representation of an event name.
- *
- * @param event The event.
- *
- * @return A human-readable string of the name.
- */
-const char *gaim_event_get_name(GaimEvent event);
-
-/*@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _GAIM_EVENT_H_ */
--- a/src/gtkaccount.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/gtkaccount.c	Mon Aug 18 01:03:43 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2002-2003, Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -26,10 +26,10 @@
 #include "accountopt.h"
 #include "core.h"
 #include "debug.h"
-#include "event.h"
 #include "plugin.h"
 #include "prefs.h"
 #include "request.h"
+#include "signals.h"
 #include "util.h"
 
 #include "gaim-disclosure.h"
@@ -1821,8 +1821,10 @@
 					 G_CALLBACK(close_accounts_cb), dialog);
 
 	/* Setup some gaim signal handlers. */
-	gaim_signal_connect(dialog, event_signon,  signed_on_off_cb, dialog);
-	gaim_signal_connect(dialog, event_signoff, signed_on_off_cb, dialog);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
+						dialog, GAIM_CALLBACK(signed_on_off_cb), dialog);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
+						dialog, GAIM_CALLBACK(signed_on_off_cb), dialog);
 
 	gtk_widget_show(win);
 }
--- a/src/gtkconv.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/gtkconv.c	Mon Aug 18 01:03:43 2003 +0000
@@ -188,7 +188,7 @@
 	else
 		do_save_convo(wid);
 }
-	
+
 static void
 do_insert_image_cb(GObject *obj, GtkWidget *wid)
 {
--- a/src/gtkutils.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/gtkutils.c	Mon Aug 18 01:03:43 2003 +0000
@@ -40,6 +40,7 @@
 #include "notify.h"
 #include "prefs.h"
 #include "prpl.h"
+#include "signals.h"
 #include "util.h"
 
 #include "gtkconv.h"
@@ -887,8 +888,7 @@
 account_menu_destroyed_cb(GtkWidget *optmenu, GdkEvent *event,
 						  void *user_data)
 {
-	gaim_signal_disconnect(optmenu, event_signon,  account_menu_sign_on_off_cb);
-	gaim_signal_disconnect(optmenu, event_signoff, account_menu_sign_on_off_cb);
+	gaim_signals_disconnect_by_handle(optmenu);
 
 	return FALSE;
 }
@@ -908,10 +908,12 @@
 					 G_CALLBACK(account_menu_destroyed_cb), NULL);
 
 	/* Register the gaim sign on/off event callbacks. */
-	gaim_signal_connect(optmenu, event_signon,
-						account_menu_sign_on_off_cb, optmenu);
-	gaim_signal_connect(optmenu, event_signoff,
-						account_menu_sign_on_off_cb, optmenu);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
+						optmenu, GAIM_CALLBACK(account_menu_sign_on_off_cb),
+						optmenu);
+	gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
+						optmenu, GAIM_CALLBACK(account_menu_sign_on_off_cb),
+						optmenu);
 
 	/* Set some data. */
 	g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
--- a/src/idle.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/idle.c	Mon Aug 18 01:03:43 2003 +0000
@@ -37,6 +37,7 @@
 #include "multi.h"
 #include "prefs.h"
 #include "prpl.h"
+#include "signals.h"
 
 #include "ui.h"
 
@@ -62,7 +63,7 @@
 
 	account = gaim_connection_get_account(gc);
 
-	gaim_event_broadcast(event_blist_update);
+	gaim_signal_emit(gaim_blist_get_handle(), "update-idle");
 
 	time(&t);
 
--- a/src/plugin.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/plugin.c	Mon Aug 18 01:03:43 2003 +0000
@@ -38,11 +38,11 @@
 
 #include "accountopt.h"
 #include "debug.h"
-#include "event.h"
 #include "notify.h"
 #include "prefs.h"
 #include "prpl.h"
 #include "request.h"
+#include "signals.h"
 
 #ifdef _WIN32
 # define PLUGIN_EXT ".dll"
@@ -244,16 +244,6 @@
 		if (plugin->info != NULL) {
 			if (plugin->info->load != NULL)
 				plugin->info->load(plugin);
-
-			if (plugin->info->type == GAIM_PLUGIN_LOADER) {
-				GaimPluginLoaderInfo *loader_info;
-
-				loader_info = GAIM_PLUGIN_LOADER_INFO(plugin);
-
-				if (loader_info->broadcast != NULL)
-					gaim_signals_register_broadcast_func(loader_info->broadcast,
-														 NULL);
-			}
 		}
 	}
 	else {
@@ -327,14 +317,6 @@
 			if (prpl_info->protocol_options != NULL)
 				g_list_free(prpl_info->protocol_options);
 		}
-		else if (plugin->info->type == GAIM_PLUGIN_LOADER) {
-			GaimPluginLoaderInfo *loader_info;
-
-			loader_info = GAIM_PLUGIN_LOADER_INFO(plugin);
-
-			if (loader_info->broadcast != NULL)
-				gaim_signals_unregister_broadcast_func(loader_info->broadcast);
-		}
 	}
 	else {
 		GaimPlugin *loader;
--- a/src/plugin.h	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/plugin.h	Mon Aug 18 01:03:43 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -31,8 +31,6 @@
 
 typedef int GaimPluginPriority; /**< Plugin priority. */
 
-#include "event.h"
-
 /**
  * Plugin types.
  */
@@ -93,7 +91,7 @@
 	gboolean (*unload)(GaimPlugin *plugin);
 	void     (*destroy)(GaimPlugin *plugin);
 
-	GaimSignalBroadcastFunc broadcast;
+	/* XXX GaimSignalBroadcastFunc broadcast; */
 };
 
 /**
--- a/src/server.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/server.c	Mon Aug 18 01:03:43 2003 +0000
@@ -28,6 +28,7 @@
 #include "prefs.h"
 #include "prpl.h"
 #include "request.h"
+#include "signals.h"
 #include "server.h"
 #include "sound.h"
 #include "util.h"
@@ -61,7 +62,8 @@
 				   PACKAGE " " VERSION " logging in %s using %s\n",
 				   account->username, p->info->name);
 
-		gaim_event_broadcast(event_connecting, account);
+		gaim_signal_emit(gaim_accounts_get_handle(),
+						 "account-connecting", account);
 		prpl_info->login(account);
 	}
 }
@@ -356,6 +358,7 @@
 void serv_set_away(GaimConnection *gc, const char *state, const char *message)
 {
 	GaimPluginProtocolInfo *prpl_info = NULL;
+	GaimAccount *account;
 
 	if (gc->away_state == NULL && state == NULL &&
 		gc->away == NULL && message == NULL) {
@@ -374,6 +377,8 @@
 	if (gc != NULL && gc->prpl != NULL)
 		prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
 
+	account = gaim_connection_get_account(gc);
+
 	if (prpl_info && prpl_info->set_away) {
 		if (gc->away_state) {
 			g_free(gc->away_state);
@@ -386,8 +391,8 @@
 			gc->away_state = g_strdup(state);
 		}
 
-		gaim_event_broadcast(event_away, gc, state, message);
-
+		gaim_signal_emit(gaim_accounts_get_handle(), "account-away",
+						 account, state, message);
 	}
 
 	/* New away message... Clear out the record of sent autoresponses */
@@ -411,15 +416,24 @@
 void serv_set_info(GaimConnection *g, const char *info)
 {
 	GaimPluginProtocolInfo *prpl_info = NULL;
+	GaimAccount *account;
 
 	if (g != NULL && g->prpl != NULL)
 		prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(g->prpl);
 
-	if (prpl_info && g_list_find(gaim_connections_get_all(), g) && prpl_info->set_info) {
-		if (gaim_event_broadcast(event_set_info, g, info))
+	if (prpl_info && g_list_find(gaim_connections_get_all(), g) &&
+		prpl_info->set_info) {
+
+		account = gaim_connection_get_account(g);
+
+		if (gaim_signal_emit_return_1(gaim_accounts_get_handle(),
+									  "account-setting-info", account, info))
 			return;
 
 		prpl_info->set_info(g, info);
+
+		gaim_signal_emit(gaim_accounts_get_handle(),
+						 "account-set-info", account, info);
 	}
 }
 
@@ -678,16 +692,26 @@
 void serv_chat_invite(GaimConnection *g, int id, const char *message, const char *name)
 {
 	GaimPluginProtocolInfo *prpl_info = NULL;
+	GaimConversation *conv;
 	char *buffy = message && *message ? g_strdup(message) : NULL;
 
+	conv = gaim_find_chat(g, id);
+
+	if (conv == NULL)
+		return;
+
 	if (g != NULL && g->prpl != NULL)
 		prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(g->prpl);
 
-	gaim_event_broadcast(event_chat_send_invite, g, id, name, &buffy);
+	gaim_signal_emit(gaim_conversations_get_handle(), "chat-inviting-user",
+					 conv, name, &buffy);
 
 	if (prpl_info && g_list_find(gaim_connections_get_all(), g) && prpl_info->chat_invite)
 		prpl_info->chat_invite(g, id, buffy, name);
 
+	gaim_signal_emit(gaim_conversations_get_handle(), "chat-invited-user",
+					 conv, name, buffy);
+
 	if (buffy)
 		g_free(buffy);
 }
@@ -831,7 +855,11 @@
 		buffy = g_malloc(MAX(strlen(msg) + 1, BUF_LONG));
 		strcpy(buffy, msg);
 		angel = g_strdup(who);
-		plugin_return = gaim_event_broadcast(event_im_recv, gc, &angel, &buffy, &flags);
+
+		plugin_return = GPOINTER_TO_INT(
+			gaim_signal_emit_return_1(gaim_conversations_get_handle(),
+									  "received-im-msg",
+									  cnv, &angel, &buffy, &flags));
 
 		if (!buffy || !angel || plugin_return) {
 			if (buffy)
@@ -1049,7 +1077,6 @@
 		}
 	}
 
-	gaim_event_broadcast(event_im_displayed_rcvd, gc, name, message, flags, mtime);
 	g_free(name);
 	g_free(message);
 }
@@ -1097,11 +1124,11 @@
 
 	if (!b->idle && idle) {
 		gaim_pounce_execute(gc->account, b->name, GAIM_POUNCE_IDLE);
-		gaim_event_broadcast(event_buddy_idle, gc, b->name);
+		gaim_signal_emit(gaim_blist_get_handle(), "buddy-idle", account, b);
 		system_log(log_idle, gc, b, OPT_LOG_BUDDY_IDLE);
 	} else if (b->idle && !idle) {
 		gaim_pounce_execute(gc->account, b->name, GAIM_POUNCE_IDLE_RETURN);
-		gaim_event_broadcast(event_buddy_unidle, gc, b->name);
+		gaim_signal_emit(gaim_blist_get_handle(), "buddy-unidle", account, b);
 		system_log(log_unidle, gc, b, OPT_LOG_BUDDY_IDLE);
 	}
 
@@ -1194,8 +1221,12 @@
 void serv_got_eviled(GaimConnection *gc, const char *name, int lev)
 {
 	char buf2[1024];
+	GaimAccount *account;
 
-	gaim_event_broadcast(event_warned, gc, name, lev);
+	account = gaim_connection_get_account(gc);
+
+	gaim_signal_emit(gaim_accounts_get_handle(), "account-warned",
+					 account, name, lev);
 
 	if (gc->evil >= lev) {
 		gc->evil = lev;
@@ -1231,7 +1262,7 @@
 
 	b = gaim_find_buddy(gc->account, name);
 
-	gaim_event_broadcast(event_got_typing, gc, name);
+	gaim_signal_emit(gaim_conversations_get_handle(), "buddy-typing", cnv);
 
 	if (b != NULL) {
 		if (state == GAIM_TYPING)
@@ -1298,7 +1329,8 @@
 
 	account = gaim_connection_get_account(gc);
 
-	gaim_event_broadcast(event_chat_invited, gc, who, name, message);
+	gaim_signal_emit(gaim_conversations_get_handle(),
+					 "chat-invited", account, who, name, message);
 
 	if (message)
 		g_snprintf(buf2, sizeof(buf2),
@@ -1321,25 +1353,28 @@
 GaimConversation *serv_got_joined_chat(GaimConnection *gc,
 											   int id, const char *name)
 {
-	GaimConversation *b;
+	GaimConversation *conv;
 	GaimChat *chat;
+	GaimAccount *account;
 
-	b = gaim_conversation_new(GAIM_CONV_CHAT, gc->account, name);
-	chat = GAIM_CHAT(b);
+	account = gaim_connection_get_account(gc);
 
-	gc->buddy_chats = g_slist_append(gc->buddy_chats, b);
+	conv = gaim_conversation_new(GAIM_CONV_CHAT, account, name);
+	chat = GAIM_CHAT(conv);
+
+	gc->buddy_chats = g_slist_append(gc->buddy_chats, conv);
 
 	gaim_chat_set_id(chat, id);
 
 	/* TODO Move this to UI logging code! */
 	if (gaim_prefs_get_bool("/gaim/gtk/logging/log_chats") ||
-		find_log_info(gaim_conversation_get_name(b))) {
+		find_log_info(gaim_conversation_get_name(conv))) {
 
 		FILE *fd;
 		char *filename;
 
 		filename = (char *)malloc(100);
-		g_snprintf(filename, 100, "%s.chat", gaim_conversation_get_name(b));
+		g_snprintf(filename, 100, "%s.chat", gaim_conversation_get_name(conv));
 
 		fd = open_log_file(filename, TRUE);
 		
@@ -1356,13 +1391,13 @@
 		free(filename);
 	}
 
-	gaim_window_show(gaim_conversation_get_window(b));
-	gaim_window_switch_conversation(gaim_conversation_get_window(b),
-									gaim_conversation_get_index(b));
+	gaim_window_show(gaim_conversation_get_window(conv));
+	gaim_window_switch_conversation(gaim_conversation_get_window(conv),
+									gaim_conversation_get_index(conv));
 
-	gaim_event_broadcast(event_chat_join, gc, id, name);
+	gaim_signal_emit(gaim_conversations_get_handle(), "chat-joined", conv);
 
-	return b;
+	return conv;
 }
 
 void serv_got_chat_left(GaimConnection *g, int id)
@@ -1370,6 +1405,9 @@
 	GSList *bcs;
 	GaimConversation *conv = NULL;
 	GaimChat *chat = NULL;
+	GaimAccount *account;
+
+	account = gaim_connection_get_account(g);
 
 	for (bcs = g->buddy_chats; bcs != NULL; bcs = bcs->next) {
 		conv = (GaimConversation *)bcs->data;
@@ -1385,7 +1423,7 @@
 	if (!conv)
 		return;
 
-	gaim_event_broadcast(event_chat_leave, g, gaim_chat_get_id(chat));
+	gaim_signal_emit(gaim_conversations_get_handle(), "chat-left", conv);
 
 	gaim_debug(GAIM_DEBUG_INFO, "server", "Leaving room: %s\n",
 			   gaim_conversation_get_name(conv));
@@ -1431,8 +1469,11 @@
 	buffy = g_malloc(MAX(strlen(message) + 1, BUF_LONG));
 	strcpy(buffy, message);
 	angel = g_strdup(who);
-	plugin_return = gaim_event_broadcast(event_chat_recv, g, gaim_chat_get_id(chat),
-								 &angel, &buffy);
+
+	plugin_return = GPOINTER_TO_INT(
+		gaim_signal_emit_return_1(gaim_conversations_get_handle(),
+								  "received-chat-msg",
+								  conv, &angel, &buffy));
 
 	if (!buffy || !angel || plugin_return) {
 		if (buffy)
--- a/src/session.c	Sun Aug 17 17:55:46 2003 +0000
+++ b/src/session.c	Mon Aug 18 01:03:43 2003 +0000
@@ -33,6 +33,7 @@
 
 #include <X11/ICE/ICElib.h>
 #include <X11/SM/SMlib.h>
+#include <gdk/gdkx.h>
 #include <unistd.h>
 #include <fcntl.h>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/signals.c	Mon Aug 18 01:03:43 2003 +0000
@@ -0,0 +1,572 @@
+/**
+ * @file signal.h Signal API
+ * @ingroup core
+ *
+ * gaim
+ *
+ * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "internal.h"
+
+#include "debug.h"
+#include "signals.h"
+
+typedef struct
+{
+	void *instance;
+
+	GHashTable *signals;
+	size_t signal_count;
+
+	gulong next_signal_id;
+
+} GaimInstanceData;
+
+typedef struct
+{
+	gulong id;
+
+	GaimSignalMarshalFunc marshal;
+
+	GList *handlers;
+	size_t handler_count;
+
+	gulong next_handler_id;
+
+} GaimSignalData;
+
+typedef struct
+{
+	gulong id;
+	GaimCallback cb;
+	void *handle;
+	void *data;
+
+} GaimSignalHandlerData;
+
+static GHashTable *instance_table = NULL;
+
+static void
+destroy_instance_data(GaimInstanceData *instance_data)
+{
+	g_hash_table_destroy(instance_data->signals);
+
+	g_free(instance_data);
+}
+
+static void
+destroy_signal_data(GaimSignalData *signal_data)
+{
+	GaimSignalHandlerData *handler_data;
+	GList *l;
+
+	for (l = signal_data->handlers; l != NULL; l = l->next)
+	{
+		handler_data = (GaimSignalHandlerData *)l->data;
+
+		g_free(l->data);
+	}
+
+	g_list_free(signal_data->handlers);
+
+	g_free(signal_data);
+}
+
+gulong
+gaim_signal_register(void *instance, const char *signal,
+					 GaimSignalMarshalFunc marshal)
+{
+	GaimInstanceData *instance_data;
+	GaimSignalData *signal_data;
+
+	g_return_val_if_fail(instance != NULL, 0);
+	g_return_val_if_fail(signal   != NULL, 0);
+	g_return_val_if_fail(marshal  != NULL, 0);
+
+	instance_data =
+		(GaimInstanceData *)g_hash_table_lookup(instance_table, instance);
+
+	if (instance_data == NULL)
+	{
+		instance_data = g_new0(GaimInstanceData, 1);
+
+		instance_data->instance = instance;
+		instance_data->next_signal_id = 1;
+
+		instance_data->signals =
+			g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+								  (GDestroyNotify)destroy_signal_data);
+
+		g_hash_table_insert(instance_table, instance, instance_data);
+	}
+
+	signal_data = g_new0(GaimSignalData, 1);
+	signal_data->id              = instance_data->next_signal_id;
+	signal_data->marshal         = marshal;
+	signal_data->next_handler_id = 1;
+
+	g_hash_table_insert(instance_data->signals,
+						g_strdup(signal), signal_data);
+
+	instance_data->next_signal_id++;
+	instance_data->signal_count++;
+
+	return signal_data->id;
+}
+
+void
+gaim_signal_unregister(void *instance, const char *signal)
+{
+	GaimInstanceData *instance_data;
+
+	g_return_if_fail(instance != NULL);
+	g_return_if_fail(signal   != NULL);
+
+	instance_data =
+		(GaimInstanceData *)g_hash_table_lookup(instance_table, instance);
+
+	g_return_if_fail(instance_data != NULL);
+
+	g_hash_table_remove(instance_data->signals, signal);
+
+	instance_data->signal_count--;
+
+	if (instance_data->signal_count == 0)
+	{
+		/* Unregister the instance. */
+		g_hash_table_remove(instance_table, instance);
+	}
+}
+
+void
+gaim_signals_unregister_by_instance(void *instance)
+{
+	gboolean found;
+
+	g_return_if_fail(instance != NULL);
+
+	found = g_hash_table_remove(instance_table, instance);
+
+	/*
+	 * Makes things easier (more annoying?) for developers who don't have
+	 * things registering and unregistering in the right order :)
+	 */
+	g_return_if_fail(found);
+}
+
+gulong
+gaim_signal_connect(void *instance, const char *signal, void *handle,
+					GaimCallback func, void *data)
+{
+	GaimInstanceData *instance_data;
+	GaimSignalData *signal_data;
+	GaimSignalHandlerData *handler_data;
+
+	g_return_val_if_fail(instance != NULL, 0);
+	g_return_val_if_fail(signal   != NULL, 0);
+	g_return_val_if_fail(handle   != NULL, 0);
+	g_return_val_if_fail(func     != NULL, 0);
+
+	/* Get the instance data */
+	instance_data =
+		(GaimInstanceData *)g_hash_table_lookup(instance_table, instance);
+
+	g_return_val_if_fail(instance_data != NULL, 0);
+
+	/* Get the signal data */
+	signal_data =
+		(GaimSignalData *)g_hash_table_lookup(instance_data->signals, signal);
+
+	if (signal_data == NULL)
+	{
+		gaim_debug(GAIM_DEBUG_ERROR, "signals",
+				   "Signal data for %s not found!\n", signal);
+		return 0;
+	}
+
+	/* Create the signal handler data */
+	handler_data = g_new0(GaimSignalHandlerData, 1);
+	handler_data->id     = signal_data->next_handler_id;
+	handler_data->cb     = func;
+	handler_data->handle = handle;
+	handler_data->data   = data;
+
+	signal_data->handlers = g_list_append(signal_data->handlers, handler_data);
+	signal_data->handler_count++;
+	signal_data->next_handler_id++;
+
+	return handler_data->id;
+}
+
+void
+gaim_signal_disconnect(void *instance, const char *signal,
+					   void *handle, GaimCallback func)
+{
+	GaimInstanceData *instance_data;
+	GaimSignalData *signal_data;
+	GaimSignalHandlerData *handler_data;
+	GList *l;
+	gboolean found = FALSE;
+
+	g_return_if_fail(instance != NULL);
+	g_return_if_fail(signal   != NULL);
+	g_return_if_fail(handle   != NULL);
+	g_return_if_fail(func     != NULL);
+
+	/* Get the instance data */
+	instance_data =
+		(GaimInstanceData *)g_hash_table_lookup(instance_table, instance);
+
+	g_return_if_fail(instance_data != NULL);
+
+	/* Get the signal data */
+	signal_data =
+		(GaimSignalData *)g_hash_table_lookup(instance_data->signals, signal);
+
+	if (signal_data == NULL)
+	{
+		gaim_debug(GAIM_DEBUG_ERROR, "signals",
+				   "Signal data for %s not found!\n", signal);
+		return;
+	}
+
+	/* Find the handler data. */
+	for (l = signal_data->handlers; l != NULL; l = l->next)
+	{
+		handler_data = (GaimSignalHandlerData *)l->data;
+
+		if (handler_data->handle == handle && handler_data->cb == func)
+		{
+			g_free(handler_data);
+
+			signal_data->handlers = g_list_remove(signal_data->handlers,
+												  handler_data);
+			signal_data->handler_count--;
+
+			found = TRUE;
+
+			break;
+		}
+	}
+
+	/* See note somewhere about this actually helping developers.. */
+	g_return_if_fail(found);
+}
+
+/*
+ * TODO: Make this all more efficient by storing a list of handlers, keyed
+ *       to a handle.
+ */
+static void
+disconnect_handle_from_signals(const char *signal,
+							   GaimSignalData *signal_data, void *handle)
+{
+	GList *l, *l_next;
+	GaimSignalHandlerData *handler_data;
+
+	for (l = signal_data->handlers; l != NULL; l = l_next)
+	{
+		handler_data = (GaimSignalHandlerData *)l->data;
+		l_next = l->next;
+
+		if (handler_data->handle == handle)
+		{
+			g_free(handler_data);
+
+			signal_data->handler_count--;
+			signal_data->handlers = g_list_remove(signal_data->handlers,
+												  handler_data);
+		}
+	}
+}
+
+static void
+disconnect_handle_from_instance(void *instance,
+								GaimInstanceData *instance_data,
+								void *handle)
+{
+	g_hash_table_foreach(instance_data->signals,
+						 (GHFunc)disconnect_handle_from_signals, handle);
+}
+
+void
+gaim_signals_disconnect_by_handle(void *handle)
+{
+	g_return_if_fail(handle != NULL);
+
+	g_hash_table_foreach(instance_table,
+						 (GHFunc)disconnect_handle_from_instance, handle);
+}
+
+void
+gaim_signal_emit(void *instance, const char *signal, ...)
+{
+	va_list args;
+
+	va_start(args, signal);
+	gaim_signal_emit_vargs(instance, signal, args);
+	va_end(args);
+}
+
+void
+gaim_signal_emit_vargs(void *instance, const char *signal, va_list args)
+{
+	GaimInstanceData *instance_data;
+	GaimSignalData *signal_data;
+	GaimSignalHandlerData *handler_data;
+	GList *l;
+
+	g_return_if_fail(instance != NULL);
+	g_return_if_fail(signal   != NULL);
+
+	instance_data =
+		(GaimInstanceData *)g_hash_table_lookup(instance_table, instance);
+
+	g_return_if_fail(instance_data != NULL);
+
+	signal_data =
+		(GaimSignalData *)g_hash_table_lookup(instance_data->signals, signal);
+
+	if (signal_data == NULL)
+	{
+		gaim_debug(GAIM_DEBUG_ERROR, "signals",
+				   "Signal data for %s not found!\n", signal);
+		return;
+	}
+
+	for (l = signal_data->handlers; l != NULL; l = l->next)
+	{
+		handler_data = (GaimSignalHandlerData *)l->data;
+
+		signal_data->marshal(handler_data->cb, args, handler_data->data, NULL);
+	}
+}
+
+void *
+gaim_signal_emit_return_1(void *instance, const char *signal, ...)
+{
+	void *ret_val;
+	va_list args;
+
+	va_start(args, signal);
+	ret_val = gaim_signal_emit_vargs_return_1(instance, signal, args);
+	va_end(args);
+
+	return ret_val;
+}
+
+void *
+gaim_signal_emit_vargs_return_1(void *instance, const char *signal,
+								va_list args)
+{
+	GaimInstanceData *instance_data;
+	GaimSignalData *signal_data;
+	GaimSignalHandlerData *handler_data;
+	void *ret_val = NULL;
+	GList *l;
+
+	g_return_val_if_fail(instance != NULL, NULL);
+	g_return_val_if_fail(signal   != NULL, NULL);
+
+	instance_data =
+		(GaimInstanceData *)g_hash_table_lookup(instance_table, instance);
+
+	g_return_val_if_fail(instance_data != NULL, NULL);
+
+	signal_data =
+		(GaimSignalData *)g_hash_table_lookup(instance_data->signals, signal);
+
+	if (signal_data == NULL)
+	{
+		gaim_debug(GAIM_DEBUG_ERROR, "signals",
+				   "Signal data for %s not found!\n", signal);
+		return 0;
+	}
+
+	for (l = signal_data->handlers; l != NULL; l = l->next)
+	{
+		handler_data = (GaimSignalHandlerData *)l->data;
+
+		signal_data->marshal(handler_data->cb, args, handler_data->data,
+							 &ret_val);
+	}
+
+	return ret_val;
+}
+
+void
+gaim_signals_init()
+{
+	g_return_if_fail(instance_table == NULL);
+
+	instance_table =
+		g_hash_table_new_full(g_direct_hash, g_direct_equal,
+							  NULL, (GDestroyNotify)destroy_instance_data);
+}
+
+void
+gaim_signals_uninit()
+{
+	g_return_if_fail(instance_table != NULL);
+
+	g_hash_table_destroy(instance_table);
+	instance_table = NULL;
+}
+
+/**************************************************************************
+ * Marshallers
+ **************************************************************************/
+void
+gaim_marshal_VOID(GaimCallback cb, va_list args, void *data,
+				  void **return_val)
+{
+	((void (*)(void *))cb)(data);
+}
+
+void
+gaim_marshal_VOID__POINTER(GaimCallback cb, va_list args, void *data,
+						   void **return_val)
+{
+	((void (*)(void *, void *))cb)(va_arg(args, void *), data);
+}
+
+void
+gaim_marshal_VOID__POINTER_POINTER(GaimCallback cb, va_list args,
+								   void *data, void **return_val)
+{
+	((void (*)(void *, void *, void *))cb)(va_arg(args, void *),
+										   va_arg(args, void *),
+										   data);
+}
+
+void
+gaim_marshal_VOID__POINTER_POINTER_UINT(GaimCallback cb, va_list args,
+										void *data, void **return_val)
+{
+	((void (*)(void *, void *, guint, void *))cb)(va_arg(args, void *),
+												  va_arg(args, void *),
+												  va_arg(args, guint),
+												  data);
+}
+
+void
+gaim_marshal_VOID__POINTER_POINTER_POINTER(GaimCallback cb, va_list args,
+										   void *data, void **return_val)
+{
+	((void (*)(void *, void *, void *, void *))cb)(va_arg(args, void *),
+												   va_arg(args, void *),
+												   va_arg(args, void *),
+												   data);
+}
+
+void
+gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER(GaimCallback cb,
+												   va_list args,
+												   void *data,
+												   void **return_val)
+{
+	((void (*)(void *, void *, void *, void *, void *))cb)(
+		va_arg(args, void *), va_arg(args, void *),
+		va_arg(args, void *), va_arg(args, void *), data);
+}
+void
+gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT(GaimCallback cb,
+													 va_list args,
+													 void *data,
+													 void **return_val)
+{
+	((void (*)(void *, void *, void *, guint, guint, void *))cb)(
+			va_arg(args, void *), va_arg(args, void *),
+			va_arg(args, void *), va_arg(args, guint),
+			va_arg(args, guint), data);
+}
+
+void
+gaim_marshal_BOOLEAN__POINTER(GaimCallback cb, va_list args, void *data,
+							  void **return_val)
+{
+	gboolean ret_val;
+
+	ret_val = ((gboolean (*)(void *, void *))cb)(va_arg(args, void *), data);
+
+	if (return_val != NULL)
+		*return_val = GINT_TO_POINTER(ret_val);
+}
+
+void
+gaim_marshal_BOOLEAN__POINTER_POINTER(GaimCallback cb, va_list args,
+									  void *data, void **return_val)
+{
+	gboolean ret_val;
+
+	ret_val = ((gboolean (*)(void *, void *, void *))cb)(va_arg(args, void *),
+														 va_arg(args, void *),
+														 data);
+
+	if (return_val != NULL)
+		*return_val = GINT_TO_POINTER(ret_val);
+}
+
+void
+gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT(GaimCallback cb,
+												   va_list args,
+												   void *data,
+												   void **return_val)
+{
+	gboolean ret_val;
+
+	ret_val = ((gboolean (*)(void *, void *, void *, guint, void *))cb)(
+			va_arg(args, void *), va_arg(args, void *),
+			va_arg(args, void *), va_arg(args, guint),
+			data);
+
+	if (return_val != NULL)
+		*return_val = GINT_TO_POINTER(ret_val);
+}
+
+void
+gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER(GaimCallback cb,
+													  va_list args,
+													  void *data,
+													  void **return_val)
+{
+	gboolean ret_val;
+
+	ret_val = ((gboolean (*)(void *, void *, void *, void *, void *))cb)(
+			va_arg(args, void *), va_arg(args, void *),
+			va_arg(args, void *), va_arg(args, void *),
+			data);
+
+	if (return_val != NULL)
+		*return_val = GINT_TO_POINTER(ret_val);
+}
+
+void
+gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val)
+{
+	gboolean ret_val;
+
+	ret_val =
+		((gboolean (*)(void *, void *, void *, void *, void *, void *))cb)(
+			va_arg(args, void *), va_arg(args, void *),
+			va_arg(args, void *), va_arg(args, void *),
+			va_arg(args, void *), data);
+
+	if (return_val != NULL)
+		*return_val = GINT_TO_POINTER(ret_val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/signals.h	Mon Aug 18 01:03:43 2003 +0000
@@ -0,0 +1,251 @@
+/**
+ * @file signal.h Signal API
+ * @ingroup core
+ *
+ * gaim
+ *
+ * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _GAIM_SIGNAL_H_
+#define _GAIM_SIGNAL_H_
+
+#include <glib.h>
+
+#if 0
+/**
+ * Event types
+ */
+typedef enum gaim_event
+{
+	event_signon = 0,
+	event_signoff,
+	event_away,
+	event_back,
+	event_im_recv,
+	event_im_send,
+	event_buddy_signon,
+	event_buddy_signoff,
+	event_buddy_away,
+	event_buddy_back,
+	event_buddy_idle,
+	event_buddy_unidle,
+	event_blist_update,
+	event_chat_invited,
+	event_chat_join,
+	event_chat_leave,
+	event_chat_buddy_join,
+	event_chat_buddy_leave,
+	event_chat_recv,
+	event_chat_send,
+	event_warned,
+	event_error,
+	event_quit,
+	event_new_conversation,
+	event_set_info,
+	event_draw_menu,
+	event_im_displayed_sent,
+	event_im_displayed_rcvd,
+	event_chat_send_invite,
+	event_got_typing,
+	event_del_conversation,
+	event_connecting,
+	event_conversation_switch
+	/* any others? it's easy to add... */
+
+} GaimEvent;
+
+typedef int (*GaimSignalBroadcastFunc)(GaimEvent event, void *data,
+									   va_list args);
+#endif
+
+#define GAIM_CALLBACK(func) ((GaimCallback)func)
+
+typedef void (*GaimCallback)(void);
+typedef void (*GaimSignalMarshalFunc)(GaimCallback cb, va_list args,
+									  void *data, void **return_val);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************/
+/** @name Signal API                                                      */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Registers a signal in an instance.
+ *
+ * @param instance The instance to register the signal for.
+ * @param signal   The signal name.
+ * @param marshal  The marshal function.
+ *
+ * @return The signal ID local to that instance, or 0 if the signal
+ *         couldn't be registered.
+ */
+gulong gaim_signal_register(void *instance, const char *signal,
+							GaimSignalMarshalFunc marshal);
+
+/**
+ * Unregisters a signal in an instance.
+ *
+ * @param instance The instance to unregister the signal for.
+ * @param signal   The signal name.
+ */
+void gaim_signal_unregister(void *instance, const char *signal);
+
+/**
+ * Unregisters all signals in an instance.
+ *
+ * @param instance The instance to unregister the signal for.
+ */
+void gaim_signals_unregister_by_instance(void *instance);
+
+/**
+ * Connects a signal handler to a signal for a particular object.
+ *
+ * Take care not to register a handler function twice. Gaim will
+ * not correct any mistakes for you in this area.
+ *
+ * @param instance The instance to connect to.
+ * @param signal   The name of the signal to connect.
+ * @param handle   The handle of the receiver.
+ * @param func     The callback function.
+ * @param data     The data to pass to the callback function.
+ *
+ * @return The signal handler ID.
+ *
+ * @see gaim_signal_disconnect()
+ */
+gulong gaim_signal_connect(void *instance, const char *signal,
+						   void *handle, GaimCallback func, void *data);
+
+/**
+ * Disconnects a signal handler from a signal on an object.
+ *
+ * @param instance The instance to disconnect from.
+ * @param signal   The name of the signal to disconnect.
+ * @param handle   The handle of the receiver.
+ * @param func     The registered function to disconnect.
+ *
+ * @see gaim_signal_connect()
+ */
+void gaim_signal_disconnect(void *instance, const char *signal,
+							void *handle, GaimCallback func);
+
+/**
+ * Removes all callbacks associated with a receiver handle.
+ *
+ * @param handle The receiver handle.
+ */
+void gaim_signals_disconnect_by_handle(void *handle);
+
+/**
+ * Emits a signal.
+ *
+ * @param instance The instance emitting the signal.
+ * @param signal   The signal being emitted.
+ *
+ * @see gaim_signal_connect()
+ * @see gaim_signal_disconnect()
+ */
+void gaim_signal_emit(void *instance, const char *signal, ...);
+
+/**
+ * Emits a signal, using a va_list of arguments.
+ *
+ * @param instance The instance emitting the signal.
+ * @param signal   The signal being emitted.
+ * @param args     The arguments list.
+ *
+ * @see gaim_signal_connect()
+ * @see gaim_signal_disconnect()
+ */
+void gaim_signal_emit_vargs(void *instance, const char *signal, va_list args);
+
+/**
+ * Emits a signal and returns the return value from the last handler.
+ *
+ * @param instance The instance emitting the signal.
+ * @param signal   The signal being emitted.
+ *
+ * @return The return value from the last handler.
+ */
+void *gaim_signal_emit_return_1(void *instance, const char *signal, ...);
+
+/**
+ * Emits a signal and returns the return value from the last handler.
+ *
+ * @param instance The instance emitting the signal.
+ * @param signal   The signal being emitted.
+ * @param args     The arguments list.
+ *
+ * @return The return value from the last handler.
+ */
+void *gaim_signal_emit_vargs_return_1(void *instance, const char *signal,
+									  va_list args);
+
+/**
+ * Initializes the signals subsystem.
+ */
+void gaim_signals_init();
+
+/**
+ * Uninitializes the signals subsystem.
+ */
+void gaim_signals_uninit();
+
+/*@}*/
+
+/**************************************************************************/
+/** @name Marshal Functions                                               */
+/**************************************************************************/
+/*@{*/
+
+void gaim_marshal_VOID(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_VOID__POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_VOID__POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_VOID__POINTER_POINTER_UINT(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_VOID__POINTER_POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+
+void gaim_marshal_BOOLEAN__POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_BOOLEAN__POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GAIM_SIGNAL_H_ */