Index: protocols/Makefile
===================================================================
--- protocols/Makefile	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/Makefile	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT)
+objects = $(EVENT_HANDLER) http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT)
 
 # [SH] The next two lines should contain the directory name (in $(subdirs))
Index: protocols/events.h
===================================================================
--- protocols/events.h	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
+++ protocols/events.h	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -0,0 +1,66 @@
+/*
+ * nogaim
+ *
+ * Copyright (C) 2006 Wilmer van der Gaast and others
+ *
+ * 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
+ *
+ */
+
+/*
+ * Split off the event handling things from proxy.[ch] (and adding timer
+ * stuff. This to allow BitlBee to use other libs than GLib for event
+ * handling.
+ */
+
+
+#ifndef _EVENTS_H_
+#define _EVENTS_H_
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#endif
+#include <glib.h>
+#include <gmodule.h>
+
+typedef enum {
+	GAIM_INPUT_READ = 1 << 1,
+	GAIM_INPUT_WRITE = 1 << 2
+} b_input_condition;
+typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond);
+
+#define GAIM_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+#define GAIM_ERR_COND   (G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+// #define event_debug( x... ) printf( x )
+#define event_debug( x... )
+
+G_MODULE_EXPORT void b_main_init();
+G_MODULE_EXPORT void b_main_run();
+G_MODULE_EXPORT void b_main_quit();
+
+G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data);
+G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data);
+G_MODULE_EXPORT void b_event_remove(gint id);
+
+#ifdef EVENTS_LIBEVENT
+G_MODULE_EXPORT void closesocket(int fd);
+#endif
+
+#endif /* _EVENTS_H_ */
Index: protocols/events_glib.c
===================================================================
--- protocols/events_glib.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
+++ protocols/events_glib.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -0,0 +1,137 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2006 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/*
+ * Event handling (using GLib)
+ */
+
+/*
+  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 with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define BITLBEE_CORE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#else
+#include "sock.h"
+#define ETIMEDOUT WSAETIMEDOUT
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include "proxy.h"
+
+typedef struct _GaimIOClosure {
+	b_event_handler function;
+	guint result;
+	gpointer data;
+} GaimIOClosure;
+
+static GMainLoop *loop;
+
+void b_main_init()
+{
+	loop = g_main_new( FALSE );
+}
+
+void b_main_run()
+{
+	g_main_run( loop );
+}
+
+void b_main_quit()
+{
+	g_main_quit( loop );
+}
+
+static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	GaimIOClosure *closure = data;
+	b_input_condition gaim_cond = 0;
+	gboolean st;
+
+	if (condition & GAIM_READ_COND)
+		gaim_cond |= GAIM_INPUT_READ;
+	if (condition & GAIM_WRITE_COND)
+		gaim_cond |= GAIM_INPUT_WRITE;
+	
+	event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data );
+
+	st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
+	
+	if( !st )
+		event_debug( "Returned FALSE, cancelling.\n" );
+	
+	return st;
+}
+
+static void gaim_io_destroy(gpointer data)
+{
+	event_debug( "gaim_io_destroy( 0x%x )\n", data );
+	g_free(data);
+}
+
+gint b_input_add(gint source, b_input_condition condition, b_event_handler function, gpointer data)
+{
+	GaimIOClosure *closure = g_new0(GaimIOClosure, 1);
+	GIOChannel *channel;
+	GIOCondition cond = 0;
+	
+	closure->function = function;
+	closure->data = data;
+	
+	if (condition & GAIM_INPUT_READ)
+		cond |= GAIM_READ_COND;
+	if (condition & GAIM_INPUT_WRITE)
+		cond |= GAIM_WRITE_COND;
+	
+	channel = g_io_channel_unix_new(source);
+	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
+					      gaim_io_invoke, closure, gaim_io_destroy);
+	
+	event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure );
+	
+	g_io_channel_unref(channel);
+	return closure->result;
+}
+
+gint b_timeout_add(gint timeout, b_event_handler func, gpointer data)
+{
+	gint st = g_timeout_add(timeout, func, data);
+	
+	event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st );
+	
+	return st;
+}
+
+void b_event_remove(gint tag)
+{
+	event_debug( "b_event_remove( %d )\n", tag );
+	
+	if (tag > 0)
+		g_source_remove(tag);
+}
Index: protocols/events_libevent.c
===================================================================
--- protocols/events_libevent.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
+++ protocols/events_libevent.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -0,0 +1,247 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2006 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/*
+ * Event handling (using libevent)
+ */
+
+/*
+  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 with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define BITLBEE_CORE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "proxy.h"
+
+#include <sys/time.h>
+#include <event.h>
+
+static guint id_next;
+static GHashTable *id_hash;
+static int quitting = 0;
+
+/* Since libevent doesn't handle two event handlers for one fd-condition
+   very well (which happens sometimes when BitlBee changes event handlers
+   for a combination), let's buid some indexes so we can delete them here
+   already, just in time. */
+static GHashTable *read_hash;
+static GHashTable *write_hash;
+
+struct b_event_data
+{
+	guint id;
+	struct event evinfo;
+	gint timeout;
+	b_event_handler function;
+	void *data;
+};
+
+void b_main_init()
+{
+	event_init();
+	
+	id_next = 1;
+	id_hash = g_hash_table_new( g_int_hash, g_int_equal );
+	read_hash = g_hash_table_new( g_int_hash, g_int_equal );
+	write_hash = g_hash_table_new( g_int_hash, g_int_equal );
+}
+
+void b_main_run()
+{
+	event_dispatch();
+}
+
+void b_main_quit()
+{
+	struct timeval tv;
+	
+	/* libevent sometimes generates events before really quitting,
+	   we want to stop them. */
+	quitting = 1;
+	
+	memset( &tv, 0, sizeof( struct timeval ) );
+	event_loopexit( &tv );
+}
+
+static void b_event_passthrough( int fd, short event, void *data )
+{
+	struct b_event_data *b_ev = data;
+	b_input_condition cond = 0;
+	int id;
+	
+	if( fd >= 0 )
+	{
+		if( event & EV_READ )
+			cond |= GAIM_INPUT_READ;
+		if( event & EV_WRITE )
+			cond |= GAIM_INPUT_WRITE;
+	}
+	
+	event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id );
+	
+	/* Since the called function might cancel this handler already
+	   (which free()s b_ev, we have to remember the ID here. */
+	id = b_ev->id;
+	
+	if( quitting )
+	{
+		b_event_remove( id );
+		return;
+	}
+	
+	if( !b_ev->function( b_ev->data, fd, cond ) )
+	{
+		event_debug( "Handler returned FALSE: " );
+		b_event_remove( id );
+	}
+	else if( fd == -1 )
+	{
+		struct timeval tv;
+		
+		tv.tv_sec = b_ev->timeout / 1000;
+		tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000;
+		
+		evtimer_add( &b_ev->evinfo, &tv );
+	}
+}
+
+gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data )
+{
+	struct b_event_data *b_ev;
+	
+	event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data );
+	
+	if( ( condition & GAIM_INPUT_READ  && ( b_ev = g_hash_table_lookup( read_hash,  &fd ) ) ) ||
+	    ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
+	{
+		/* We'll stick with this libevent entry, but give it a new BitlBee id. */
+		g_hash_table_remove( id_hash, &b_ev->id );
+		
+		event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next );
+		
+		b_ev->id = id_next++;
+		b_ev->function = function;
+		b_ev->data = data;
+	}
+	else
+	{
+		GIOCondition out_cond;
+		
+		event_debug( "(new) = %d\n", id_next );
+		
+		b_ev = g_new0( struct b_event_data, 1 );
+		b_ev->id = id_next++;
+		b_ev->function = function;
+		b_ev->data = data;
+		
+		out_cond = EV_PERSIST;
+		if( condition & GAIM_INPUT_READ )
+			out_cond |= EV_READ;
+		if( condition & GAIM_INPUT_WRITE )
+			out_cond |= EV_WRITE;
+		
+		event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev );
+		event_add( &b_ev->evinfo, NULL );
+		
+		if( out_cond & EV_READ )
+			g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev );
+		if( out_cond & EV_WRITE )
+			g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev );
+	}
+	
+	g_hash_table_insert( id_hash, &b_ev->id, b_ev );
+	return b_ev->id;
+}
+
+/* TODO: Persistence for timers! */
+gint b_timeout_add( gint timeout, b_event_handler function, gpointer data )
+{
+	struct b_event_data *b_ev = g_new0( struct b_event_data, 1 );
+	struct timeval tv;
+	
+	b_ev->id = id_next++;
+	b_ev->timeout = timeout;
+	b_ev->function = function;
+	b_ev->data = data;
+	
+	tv.tv_sec = timeout / 1000;
+	tv.tv_usec = ( timeout % 1000 ) * 1000;
+	
+	evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev );
+	evtimer_add( &b_ev->evinfo, &tv );
+	
+	event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id );
+	
+	g_hash_table_insert( id_hash, &b_ev->id, b_ev );
+	
+	return b_ev->id;
+}
+
+void b_event_remove( gint id )
+{
+	struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id );
+	
+	event_debug( "b_event_remove( %d )\n", id );
+	if( b_ev )
+	{
+		g_hash_table_remove( id_hash, &b_ev->id );
+		if( b_ev->evinfo.ev_fd >= 0 )
+		{
+			if( b_ev->evinfo.ev_events & EV_READ )
+				g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd );
+			if( b_ev->evinfo.ev_events & EV_WRITE )
+				g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd );
+		}
+		
+		event_del( &b_ev->evinfo );
+		g_free( b_ev );
+	}
+	else
+	{
+		event_debug( "Already removed?\n" );
+	}
+}
+
+void closesocket( int fd )
+{
+	struct b_event_data *b_ev;
+	
+	/* Since epoll() (the main reason we use libevent) automatically removes sockets from
+	   the epoll() list when a socket gets closed and some modules have a habit of
+	   closing sockets before removing event handlers, our and libevent's administration
+	   get a little bit messed up. So this little function will remove the handlers
+	   properly before closing a socket. */
+	
+	if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) )
+	{
+		event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd );
+		b_event_remove( b_ev->id );
+	}
+	if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) )
+	{
+		event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd );
+		b_event_remove( b_ev->id );
+	}
+	
+	close( fd );
+}
Index: protocols/http_client.c
===================================================================
--- protocols/http_client.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/http_client.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -32,7 +32,7 @@
 
 
-static void http_connected( gpointer data, int source, GaimInputCondition cond );
-static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond );
-static void http_incoming_data( gpointer data, int source, GaimInputCondition cond );
+static gboolean http_connected( gpointer data, int source, b_input_condition cond );
+static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond );
+static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond );
 
 
@@ -104,5 +104,5 @@
 /* This one is actually pretty simple... Might get more calls if we can't write 
    the whole request at once. */
