Index: irc.h
===================================================================
--- irc.h	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ irc.h	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -147,4 +147,5 @@
 	
 	const struct irc_channel_funcs *f;
+	void *data;
 } irc_channel_t;
 
Index: irc_im.c
===================================================================
--- irc_im.c	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ irc_im.c	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -203,4 +203,66 @@
 }
 
+
+/* Groupchats */
+gboolean bee_irc_chat_new( bee_t *bee, struct groupchat *c )
+{
+	irc_t *irc = bee->ui_data;
+	irc_channel_t *ic;
+	char *topic;
+	int i;
+	
+	for( i = 0; i <= 999; i ++ )
+	{
+		char name[16];
+		sprintf( name, "&chat_%03d", i );
+		if( ( ic = irc_channel_new( irc, name ) ) )
+			break;
+	}
+	
+	if( ic == NULL )
+		return FALSE;
+	
+	c->ui_data = ic;
+	ic->data = c;
+	
+	topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title );
+	irc_channel_set_topic( ic, topic, irc->root );
+	g_free( topic );
+	
+	return TRUE;
+}
+
+gboolean bee_irc_chat_free( bee_t *bee, struct groupchat *c )
+{
+	irc_channel_t *ic = c->ui_data;
+	
+	if( ic->flags & IRC_CHANNEL_JOINED )
+		irc_channel_printf( ic, "Cleaning up channel, bye!" );
+	
+	irc_channel_free( ic );
+	
+	return TRUE;
+}
+
+gboolean bee_irc_chat_log( bee_t *bee, struct groupchat *c, const char *format, ... )
+{
+}
+
+gboolean bee_irc_chat_msg( bee_t *bee, struct groupchat *c, const char *who, const char *msg, time_t sent_at )
+{
+}
+
+gboolean bee_irc_chat_add_user( bee_t *bee, struct groupchat *c, bee_user_t *bu )
+{
+	irc_t *irc = bee->ui_data;
+	
+	irc_channel_add_user( c->ui_data, bu == bee->user ? irc->user : bu->ui_data );
+}
+
+gboolean bee_irc_chat_remove_user( bee_t *bee, struct groupchat *c, bee_user_t *bu )
+{
+}
+
+
 /* File transfers */
 static file_transfer_t *bee_irc_ft_in_start( bee_t *bee, bee_user_t *bu, const char *file_name, size_t file_size )
@@ -237,4 +299,11 @@
 	bee_irc_user_typing,
 	
+	bee_irc_chat_new,
+	bee_irc_chat_free,
+	NULL,
+	NULL,
+	bee_irc_chat_add_user,
+	NULL,
+	
 	bee_irc_ft_in_start,
 	bee_irc_ft_out_start,
Index: protocols/Makefile
===================================================================
--- protocols/Makefile	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/Makefile	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = account.o bee.o bee_ft.o bee_user.o nogaim.o
+objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o
 
 
Index: protocols/bee.c
===================================================================
--- protocols/bee.c	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/bee.c	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -47,4 +47,6 @@
 	s = set_add( &b->set, "strip_html", "true", NULL, b );
 	
+	b->user = g_malloc( 1 );
+	
 	return b;
 }
@@ -70,4 +72,5 @@
 		set_del( &b->set, b->set->key );
 	
+	g_free( b->user );
 	g_free( b );
 }
Index: protocols/bee.h
===================================================================
--- protocols/bee.h	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/bee.h	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -28,4 +28,5 @@
 
 struct bee_ui_funcs;
+struct groupchat;
 
 typedef struct bee
@@ -35,4 +36,9 @@
 	GSList *users;
 	struct account *accounts; /* TODO(wilmer): Use GSList here too? */
+	
+	/* Symbolic, to refer to the local user (who has no real bee_user
+	   object). Not to be used by anything except so far imcb_chat_add/
+	   remove_buddy(). This seems slightly cleaner than abusing NULL. */
+	struct bee_user *user;
 	
 	const struct bee_ui_funcs *ui;
@@ -73,4 +79,11 @@
 	gboolean (*user_typing)( bee_t *bee, bee_user_t *bu, guint32 flags );
 	
+	gboolean (*chat_new)( bee_t *bee, struct groupchat *c );
+	gboolean (*chat_free)( bee_t *bee, struct groupchat *c );
+	gboolean (*chat_log)( bee_t *bee, struct groupchat *c, const char *format, ... );
+	gboolean (*chat_msg)( bee_t *bee, struct groupchat *c, const char *who, const char *msg, time_t sent_at );
+	gboolean (*chat_add_user)( bee_t *bee, struct groupchat *c, bee_user_t *bu );
+	gboolean (*chat_remove_user)( bee_t *bee, struct groupchat *c, bee_user_t *bu );
+	
 	struct file_transfer* (*ft_in_start)( bee_t *bee, bee_user_t *bu, const char *file_name, size_t file_size );
 	gboolean (*ft_out_start)( struct im_connection *ic, struct file_transfer *ft );
@@ -101,3 +114,16 @@
 G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, guint32 flags, time_t sent_at );
 