-static void http_connected( gpointer data, int source, GaimInputCondition cond )
+static gboolean http_connected( gpointer data, int source, b_input_condition cond )
 {
 	struct http_request *req = data;
@@ -113,5 +113,5 @@
 	
 	if( req->inpa > 0 )
-		gaim_input_remove( req->inpa );
+		b_event_remove( req->inpa );
 	
 	sock_make_nonblocking( req->fd );
@@ -148,11 +148,11 @@
 	
 	if( req->bytes_written < req->request_length )
-		req->inpa = gaim_input_add( source,
-		                            req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
-	        	                    http_connected, req );
-	else
-		req->inpa = gaim_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
-	
-	return;
+		req->inpa = b_input_add( source,
+		                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
+	        	                 http_connected, req );
+	else
+		req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
+	
+	return FALSE;
 	
 error:
@@ -164,8 +164,8 @@
 	g_free( req );
 	
-	return;
+	return FALSE;
 }
 
-static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond )
+static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond )
 {
 	struct http_request *req = data;
@@ -179,5 +179,5 @@
 }
 
-static void http_incoming_data( gpointer data, int source, GaimInputCondition cond )
+static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
 {
 	struct http_request *req = data;
@@ -188,5 +188,5 @@
 	
 	if( req->inpa > 0 )
-		gaim_input_remove( req->inpa );
+		b_event_remove( req->inpa );
 	
 	if( req->ssl )
@@ -236,9 +236,9 @@
 	
 	/* There will be more! */
-	req->inpa = gaim_input_add( req->fd,
-	                            req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
-	                            http_incoming_data, req );
-	
-	return;
+	req->inpa = b_input_add( req->fd,
+	                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
+	                         http_incoming_data, req );
+	
+	return FALSE;
 
 got_reply:
@@ -430,5 +430,5 @@
 		req->reply_headers = req->reply_body = NULL;
 		
-		return;
+		return FALSE;
 	}
 	
@@ -449,3 +449,5 @@
 	g_free( req->status_string );
 	g_free( req );
+	
+	return FALSE;
 }
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/jabber/jabber.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -471,5 +471,5 @@
 }
 
-static void jabber_callback(gpointer data, gint source, GaimInputCondition condition)
+static gboolean jabber_callback(gpointer data, gint source, b_input_condition condition)
 {
 	struct gaim_connection *gc = (struct gaim_connection *)data;
@@ -477,4 +477,6 @@
 
 	gjab_recv(jd->gjc);
+	
+	return TRUE;
 }
 
@@ -487,5 +489,5 @@
 }
 
-static void gjab_connected(gpointer data, gint source, GaimInputCondition cond)
+static gboolean gjab_connected(gpointer data, gint source, b_input_condition cond)
 {
 	xmlnode x;
@@ -497,5 +499,5 @@
 	if (!g_slist_find(get_connections(), gc)) {
 		closesocket(source);
-		return;
+		return FALSE;
 	}
 
@@ -508,5 +510,5 @@
 	if (source == -1) {
 		STATE_EVT(JCONN_STATE_OFF)
-		return;
+		return FALSE;
 	}
 
@@ -530,8 +532,10 @@
 
 	gc = GJ_GC(gjc);
-	gc->inpa = gaim_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc);
-}
-
-static void gjab_connected_ssl(gpointer data, void *source, GaimInputCondition cond)
+	gc->inpa = b_input_add(gjc->fd, GAIM_INPUT_READ, jabber_callback, gc);
+	
+	return FALSE;
+}
+
+static gboolean gjab_connected_ssl(gpointer data, void *source, b_input_condition cond)
 {
 	struct gaim_connection *gc = data;
@@ -544,13 +548,13 @@
 	if (source == NULL) {
 		STATE_EVT(JCONN_STATE_OFF)
-		return;
+		return FALSE;
 	}
 	
 	if (!g_slist_find(get_connections(), gc)) {
 		ssl_disconnect(source);
-		return;
+		return FALSE;
 	}
 	
-	gjab_connected(data, gjc->fd, cond);
+	return gjab_connected(data, gjc->fd, cond);
 }
 
@@ -1543,5 +1547,5 @@
 }
 
-static gboolean jabber_free(gpointer data)
+static gboolean jabber_free(gpointer data, gint fd, b_input_condition cond)
 {
 	struct jabber_data *jd = data;
@@ -1588,8 +1592,8 @@
 	}
 	if (gc->inpa)
-		gaim_input_remove(gc->inpa);
+		b_event_remove(gc->inpa);
 
 	if(jd) {
-		g_timeout_add(50, jabber_free, jd);
+		b_timeout_add(50, jabber_free, jd);
 		if(jd->gjc != NULL)
 			xmlnode_free(jd->gjc->current);
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/msn/msn.h	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -146,5 +146,5 @@
 
 /* ns.c */
-void msn_ns_connected( gpointer data, gint source, GaimInputCondition cond );
+gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
 
 /* msn_util.c */
@@ -173,3 +173,3 @@
 void msn_sb_to_chat( struct msn_switchboard *sb );
 void msn_sb_destroy( struct msn_switchboard *sb );
-void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond );
+gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond );
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/msn/ns.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -30,5 +30,5 @@
 #include "md5.h"
 
-static void msn_ns_callback( gpointer data, gint source, GaimInputCondition cond );
+static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
 static int msn_ns_command( gpointer data, char **cmd, int num_parts );
 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
@@ -36,5 +36,5 @@
 static void msn_auth_got_passport_id( struct passport_reply *rep );
 
-void msn_ns_connected( gpointer data, gint source, GaimInputCondition cond )
+gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
 {
 	struct gaim_connection *gc = data;
@@ -43,5 +43,5 @@
 	
 	if( !g_slist_find( msn_connections, gc ) )
-		return;
+		return FALSE;
 	
 	if( source == -1 )
@@ -49,5 +49,5 @@
 		hide_login_progress( gc, "Could not connect to server" );
 		signoff( gc );
-		return;
+		return FALSE;
 	}
 	
@@ -75,10 +75,12 @@
 	if( msn_write( gc, s, strlen( s ) ) )
 	{
-		gc->inpa = gaim_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, gc );
+		gc->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, gc );
 		set_login_progress( gc, 1, "Connected to server, waiting for reply" );
 	}
+	
+	return FALSE;
 }
 
-void msn_ns_callback( gpointer data, gint source, GaimInputCondition cond )
+static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond )
 {
 	struct gaim_connection *gc = data;
@@ -89,5 +91,9 @@
 		hide_login_progress( gc, "Error while reading from server" );
 		signoff( gc );
-	}
+		
+		return FALSE;
+	}
+	else
+		return TRUE;
 }
 
@@ -130,5 +136,5 @@
 		if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )
 		{
-			gaim_input_remove( gc->inpa );
+			b_event_remove( gc->inpa );
 			gc->inpa = 0;
 			closesocket( md->fd );
Index: protocols/msn/sb.c
===================================================================
--- protocols/msn/sb.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/msn/sb.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -30,5 +30,5 @@
 #include "md5.h"
 
-static void msn_sb_callback( gpointer data, gint source, GaimInputCondition cond );
+static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
 static int msn_sb_command( gpointer data, char **cmd, int num_parts );
 static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
@@ -237,5 +237,5 @@
 	}
 	
-	if( sb->inp ) gaim_input_remove( sb->inp );
+	if( sb->inp ) b_event_remove( sb->inp );
 	closesocket( sb->fd );
 	
@@ -245,5 +245,5 @@
 }
 
-void msn_sb_connected( gpointer data, gint source, GaimInputCondition cond )
+gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond )
 {
 	struct msn_switchboard *sb = data;
@@ -254,5 +254,5 @@
 	/* Are we still alive? */
 	if( !g_slist_find( msn_switchboards, sb ) )
-		return;
+		return FALSE;
 	
 	gc = sb->gc;
@@ -263,5 +263,5 @@
 		debug( "ERROR %d while connecting to switchboard server", 1 );
 		msn_sb_destroy( sb );
-		return;
+		return FALSE;
 	}
 	