+/* bee_chat.c */
+#if 0
+struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle );
+void imcb_chat_name_hint( struct groupchat *c, const char *name );
+void imcb_chat_free( struct groupchat *c );
+void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at );
+void imcb_chat_log( struct groupchat *c, char *format, ... );
+void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at );
+void imcb_chat_add_buddy( struct groupchat *b, const char *handle );
+void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason );
+static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
+#endif
+
 #endif /* __BEE_H__ */
Index: protocols/jabber/conference.c
===================================================================
--- protocols/jabber/conference.c	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/jabber/conference.c	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -92,9 +92,11 @@
 {
 	char *normalized = jabber_normalize( name );
+	GSList *l;
 	struct groupchat *ret;
 	struct jabber_chat *jc;
 	
-	for( ret = ic->groupchats; ret; ret = ret->next )
-	{
+	for( l = ic->groupchats; l; l = l->next )
+	{
+		ret = l->data;
 		jc = ret->data;
 		if( strcmp( normalized, jc->name ) == 0 )
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/jabber/jabber.c	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -282,5 +282,5 @@
 	
 	while( ic->groupchats )
-		jabber_chat_free( ic->groupchats );
+		jabber_chat_free( ic->groupchats->data );
 	
 	if( jd->r_inpa >= 0 )
Index: protocols/jabber/presence.c
===================================================================
--- protocols/jabber/presence.c	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/jabber/presence.c	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -206,4 +206,5 @@
 	struct xt_node *node, *cap;
 	struct groupchat *c;
+	GSList *l;
 	int st;
 	
@@ -229,6 +230,7 @@
 	/* Have to send this update to all groupchats too, the server won't
 	   do this automatically. */
-	for( c = ic->groupchats; c && st; c = c->next )
-	{
+	for( l = ic->groupchats; l && st; l = l->next )
+	{
+		struct groupchat *c = l->data;
 		struct jabber_chat *jc = c->data;
 		
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/nogaim.c	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -536,274 +536,4 @@
 	return bee_user_by_handle( ic->bee, ic, handle );
 }
-
-struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle )
-{
-#if 0
-	struct groupchat *c;
-	
-	/* This one just creates the conversation structure, user won't see anything yet */
-	
-	if( ic->groupchats )
-	{
-		for( c = ic->groupchats; c->next; c = c->next );
-		c = c->next = g_new0( struct groupchat, 1 );
-	}
-	else
-		ic->groupchats = c = g_new0( struct groupchat, 1 );
-	
-	c->ic = ic;
-	c->title = g_strdup( handle );
-	c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ );
-	c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title );
-	
-	if( set_getbool( &ic->bee->set, "debug" ) )
-		imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle );
-	
-	return c;
-#endif
-	return NULL;
-}
-
-void imcb_chat_name_hint( struct groupchat *c, const char *name )
-{
-#if 0
-	if( !c->joined )
-	{
-		struct im_connection *ic = c->ic;
-		char stripped[MAX_NICK_LENGTH+1], *full_name;
-		
-		strncpy( stripped, name, MAX_NICK_LENGTH );
-		stripped[MAX_NICK_LENGTH] = '\0';
-		nick_strip( stripped );
-		if( set_getbool( &ic->irc->set, "lcnicks" ) )
-			nick_lc( stripped );
-		
-		full_name = g_strdup_printf( "&%s", stripped );
-		
-		if( stripped[0] &&
-		    nick_cmp( stripped, ic->irc->channel + 1 ) != 0 &&
-		    irc_chat_by_channel( ic->irc, full_name ) == NULL )
-		{
-			g_free( c->channel );
-			c->channel = full_name;
-		}
-		else
-		{
-			g_free( full_name );
-		}
-	}
-#endif
-}
-
-void imcb_chat_free( struct groupchat *c )
-{
-#if 0
-	struct im_connection *ic = c->ic;
-	struct groupchat *l;
-	GList *ir;
-	
-	if( set_getbool( &ic->bee->set, "debug" ) )
-		imcb_log( ic, "You were removed from conversation %p", c );
-	
-	if( c )
-	{
-		if( c->joined )
-		{
-			user_t *u, *r;
-			
-			r = user_find( ic->irc, ic->irc->mynick );
-			irc_privmsg( ic->irc, r, "PRIVMSG", c->channel, "", "Cleaning up channel, bye!" );
-			
-			u = user_find( ic->irc, ic->irc->nick );
-			irc_kick( ic->irc, u, c->channel, r );
-			/* irc_part( ic->irc, u, c->channel ); */
-		}
-		
-		/* Find the previous chat in the linked list. */
-		for( l = ic->groupchats; l && l->next != c; l = l->next );
-		
-		if( l )
-			l->next = c->next;
-		else
-			ic->groupchats = c->next;
-		
-		for( ir = c->in_room; ir; ir = ir->next )
-			g_free( ir->data );
-		g_list_free( c->in_room );
-		g_free( c->channel );
-		g_free( c->title );
-		g_free( c->topic );
-		g_free( c );
-	}
-#endif
-}
-
-void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
-{
-#if 0
-	struct im_connection *ic = c->ic;
-	char *wrapped;
-	user_t *u;
-	
-	/* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
-	if( g_strcasecmp( who, ic->acc->user ) == 0 )
-		return;
-	
-	u = user_findhandle( ic, who );
-	
-	if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
-	    ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
-		strip_html( msg );
-	
-	wrapped = word_wrap( msg, 425 );
-	if( c && u )
-	{
-		char *ts = NULL;
-		if( set_getbool( &ic->irc->set, "display_timestamps" ) )
-			ts = format_timestamp( ic->irc, sent_at );
-		irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped );
-		g_free( ts );
-	}
-	else
-	{
-		imcb_log( ic, "Message from/to conversation %s@%p (unknown conv/user): %s", who, c, wrapped );
-	}
-	g_free( wrapped );
-#endif
-}
-
-void imcb_chat_log( struct groupchat *c, char *format, ... )
-{
-#if 0
-	irc_t *irc = c->ic->irc;
-	va_list params;
-	char *text;
-	user_t *u;
-	
-	va_start( params, format );
-	text = g_strdup_vprintf( format, params );
-	va_end( params );
-	
-	u = user_find( irc, irc->mynick );
-	
-	irc_privmsg( irc, u, "PRIVMSG", c->channel, "System message: ", text );
-	
-	g_free( text );
-#endif
-}
-
-void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at )
-{
-#if 0
-	struct im_connection *ic = c->ic;
-	user_t *u = NULL;
-	
-	if( who == NULL)
-		u = user_find( ic->irc, ic->irc->mynick );
-	else if( g_strcasecmp( who, ic->acc->user ) == 0 )
-		u = user_find( ic->irc, ic->irc->nick );
-	else
-		u = user_findhandle( ic, who );
-	
-	if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
-	    ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
-		strip_html( topic );
-	
-	g_free( c->topic );
-	c->topic = g_strdup( topic );
-	
-	if( c->joined && u )
-		irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic );
-#endif
-}
-
-void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
-{
-#if 0
-	user_t *u = user_findhandle( b->ic, handle );
-	int me = 0;
-	
-	if( set_getbool( &b->ic->bee->set, "debug" ) )
-		imcb_log( b->ic, "User %s added to conversation %p", handle, b );
-	
-	/* It might be yourself! */
-	if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 )
-	{
-		u = user_find( b->ic->irc, b->ic->irc->nick );
-		if( !b->joined )
-			irc_join( b->ic->irc, u, b->channel );
-		b->joined = me = 1;
-	}
-	
-	/* Most protocols allow people to join, even when they're not in
-	   your contact list. Try to handle that here */
-	if( !u )
-	{
-		imcb_add_buddy( b->ic, handle, NULL );
-		u = user_findhandle( b->ic, handle );
-	}
-	
-	/* Add the handle to the room userlist, if it's not 'me' */
-	if( !me )
-	{
-		if( b->joined )
-			irc_join( b->ic->irc, u, b->channel );
-		b->in_room = g_list_append( b->in_room, g_strdup( handle ) );
-	}
-#endif
-}
-
-/* This function is one BIG hack... :-( EREWRITE */
-void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
-{
-#if 0
-	user_t *u;
-	int me = 0;
-	
-	if( set_getbool( &b->ic->bee->set, "debug" ) )
-		imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" );
-	
-	/* It might be yourself! */
-	if( g_strcasecmp( handle, b->ic->acc->user ) == 0 )
-	{
-		if( b->joined == 0 )
-			return;
-		
-		u = user_find( b->ic->irc, b->ic->irc->nick );
-		b->joined = 0;
-		me = 1;
-	}
-	else
-	{
-		u = user_findhandle( b->ic, handle );
-	}
-	
-	if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) )
-		irc_part( b->ic->irc, u, b->channel );
-#endif
-}
-
-#if 0
-static int remove_chat_buddy_silent( struct groupchat *b, const char *handle )
-{
-	GList *i;
-	
-	/* Find the handle in the room userlist and shoot it */
-	i = b->in_room;
-	while( i )
-	{
-		if( g_strcasecmp( handle, i->data ) == 0 )
-		{
-			g_free( i->data );
-			b->in_room = g_list_remove( b->in_room, i->data );
-			return( 1 );
-		}
-		
-		i = i->next;
-	}
-	
-	return 0;
-}
-#endif
 
 
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision 94383231eddf56112cf74f2ae65d691821d70803)
+++ protocols/nogaim.h	(revision aea8b68bd0e057441d671c008200e71dd046a211)
@@ -89,5 +89,5 @@
 	bee_t *bee;
 	
-	struct groupchat *groupchats;
+	GSList *groupchats;
 };
 
@@ -100,8 +100,7 @@
 	 * already, for example to avoid adding somebody two times. */
 	GList *in_room;
-	GList *ignored;
-	
-	struct groupchat *next;
-	char *channel;
+	//GList *ignored;
+	
+	//struct groupchat *next;
 	/* The title variable contains the ID you gave when you created the
 	 * chat using imcb_chat_new(). */
@@ -114,4 +113,5 @@
 	 * structure for your protocol's needs. */
 	void *data;
+	void *ui_data;
 };
 