@@ -280,10 +280,12 @@
 	
 	if( msn_sb_write( sb, buf, strlen( buf ) ) )
-		sb->inp = gaim_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb );
+		sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb );
 	else
 		debug( "ERROR %d while connecting to switchboard server", 2 );
-}
-
-static void msn_sb_callback( gpointer data, gint source, GaimInputCondition cond )
+	
+	return FALSE;
+}
+
+static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond )
 {
 	struct msn_switchboard *sb = data;
@@ -293,5 +295,9 @@
 		debug( "ERROR: Switchboard died" );
 		msn_sb_destroy( sb );
-	}
+		
+		return FALSE;
+	}
+	else
+		return TRUE;
 }
 
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/nogaim.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -2,5 +2,5 @@
   * BitlBee -- An IRC to other IM-networks gateway                     *
   *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  * Copyright 2002-2006 Wilmer van der Gaast and others                *
   \********************************************************************/
 
@@ -13,6 +13,4 @@
  * from scratch for BitlBee and doesn't contain any code from Gaim anymore
  * (except for the function names).
- *
- * Copyright 2002-2006 Wilmer van der Gaast <wilmer@gaast.net> and others
  */
 
@@ -160,5 +158,5 @@
 	 * This fixes daemon mode breakage where IRC doesn't point to the currently active connection.
 	 */
-	gc->irc=user->irc;
+	gc->irc = user->irc;
 	
 	connections = g_slist_append( connections, gc );
@@ -240,5 +238,5 @@
 }
 
-static gboolean send_keepalive( gpointer d )
+static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond )
 {
 	struct gaim_connection *gc = d;
@@ -264,5 +262,5 @@
 	serv_got_crap( gc, "Logged in" );
 	
-	gc->keepalive = g_timeout_add( 60000, send_keepalive, gc );
+	gc->keepalive = b_timeout_add( 60000, send_keepalive, gc );
 	gc->flags |= OPT_LOGGED_IN;
 	
@@ -272,5 +270,5 @@
 }
 
-gboolean auto_reconnect( gpointer data )
+gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond )
 {
 	account_t *a = data;
@@ -284,5 +282,6 @@
 void cancel_auto_reconnect( account_t *a )
 {
-	while( g_source_remove_by_user_data( (gpointer) a ) );
+	/* while( b_event_remove_by_data( (gpointer) a ) ); */
+	b_event_remove( a->reconnect );
 	a->reconnect = 0;
 }
@@ -297,8 +296,8 @@
 	gc->flags |= OPT_LOGGING_OUT;
 	
-	gaim_input_remove( gc->keepalive );
+	b_event_remove( gc->keepalive );
 	gc->keepalive = 0;
 	gc->prpl->close( gc );
-	gaim_input_remove( gc->inpa );
+	b_event_remove( gc->inpa );
 	
 	while( u )
@@ -327,8 +326,7 @@
 	{
 		int delay = set_getint( irc, "auto_reconnect_delay" );
+		
 		serv_got_crap( gc, "Reconnecting in %d seconds..", delay );
-		
-		a->reconnect = 1;
-		g_timeout_add( delay * 1000, auto_reconnect, a );
+		a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a );
 	}
 	
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/nogaim.h	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -208,5 +208,5 @@
 char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value );
 
-gboolean auto_reconnect( gpointer data );
+gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond );
 void cancel_auto_reconnect( struct account *a );
 
Index: protocols/oscar/oscar.c
===================================================================
--- protocols/oscar/oscar.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/oscar/oscar.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -255,6 +255,6 @@
 static int msgerrreasonlen = 25;
 
-static void oscar_callback(gpointer data, gint source,
-				GaimInputCondition condition) {
+static gboolean oscar_callback(gpointer data, gint source,
+				b_input_condition condition) {
 	aim_conn_t *conn = (aim_conn_t *)data;
 	aim_session_t *sess = aim_conn_getsess(conn);
@@ -264,5 +264,5 @@
 	if (!gc) {
 		/* gc is null. we return, else we seg SIGSEG on next line. */
-		return;
+		return FALSE;
 	}
       
@@ -270,5 +270,5 @@
 		/* oh boy. this is probably bad. i guess the only thing we 
 		 * can really do is return? */
-		return;
+		return FALSE;
 	}
 
@@ -290,5 +290,5 @@
 				c->conn = NULL;
 				if (c->inpa > 0)
-					gaim_input_remove(c->inpa);
+					b_event_remove(c->inpa);
 				c->inpa = 0;
 				c->fd = -1;
@@ -298,5 +298,5 @@
 			} else if (conn->type == AIM_CONN_TYPE_CHATNAV) {
 				if (odata->cnpa > 0)
-					gaim_input_remove(odata->cnpa);
+					b_event_remove(odata->cnpa);
 				odata->cnpa = 0;
 				while (odata->create_rooms) {
@@ -312,5 +312,5 @@
 			} else if (conn->type == AIM_CONN_TYPE_AUTH) {
 				if (odata->paspa > 0)
-					gaim_input_remove(odata->paspa);
+					b_event_remove(odata->paspa);
 				odata->paspa = 0;
 				aim_conn_kill(odata->sess, &conn);
@@ -319,8 +319,13 @@
 			}
 		}
-	}
-}
-
-static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond)
+	} else {
+		/* WTF??? */
+		return FALSE;
+	}
+		
+	return TRUE;
+}
+
+static gboolean oscar_login_connect(gpointer data, gint source, b_input_condition cond)
 {
 	struct gaim_connection *gc = data;
@@ -331,5 +336,5 @@
 	if (!g_slist_find(get_connections(), gc)) {
 		closesocket(source);
-		return;
+		return FALSE;
 	}
 
@@ -341,10 +346,12 @@
 		hide_login_progress(gc, _("Couldn't connect to host"));
 		signoff(gc);
-		return;
+		return FALSE;
 	}
 
 	aim_conn_completeconnect(sess, conn);
-	gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ,
+	gc->inpa = b_input_add(conn->fd, GAIM_INPUT_READ,
 			oscar_callback, conn);
+	
+	return FALSE;
 }
 
@@ -414,5 +421,5 @@
 		struct chat_connection *n = odata->oscar_chats->data;
 		if (n->inpa > 0)
-			gaim_input_remove(n->inpa);
+			b_event_remove(n->inpa);
 		g_free(n->name);
 		g_free(n->show);
@@ -433,9 +440,9 @@
 		g_free(odata->oldp);
 	if (gc->inpa > 0)
-		gaim_input_remove(gc->inpa);
+		b_event_remove(gc->inpa);
 	if (odata->cnpa > 0)
-		gaim_input_remove(odata->cnpa);
+		b_event_remove(odata->cnpa);
 	if (odata->paspa > 0)
-		gaim_input_remove(odata->paspa);
+		b_event_remove(odata->paspa);
 	aim_session_kill(odata->sess);
 	g_free(odata->sess);
@@ -445,5 +452,5 @@
 }
 
-static void oscar_bos_connect(gpointer data, gint source, GaimInputCondition cond) {
+static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition cond) {
 	struct gaim_connection *gc = data;
 	struct oscar_data *odata;
@@ -453,5 +460,5 @@
 	if (!g_slist_find(get_connections(), gc)) {
 		closesocket(source);
-		return;
+		return FALSE;
 	}
 
@@ -463,11 +470,13 @@
 		hide_login_progress(gc, _("Could Not Connect"));
 		signoff(gc);
-		return;
+		return FALSE;
 	}
 
 	aim_conn_completeconnect(sess, bosconn);
-	gc->inpa = gaim_input_add(bosconn->fd, GAIM_INPUT_READ,
+	gc->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ,
 			oscar_callback, bosconn);
 	set_login_progress(gc, 4, _("Connection established, cookie sent"));
+	
+	return FALSE;
 }
 
@@ -572,5 +581,5 @@
 	}
 	aim_sendcookie(sess, bosconn, info->cookie);
-	gaim_input_remove(gc->inpa);
+	b_event_remove(gc->inpa);
 
 	return 1;
@@ -587,5 +596,5 @@
 };
 
-static void damn_you(gpointer data, gint source, GaimInputCondition c)
+static gboolean damn_you(gpointer data, gint source, b_input_condition c)
 {
 	struct pieceofcrap *pos = data;
@@ -607,19 +616,21 @@
 		do_error_dialog(pos->gc, "Gaim was unable to get a valid hash for logging into AIM."
 				" You may be disconnected shortly.", "Login Error");
-		gaim_input_remove(pos->inpa);
+		b_event_remove(pos->inpa);
 		closesocket(pos->fd);
 		g_free(pos);
-		return;
+		return FALSE;
 	}
 	/* [WvG] Wheeeee! Who needs error checking anyway? ;-) */
 	read(pos->fd, m, 16);
 	m[16] = '\0';
-	gaim_input_remove(pos->inpa);
+	b_event_remove(pos->inpa);
 	closesocket(pos->fd);
 	aim_sendmemblock(od->sess, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH);
 	g_free(pos);
-}
-
-static void straight_to_hell(gpointer data, gint source, GaimInputCondition cond) {
+	
+	return FALSE;
+}
+
+static gboolean straight_to_hell(gpointer data, gint source, b_input_condition cond) {
 	struct pieceofcrap *pos = data;
 	char buf[BUF_LONG];
@@ -631,5 +642,5 @@
 			g_free(pos->modname);
 		g_free(pos);
-		return;
+		return FALSE;
 	}
 
@@ -640,6 +651,6 @@
 	if (pos->modname)
 		g_free(pos->modname);
-	pos->inpa = gaim_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos);
-	return;
+	pos->inpa = b_input_add(pos->fd, GAIM_INPUT_READ, damn_you, pos);
+	return FALSE;
 }
 
@@ -763,5 +774,5 @@
 }
 
-static void oscar_chatnav_connect(gpointer data, gint source, GaimInputCondition cond) {
+static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condition cond) {
 	struct gaim_connection *gc = data;
 	struct oscar_data *odata;
@@ -771,5 +782,5 @@
 	if (!g_slist_find(get_connections(), gc)) {
 		closesocket(source);
-		return;
+		return FALSE;
 	}
 
@@ -780,13 +791,15 @@
 	if (source < 0) {
 		aim_conn_kill(sess, &tstconn);
-		return;
+		return FALSE;
 	}
 
 	aim_conn_completeconnect(sess, tstconn);
-	odata->cnpa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ,
+	odata->cnpa = b_input_add(tstconn->fd, GAIM_INPUT_READ,
 					oscar_callback, tstconn);
-}
-
-static void oscar_auth_connect(gpointer data, gint source, GaimInputCondition cond)
+	
+	return FALSE;
+}
+
+static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition cond)
 {
 	struct gaim_connection *gc = data;
@@ -797,5 +810,5 @@
 	if (!g_slist_find(get_connections(), gc)) {
 		closesocket(source);
-		return;
+		return FALSE;
 	}
 
@@ -806,13 +819,15 @@
 	if (source < 0) {
 		aim_conn_kill(sess, &tstconn);
-		return;
+		return FALSE;
 	}
 
 	aim_conn_completeconnect(sess, tstconn);
-	odata->paspa = gaim_input_add(tstconn->fd, GAIM_INPUT_READ,
+	odata->paspa = b_input_add(tstconn->fd, GAIM_INPUT_READ,
 				oscar_callback, tstconn);
-}
-
-static void oscar_chat_connect(gpointer data, gint source, GaimInputCondition cond)
+	
+	return FALSE;
+}
+
+static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition cond)
 {
 	struct chat_connection *ccon = data;
@@ -827,5 +842,5 @@
 		g_free(ccon->name);
 		g_free(ccon);
-		return;
+		return FALSE;
 	}
 
@@ -839,12 +854,14 @@
 		g_free(ccon->name);
 		g_free(ccon);
-		return;
+		return FALSE;
 	}
 
 	aim_conn_completeconnect(sess, ccon->conn);
-	ccon->inpa = gaim_input_add(tstconn->fd,
+	ccon->inpa = b_input_add(tstconn->fd,
 			GAIM_INPUT_READ,
 			oscar_callback, tstconn);
 	odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon);
+	
+	return FALSE;
 }
 
@@ -2565,5 +2582,5 @@
 	od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
 	if (cc->inpa > 0)
-		gaim_input_remove(cc->inpa);
+		b_event_remove(cc->inpa);
 	aim_conn_kill(od->sess, &cc->conn);
 	g_free(cc->name);
Index: protocols/proxy.c
===================================================================
--- protocols/proxy.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/proxy.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -21,8 +21,4 @@
  */
 
-/* this is a little piece of code to handle proxy connection */
-/* it is intended to : 1st handle http proxy, using the CONNECT command
- , 2nd provide an easy way to add socks support */
-
 #define BITLBEE_CORE
 #include <stdio.h>
@@ -46,8 +42,4 @@
 #include "proxy.h"
 
-#define GAIM_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
-#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
-#define GAIM_ERR_COND   (G_IO_HUP | G_IO_ERR | G_IO_NVAL)
-
 char proxyhost[128] = "";
 int proxyport = 0;
@@ -57,5 +49,5 @@
 
 struct PHB {
-	GaimInputFunction func, proxy_func;
+	b_event_handler func, proxy_func;
 	gpointer data, proxy_data;
 	char *host;
@@ -64,10 +56,4 @@
 	gint inpa;
 };
-
-typedef struct _GaimIOClosure {
-	GaimInputFunction function;
-	guint result;
-	gpointer data;
-} GaimIOClosure;
 
 
@@ -92,25 +78,5 @@
 }
 
-static void gaim_io_destroy(gpointer data)
-{
-	g_free(data);
-}
-
-static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
-{
-	GaimIOClosure *closure = data;
-	GaimInputCondition gaim_cond = 0;
-
-	if (condition & GAIM_READ_COND)
-		gaim_cond |= GAIM_INPUT_READ;
-	if (condition & GAIM_WRITE_COND)
-		gaim_cond |= GAIM_INPUT_WRITE;
-
-	closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
-
-	return TRUE;
-}
-
-static void gaim_io_connected(gpointer data, gint source, GaimInputCondition cond)
+static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
 {
 	struct PHB *phb = data;
@@ -122,5 +88,5 @@
 	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
 		closesocket(source);
-		gaim_input_remove(phb->inpa);
+		b_event_remove(phb->inpa);
 		if( phb->proxy_func )
 			phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ);
@@ -129,9 +95,9 @@
 			g_free(phb);
 		}
-		return;
+		return FALSE;
 	}
 #endif
 	sock_make_blocking(source);
-	gaim_input_remove(phb->inpa);
+	b_event_remove(phb->inpa);
 	if( phb->proxy_func )
 		phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ);
@@ -140,4 +106,6 @@
 		g_free(phb);
 	}
+	
+	return FALSE;
 }
 
@@ -158,8 +126,10 @@
 
 	sock_make_nonblocking(fd);
-
+	
+	event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
+	
 	if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) {
 		if (sockerr_again()) {
-			phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
+			phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
 			phb->fd = fd;
 		} else {
@@ -179,5 +149,5 @@
 #define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established"
 
-static void http_canread(gpointer data, gint source, GaimInputCondition cond)
+static gboolean http_canread(gpointer data, gint source, b_input_condition cond)
 {
 	int nlc = 0;
@@ -186,5 +156,5 @@
 	char inputline[8192];
 
-	gaim_input_remove(phb->inpa);
+	b_event_remove(phb->inpa);
 
 	while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) {
@@ -201,5 +171,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -208,8 +178,9 @@
 	g_free(phb->host);
 	g_free(phb);
-	return;
-}
-
-static void http_canwrite(gpointer data, gint source, GaimInputCondition cond)
+	
+	return FALSE;
+}
+
+static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond)
 {
 	char cmd[384];
@@ -218,5 +189,5 @@
 	int error = ETIMEDOUT;
 	if (phb->inpa > 0)
-		gaim_input_remove(phb->inpa);
+		b_event_remove(phb->inpa);
 	len = sizeof(error);
 	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
@@ -225,5 +196,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 	sock_make_blocking(source);
@@ -236,5 +207,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -251,5 +222,5 @@
 			g_free(phb->host);
 			g_free(phb);
-			return;
+			return FALSE;
 		}
 	}
@@ -261,8 +232,10 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
-	}
-
-	phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_canread, phb);
+		return FALSE;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb);
+	
+	return FALSE;
 }
 
@@ -280,10 +253,10 @@
 /* Connecting to SOCKS4 proxies */
 
-static void s4_canread(gpointer data, gint source, GaimInputCondition cond)
+static gboolean s4_canread(gpointer data, gint source, b_input_condition cond)
 {
 	unsigned char packet[12];
 	struct PHB *phb = data;
 
-	gaim_input_remove(phb->inpa);
+	b_event_remove(phb->inpa);
 
 	memset(packet, 0, sizeof(packet));
@@ -292,5 +265,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -299,7 +272,9 @@
 	g_free(phb->host);
 	g_free(phb);
-}
-
-static void s4_canwrite(gpointer data, gint source, GaimInputCondition cond)
+	
+	return FALSE;
+}
+
+static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond)
 {
 	unsigned char packet[12];
@@ -309,5 +284,5 @@
 	int error = ETIMEDOUT;
 	if (phb->inpa > 0)
-		gaim_input_remove(phb->inpa);
+		b_event_remove(phb->inpa);
 	len = sizeof(error);
 	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
@@ -316,5 +291,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 	sock_make_blocking(source);
@@ -326,5 +301,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -343,8 +318,10 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
-	}
-
-	phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
+		return FALSE;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
+	
+	return FALSE;
 }
 
@@ -362,10 +339,10 @@
 /* Connecting to SOCKS5 proxies */
 
-static void s5_canread_again(gpointer data, gint source, GaimInputCondition cond)
+static gboolean s5_canread_again(gpointer data, gint source, b_input_condition cond)
 {
 	unsigned char buf[512];
 	struct PHB *phb = data;
 
-	gaim_input_remove(phb->inpa);
+	b_event_remove(phb->inpa);
 
 	if (read(source, buf, 10) < 10) {
@@ -374,5 +351,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 	if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
@@ -381,5 +358,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -387,5 +364,6 @@
 	g_free(phb->host);
 	g_free(phb);
-	return;
+	
+	return FALSE;
 }
 
@@ -395,5 +373,5 @@
 	struct PHB *phb = data;
 	int hlen = strlen(phb->host);
-
+	
 	buf[0] = 0x05;
 	buf[1] = 0x01;		/* CONNECT */
@@ -413,13 +391,13 @@
 	}
 
-	phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
-}
-
-static void s5_readauth(gpointer data, gint source, GaimInputCondition cond)
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
+}
+
+static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond)
 {
 	unsigned char buf[512];
 	struct PHB *phb = data;
 
-	gaim_input_remove(phb->inpa);
+	b_event_remove(phb->inpa);
 
 	if (read(source, buf, 2) < 2) {
@@ -428,5 +406,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -436,16 +414,18 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
 	s5_sendconnect(phb, source);
-}
-
-static void s5_canread(gpointer data, gint source, GaimInputCondition cond)
+	
+	return FALSE;
+}
+
+static gboolean s5_canread(gpointer data, gint source, b_input_condition cond)
 {
 	unsigned char buf[512];
 	struct PHB *phb = data;
 
-	gaim_input_remove(phb->inpa);
+	b_event_remove(phb->inpa);
 
 	if (read(source, buf, 2) < 2) {
@@ -454,5 +434,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -462,5 +442,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 
@@ -477,14 +457,16 @@
 			g_free(phb->host);
 			g_free(phb);
-			return;
+			return FALSE;
 		}
 
-		phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);
+		phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);
 	} else {
 		s5_sendconnect(phb, source);
 	}
-}
-
-static void s5_canwrite(gpointer data, gint source, GaimInputCondition cond)
+	
+	return FALSE;
+}
+
+static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond)
 {
 	unsigned char buf[512];
@@ -494,5 +476,5 @@
 	int error = ETIMEDOUT;
 	if (phb->inpa > 0)
-		gaim_input_remove(phb->inpa);
+		b_event_remove(phb->inpa);
 	len = sizeof(error);
 	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
@@ -501,5 +483,5 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
+		return FALSE;
 	}
 	sock_make_blocking(source);
@@ -523,8 +505,10 @@
 		g_free(phb->host);
 		g_free(phb);
-		return;
-	}
-
-	phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
+		return FALSE;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
+	
+	return FALSE;
 }
 
@@ -542,33 +526,5 @@
 /* Export functions */
 
-gint gaim_input_add(gint source, GaimInputCondition condition, GaimInputFunction function, gpointer data)
-{
-	GaimIOClosure *closure = g_new0(GaimIOClosure, 1);
-	GIOChannel *channel;
-	GIOCondition cond = 0;
-	
-	closure->function = function;
-	closure->data = data;
-	
-	if (condition & GAIM_INPUT_READ)
-		cond |= GAIM_READ_COND;
-	if (condition & GAIM_INPUT_WRITE)
-		cond |= GAIM_WRITE_COND;
-	
-	channel = g_io_channel_unix_new(source);
-	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
-					      gaim_io_invoke, closure, gaim_io_destroy);
-	
-	g_io_channel_unref(channel);
-	return closure->result;
-}
-
-void gaim_input_remove(gint tag)
-{
-	if (tag > 0)
-		g_source_remove(tag);
-}
-
-int proxy_connect(const char *host, int port, GaimInputFunction func, gpointer data)
+int proxy_connect(const char *host, int port, b_event_handler func, gpointer data)
 {
 	struct PHB *phb;
Index: protocols/proxy.h
===================================================================
--- protocols/proxy.h	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/proxy.h	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -1,4 +1,4 @@
 /*
- * gaim
+ * nogaim
  *
  * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
@@ -36,4 +36,6 @@
 #include <gmodule.h>
 
+#include "events.h"
+
 #define PROXY_NONE 0
 #define PROXY_HTTP 1
@@ -47,14 +49,5 @@
 extern char proxypass[128];
 
-typedef enum {
-	GAIM_INPUT_READ = 1 << 0,
-	GAIM_INPUT_WRITE = 1 << 1
-} GaimInputCondition;
-typedef void (*GaimInputFunction)(gpointer, gint, GaimInputCondition);
-
-G_MODULE_EXPORT gint gaim_input_add(int, GaimInputCondition, GaimInputFunction, gpointer);
-G_MODULE_EXPORT void gaim_input_remove(gint);
-
-G_MODULE_EXPORT int proxy_connect(const char *host, int port, GaimInputFunction func, gpointer data);
+G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data);
 
 #endif /* _PROXY_H_ */
Index: protocols/ssl_bogus.c
===================================================================
--- protocols/ssl_bogus.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/ssl_bogus.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -52,5 +52,5 @@
 }
 
-GaimInputCondition ssl_getdirection( void *conn )
+b_input_condition ssl_getdirection( void *conn )
 {
 	return GAIM_INPUT_READ;
Index: protocols/ssl_client.h
===================================================================
--- protocols/ssl_client.h	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/ssl_client.h	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -33,5 +33,5 @@
 extern int ssl_errno;
 
-typedef void (*ssl_input_function)(gpointer, void*, GaimInputCondition);
+typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);
 
 G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );
@@ -40,3 +40,3 @@
 G_MODULE_EXPORT void ssl_disconnect( void *conn_ );
 G_MODULE_EXPORT int ssl_getfd( void *conn );
-G_MODULE_EXPORT GaimInputCondition ssl_getdirection( void *conn );
+G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
Index: protocols/ssl_gnutls.c
===================================================================
--- protocols/ssl_gnutls.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/ssl_gnutls.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -48,5 +48,5 @@
 };
 
-static void ssl_connected( gpointer data, gint source, GaimInputCondition cond );
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
 
 
@@ -81,7 +81,7 @@
 }
 
-static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond );
-
-static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
 {
 	struct scd *conn = data;
@@ -96,5 +96,5 @@
 		g_free( conn );
 		
-		return;
+		return FALSE;
 	}
 	
@@ -102,24 +102,18 @@
 	gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd );
 	
-	ssl_handshake( data, source, cond );
-}
-
-static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond )
+	return ssl_handshake( data, source, cond );
+}
+
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
 {
 	struct scd *conn = data;
 	int st;
 	
-	if( conn->inpa != -1 )
-	{
-		gaim_input_remove( conn->inpa );
-		conn->inpa = -1;
-	}
-	
 	if( ( st = gnutls_handshake( conn->session ) ) < 0 )
 	{
 		if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
 		{
-			conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ),
-			                             ssl_handshake, data );
+			conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ),
+			                          ssl_handshake, data );
 		}
 		else
@@ -142,4 +136,6 @@
 		conn->func( conn->data, conn, cond );
 	}
+	
+	return FALSE;
 }
 
@@ -187,5 +183,5 @@
 	
 	if( conn->inpa != -1 )
-		gaim_input_remove( conn->inpa );
+		b_event_remove( conn->inpa );
 	
 	if( conn->established )
@@ -204,5 +200,5 @@
 }
 
-GaimInputCondition ssl_getdirection( void *conn )
+b_input_condition ssl_getdirection( void *conn )
 {
 	return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ?
Index: protocols/ssl_nss.c
===================================================================
--- protocols/ssl_nss.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/ssl_nss.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -52,5 +52,5 @@
 };
 
-static void ssl_connected( gpointer data, gint source, GaimInputCondition cond );
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
 
 
@@ -116,5 +116,5 @@
 }
 
-static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
 {
 	struct scd *conn = data;
@@ -140,5 +140,5 @@
 	conn->established = TRUE;
 	conn->func( conn->data, conn, cond );
-	return;
+	return FALSE;
 	
 	ssl_connected_failure:
@@ -149,4 +149,6 @@
 	if( source >= 0 ) closesocket( source );
 	g_free( conn );
+	
+	return FALSE;
 }
 
@@ -182,5 +184,5 @@
 }
 
-GaimInputCondition ssl_getdirection( void *conn )
+b_input_condition ssl_getdirection( void *conn )
 {
 	/* Just in case someone calls us, let's return the most likely case: */
Index: protocols/ssl_openssl.c
===================================================================
--- protocols/ssl_openssl.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/ssl_openssl.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -52,6 +52,5 @@
 };
 
-static void ssl_connected( gpointer data, gint source, GaimInputCondition cond );
-
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
 
 
@@ -95,7 +94,7 @@
 }
 
-static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond );
-
-static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
 {
 	struct scd *conn = data;
@@ -104,5 +103,5 @@
 		return ssl_handshake( data, -1, cond );
 	
-	/* Make it non-blocking at least during the handshake... */
+	/* We can do at least the handshake with non-blocking I/O */
 	sock_make_nonblocking( conn->fd );
 	SSL_set_fd( conn->ssl, conn->fd );
@@ -111,14 +110,8 @@
 }	
 
-static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond )
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
 {
 	struct scd *conn = data;
 	int st;
-	
-	if( conn->inpa != -1 )
-	{
-		gaim_input_remove( conn->inpa );
-		conn->inpa = -1;
-	}
 	
 	if( ( st = SSL_connect( conn->ssl ) ) < 0 )
@@ -128,6 +121,6 @@
 			goto ssl_connected_failure;
 		
-		conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
-		return;
+		conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
+		return FALSE;
 	}
 	
@@ -135,5 +128,5 @@
 	sock_make_blocking( conn->fd );		/* For now... */
 	conn->func( conn->data, conn, cond );
-	return;
+	return FALSE;
 	
 ssl_connected_failure:
@@ -151,4 +144,6 @@
 	if( source >= 0 ) closesocket( source );
 	g_free( conn );
+	
+	return FALSE;
 }
 
@@ -204,5 +199,5 @@
 	
 	if( conn->inpa != -1 )
-		gaim_input_remove( conn->inpa );
+		b_event_remove( conn->inpa );
 	
 	if( conn->established )
@@ -221,5 +216,5 @@
 }
 
-GaimInputCondition ssl_getdirection( void *conn )
+b_input_condition ssl_getdirection( void *conn )
 {
 	return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );
Index: protocols/yahoo/yahoo.c
===================================================================
--- protocols/yahoo/yahoo.c	(revision fb62f81f947c74e274b05e32d2e88e3a4d7e2613)
+++ protocols/yahoo/yahoo.c	(revision 85e9644fe03cef7b83f3b3200943364e4eecaf14)
@@ -443,5 +443,5 @@
 };
 
-void byahoo_connect_callback( gpointer data, gint source, GaimInputCondition cond )
+void byahoo_connect_callback( gpointer data, gint source, b_input_condition cond )
 {
 	struct byahoo_connect_callback_data *d = data;
@@ -465,16 +465,15 @@
 };
 
-void byahoo_read_ready_callback( gpointer data, gint source, GaimInputCondition cond )
+gboolean byahoo_read_ready_callback( gpointer data, gint source, b_input_condition cond )
 {
 	struct byahoo_read_ready_data *d = data;
 	
 	if( !byahoo_get_gc_by_id( d->id ) )
-	{
 		/* WTF doesn't libyahoo clean this up? */
-		ext_yahoo_remove_handler( d->id, d->tag );
-		return;
-	}
+		return FALSE;
 	
 	yahoo_read_ready( d->id, d->fd, d->data );
+	
+	return TRUE;
 }
 
@@ -487,16 +486,15 @@
 };
 
-void byahoo_write_ready_callback( gpointer data, gint source, GaimInputCondition cond )
+gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condition cond )
 {
 	struct byahoo_write_ready_data *d = data;
 	
 	if( !byahoo_get_gc_by_id( d->id ) )
-	{
 		/* WTF doesn't libyahoo clean this up? */
-		ext_yahoo_remove_handler( d->id, d->tag );
-		return;
-	}
+		return FALSE;
 	
 	yahoo_write_ready( d->id, d->fd, d->data );
+	
+	return FALSE;
 }
 
@@ -687,5 +685,5 @@
 		
 		inp->d = d;
-		d->tag = inp->h = gaim_input_add( fd, GAIM_INPUT_READ, (GaimInputFunction) byahoo_read_ready_callback, (gpointer) d );
+		d->tag = inp->h = b_input_add( fd, GAIM_INPUT_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d );
 	}
 	else if( cond == YAHOO_INPUT_WRITE )
@@ -698,5 +696,5 @@
 		
 		inp->d = d;
-		d->tag = inp->h = gaim_input_add( fd, GAIM_INPUT_WRITE, (GaimInputFunction) byahoo_write_ready_callback, (gpointer) d );
+		d->tag = inp->h = b_input_add( fd, GAIM_INPUT_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d );
 	}
 	else
@@ -729,5 +727,5 @@
 	}
 	
-	gaim_input_remove( tag );
+	b_event_remove( tag );
 }
 
@@ -738,5 +736,5 @@
 	
 	d = g_new0( struct byahoo_connect_callback_data, 1 );
-	if( ( fd = proxy_connect( host, port, (GaimInputFunction) byahoo_connect_callback, (gpointer) d ) ) < 0 )
+	if( ( fd = proxy_connect( host, port, (b_event_handler) byahoo_connect_callback, (gpointer) d ) ) < 0 )
 	{
 		g_free( d );
