changeset 6695:0c5637b5462e

[gaim-migrate @ 7221] This is contact support. Really. It has a few bugs left in it, like sorting not working, and stuff like that, but it's pretty solid for the most part. I'm not in the mood to do a whole lot of typing, so just use and enjoy. committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Tue, 02 Sep 2003 03:41:10 +0000
parents 2d2f04c5c7d2
children eb2fc3a8aa11
files plugins/statenotify.c plugins/ticker/ticker.c src/account.c src/blist.c src/blist.h src/connection.c src/conversation.c src/dialogs.c src/gaim.h src/gtkblist.h src/gtkconv.c src/gtkpounce.c src/log.c src/log.h src/prefs.c src/protocols/gg/gg.c src/protocols/irc/irc.c src/protocols/irc/msgs.c src/protocols/jabber/jabber.c src/protocols/msn/buddyicon.c src/protocols/msn/msn.c src/protocols/msn/notification.c src/protocols/msn/switchboard.c src/protocols/napster/napster.c src/protocols/oscar/oscar.c src/protocols/toc/toc.c src/protocols/yahoo/yahoo.c src/protocols/zephyr/zephyr.c src/prpl.c src/prpl.h src/server.c src/server.h src/ui.h
diffstat 33 files changed, 1063 insertions(+), 691 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/statenotify.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/plugins/statenotify.c	Tue Sep 02 03:41:10 2003 +0000
@@ -6,7 +6,7 @@
 #include "signals.h"
 
 static void
-write_status(struct buddy *buddy, const char *message)
+write_status(GaimBuddy *buddy, const char *message)
 {
 	GaimConversation *conv;
 	const char *who;
@@ -25,25 +25,25 @@
 }
 
 static void
-buddy_away_cb(struct buddy *buddy, void *data)
+buddy_away_cb(GaimBuddy *buddy, void *data)
 {
 	write_status(buddy, _("%s has gone away."));
 }
 
 static void
-buddy_unaway_cb(struct buddy *buddy, void *data)
+buddy_unaway_cb(GaimBuddy *buddy, void *data)
 {
 	write_status(buddy, _("%s is no longer away."));
 }
 
 static void
-buddy_idle_cb(struct buddy *buddy, void *data)
+buddy_idle_cb(GaimBuddy *buddy, void *data)
 {
 	write_status(buddy, _("%s has become idle."));
 }
 
 static void
-buddy_unidle_cb(struct buddy *buddy, void *data)
+buddy_unidle_cb(GaimBuddy *buddy, void *data)
 {
 	write_status(buddy, _("%s is no longer idle."));
 }
--- a/plugins/ticker/ticker.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/plugins/ticker/ticker.c	Tue Sep 02 03:41:10 2003 +0000
@@ -44,7 +44,7 @@
 static GtkWidget *ticker;
 
 typedef struct {
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 	GtkWidget *ebox;
 	GtkWidget *label;
 	GtkWidget *icon;
@@ -86,13 +86,13 @@
 }
 
 static gboolean buddy_click_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
-	struct buddy *b = user_data;
+	GaimBuddy *b = user_data;
 
 	gaim_conversation_new(GAIM_CONV_IM, b->account, b->name);
 	return TRUE;
 }
 
-static TickerData *buddy_ticker_find_buddy(struct buddy *b) {
+static TickerData *buddy_ticker_find_buddy(GaimBuddy *b) {
 	GList *tb;
 	for(tb = tickerbuds; tb; tb = tb->next) {
 		TickerData *td = tb->data;
@@ -102,7 +102,7 @@
 	return NULL;
 }
 
-static void buddy_ticker_set_pixmap(struct buddy *b) {
+static void buddy_ticker_set_pixmap(GaimBuddy *b) {
 	TickerData *td = buddy_ticker_find_buddy(b);
 	GdkPixbuf *pixbuf;
 
@@ -128,7 +128,7 @@
 	return FALSE;
 }
 
-static void buddy_ticker_add_buddy(struct buddy *b) {
+static void buddy_ticker_add_buddy(GaimBuddy *b) {
 	GtkWidget *hbox;
 	TickerData *td;
 
@@ -167,7 +167,7 @@
 	td->timeout = g_timeout_add(11000, buddy_ticker_set_pixmap_cb, td);
 }
 
-static void buddy_ticker_remove_buddy(struct buddy *b) {
+static void buddy_ticker_remove_buddy(GaimBuddy *b) {
 	TickerData *td = buddy_ticker_find_buddy(b);
 
 	if (!td)
@@ -186,8 +186,8 @@
 static void buddy_ticker_show()
 {
 	struct gaim_buddy_list *list = gaim_get_blist();
-	GaimBlistNode *gnode, *bnode;
-	struct buddy *b;
+	GaimBlistNode *gnode, *cnode, *bnode;
+	GaimBuddy *b;
 
 	if(!list)
 		return;
@@ -195,12 +195,16 @@
 	for(gnode = list->root; gnode; gnode = gnode->next) {
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(bnode = gnode->child; bnode; bnode = bnode->next) {
-			if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 				continue;
-			b = (struct buddy *)bnode;
-			if(GAIM_BUDDY_IS_ONLINE(b))
-				buddy_ticker_add_buddy(b);
+			for(bnode = cnode->child; bnode; bnode = bnode->next) {
+				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+					continue;
+				b = (GaimBuddy *)bnode;
+				if(GAIM_BUDDY_IS_ONLINE(b))
+					buddy_ticker_add_buddy(b);
+			}
 		}
 	}
 }
@@ -236,7 +240,7 @@
 }
 
 static void
-buddy_signon_cb(struct buddy *b)
+buddy_signon_cb(GaimBuddy *b)
 {
 	if(buddy_ticker_find_buddy(b))
 		buddy_ticker_set_pixmap(b);
@@ -245,7 +249,7 @@
 }
 
 static void
-buddy_signoff_cb(struct buddy *b)
+buddy_signoff_cb(GaimBuddy *b)
 {
 	buddy_ticker_remove_buddy(b);
 	if(!tickerbuds)
@@ -253,7 +257,7 @@
 }
 
 static void
-away_cb(struct buddy *b)
+away_cb(GaimBuddy *b)
 {
 	if(buddy_ticker_find_buddy(b))
 		buddy_ticker_set_pixmap(b);
--- a/src/account.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/account.c	Tue Sep 02 03:41:10 2003 +0000
@@ -1300,7 +1300,7 @@
 void
 gaim_accounts_delete(GaimAccount *account)
 {
-	GaimBlistNode *gnode, *bnode;
+	GaimBlistNode *gnode, *cnode, *bnode;
 
 	g_return_if_fail(account != NULL);
 
@@ -1309,16 +1309,18 @@
 	for (gnode = gaim_get_blist()->root; gnode != NULL; gnode = gnode->next) {
 		if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-
-		for (bnode = gnode->child; bnode != NULL; bnode = bnode->next) {
-			if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
-				struct buddy *b = (struct buddy *)bnode;
+		for (cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+				for (bnode = cnode->child; bnode; bnode = bnode->next) {
+					if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
+						GaimBuddy *b = (GaimBuddy *)bnode;
 
-				if (b->account == account)
-					gaim_blist_remove_buddy(b);
-			}
-			else if (GAIM_BLIST_NODE_IS_CHAT(bnode)) {
-				struct chat *c = (struct chat *)bnode;
+						if (b->account == account)
+							gaim_blist_remove_buddy(b);
+					}
+				}
+			} else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+				GaimBlistChat *c = (GaimBlistChat *)cnode;
 
 				if (c->account == account)
 					gaim_blist_remove_chat(c);
--- a/src/blist.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/blist.c	Tue Sep 02 03:41:10 2003 +0000
@@ -49,6 +49,7 @@
 		n = n->next;
 	return n;
 }
+
 static GaimBlistNode *gaim_blist_get_last_child(GaimBlistNode *node)
 {
 	if (!node)
@@ -75,18 +76,24 @@
 static void blist_pref_cb(const char *name, GaimPrefType typ, gpointer value, gpointer data)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
-	GaimBlistNode *group, *buddy;
+	GaimBlistNode *gnode, *cnode, *bnode;
 
 	if (!ops)
 		return;
 
-	for(group = gaimbuddylist->root; group; group = group->next) {
-		if(!GAIM_BLIST_NODE_IS_GROUP(group))
+	for(gnode = gaimbuddylist->root; gnode; gnode = gnode->next) {
+		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(buddy = group->child; buddy; buddy = buddy->next) {
-			if(!GAIM_BLIST_NODE_IS_BUDDY(buddy))
-				continue;
-			ops->update(gaimbuddylist, buddy);
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+				for(bnode = cnode->child; bnode; bnode = bnode->next) {
+					if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+						continue;
+					ops->update(gaimbuddylist, bnode);
+				}
+			} else if(GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+				ops->update(gaimbuddylist, cnode);
+			}
 		}
 	}
 }
@@ -126,7 +133,7 @@
 	return gaimbuddylist;
 }
 
-void  gaim_blist_show () 
+void  gaim_blist_show ()
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	if (ops)
@@ -147,7 +154,7 @@
 		ops->set_visible(gaimbuddylist, show);
 }
 
-void  gaim_blist_update_buddy_status (struct buddy *buddy, int status)
+void  gaim_blist_update_buddy_status (GaimBuddy *buddy, int status)
 {
 	struct gaim_blist_ui_ops *ops;
 
@@ -168,7 +175,7 @@
 		ops->update(gaimbuddylist, (GaimBlistNode*)buddy);
 }
 
-static gboolean presence_update_timeout_cb(struct buddy *buddy) {
+static gboolean presence_update_timeout_cb(GaimBuddy *buddy) {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	GaimConversation *conv;
 
@@ -195,7 +202,7 @@
 	return FALSE;
 }
 
-void gaim_blist_update_buddy_presence(struct buddy *buddy, int presence) {
+void gaim_blist_update_buddy_presence(GaimBuddy *buddy, int presence) {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	gboolean do_timer = FALSE;
 
@@ -203,12 +210,16 @@
 		buddy->present = GAIM_BUDDY_SIGNING_ON;
 		gaim_signal_emit(gaim_blist_get_handle(), "buddy-signed-on", buddy);
 		do_timer = TRUE;
-		((struct group *)((GaimBlistNode *)buddy)->parent)->online++;
+		((GaimContact*)((GaimBlistNode*)buddy)->parent)->online++;
+		if(((GaimContact*)((GaimBlistNode*)buddy)->parent)->online == 1)
+			((GaimGroup *)((GaimBlistNode *)buddy)->parent->parent)->online++;
 	} else if(GAIM_BUDDY_IS_ONLINE(buddy) && !presence) {
 		buddy->present = GAIM_BUDDY_SIGNING_OFF;
 		gaim_signal_emit(gaim_blist_get_handle(), "buddy-signed-off", buddy);
 		do_timer = TRUE;
-		((struct group *)((GaimBlistNode *)buddy)->parent)->online--;
+		((GaimContact*)((GaimBlistNode*)buddy)->parent)->online--;
+		if(((GaimContact*)((GaimBlistNode*)buddy)->parent)->online == 0)
+			((GaimGroup *)((GaimBlistNode *)buddy)->parent->parent)->online--;
 	}
 
 	if(do_timer) {
@@ -222,26 +233,29 @@
 }
 
 
-void  gaim_blist_update_buddy_idle (struct buddy *buddy, int idle)
+void  gaim_blist_update_buddy_idle (GaimBuddy *buddy, int idle)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	buddy->idle = idle;
 	if (ops)
 		ops->update(gaimbuddylist, (GaimBlistNode*)buddy);
 }
-void  gaim_blist_update_buddy_evil (struct buddy *buddy, int warning)
+
+void  gaim_blist_update_buddy_evil (GaimBuddy *buddy, int warning)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	buddy->evil = warning;
 	if (ops)
 		ops->update(gaimbuddylist,(GaimBlistNode*)buddy);
 }
-void gaim_blist_update_buddy_icon(struct buddy *buddy) {
+
+void gaim_blist_update_buddy_icon(GaimBuddy *buddy) {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	if(ops)
 		ops->update(gaimbuddylist, (GaimBlistNode*)buddy);
 }
-void  gaim_blist_rename_buddy (struct buddy *buddy, const char *name)
+
+void  gaim_blist_rename_buddy (GaimBuddy *buddy, const char *name)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	g_free(buddy->name);
@@ -250,7 +264,7 @@
 		ops->update(gaimbuddylist, (GaimBlistNode*)buddy);
 }
 
-void gaim_blist_alias_chat(struct chat *chat, const char *alias)
+void gaim_blist_alias_chat(GaimBlistChat *chat, const char *alias)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 
@@ -265,7 +279,7 @@
 		ops->update(gaimbuddylist, (GaimBlistNode*)chat);
 }
 
-void  gaim_blist_alias_buddy (struct buddy *buddy, const char *alias)
+void  gaim_blist_alias_buddy (GaimBuddy *buddy, const char *alias)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	GaimConversation *conv;
@@ -286,7 +300,7 @@
 		gaim_conversation_autoset_title(conv);
 }
 
-void  gaim_blist_server_alias_buddy (struct buddy *buddy, const char *alias)
+void  gaim_blist_server_alias_buddy (GaimBuddy *buddy, const char *alias)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	GaimConversation *conv;
@@ -307,10 +321,10 @@
 		gaim_conversation_autoset_title(conv);
 }
 
-void gaim_blist_rename_group(struct group *group, const char *name)
+void gaim_blist_rename_group(GaimGroup *group, const char *name)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
-	struct group *dest_group;
+	GaimGroup *dest_group;
 	GaimBlistNode *prev, *child, *next;
 	GSList *accts;
 
@@ -325,11 +339,15 @@
 		while(child)
 		{
 			next = child->next;
-			if(GAIM_BLIST_NODE_IS_BUDDY(child)) {
-				gaim_blist_add_buddy((struct buddy *)child, dest_group, prev);
+			if(GAIM_BLIST_NODE_IS_CONTACT(child)) {
+				GaimBlistNode *bnode;
+				gaim_blist_add_contact((GaimContact *)child, dest_group, prev);
+				for(bnode = child->child; bnode; bnode = bnode->next)
+					gaim_blist_add_buddy((GaimBuddy*)bnode, (GaimContact*)child,
+							NULL, bnode->prev);
 				prev = child;
 			} else if(GAIM_BLIST_NODE_IS_CHAT(child)) {
-				gaim_blist_add_chat((struct chat *)child, dest_group, prev);
+				gaim_blist_add_chat((GaimBlistChat *)child, dest_group, prev);
 				prev = child;
 			} else {
 				gaim_debug(GAIM_DEBUG_ERROR, "blist",
@@ -355,15 +373,15 @@
 	}
 }
 
-struct chat *gaim_chat_new(GaimAccount *account, const char *alias, GHashTable *components)
+GaimBlistChat *gaim_blist_chat_new(GaimAccount *account, const char *alias, GHashTable *components)
 {
-	struct chat *chat;
+	GaimBlistChat *chat;
 	struct gaim_blist_ui_ops *ops;
 
 	if(!components)
 		return NULL;
 
-	chat = g_new0(struct chat, 1);
+	chat = g_new0(GaimBlistChat, 1);
 	chat->account = account;
 	if(alias && strlen(alias))
 		chat->alias = g_strdup(alias);
@@ -381,7 +399,7 @@
 	return chat;
 }
 
-char *gaim_chat_get_display_name(struct chat *chat)
+char *gaim_blist_chat_get_display_name(GaimBlistChat *chat)
 {
 	char *name;
 
@@ -408,12 +426,12 @@
 	return name;
 }
 
-struct buddy *gaim_buddy_new(GaimAccount *account, const char *screenname, const char *alias)
+GaimBuddy *gaim_buddy_new(GaimAccount *account, const char *screenname, const char *alias)
 {
-	struct buddy *b;
+	GaimBuddy *b;
 	struct gaim_blist_ui_ops *ops;
 
-	b = g_new0(struct buddy, 1);
+	b = g_new0(GaimBuddy, 1);
 	b->account = account;
 	b->name  = g_strdup(screenname);
 	b->alias = g_strdup(alias);
@@ -428,10 +446,10 @@
 	return b;
 }
 
-void gaim_blist_add_chat(struct chat *chat, struct group *group, GaimBlistNode *node)
+void gaim_blist_add_chat(GaimBlistChat *chat, GaimGroup *group, GaimBlistNode *node)
 {
 	GaimBlistNode *n = node, *cnode = (GaimBlistNode*)chat;
-	struct group *g = group;
+	GaimGroup *g = group;
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	gboolean save = FALSE;
 
@@ -442,7 +460,7 @@
 					gaim_blist_get_last_sibling(gaimbuddylist->root));
 		}
 	} else {
-		g = (struct group*)n->parent;
+		g = (GaimGroup*)n->parent;
 	}
 
 	/* if we're moving to overtop of ourselves, do nothing */
@@ -453,10 +471,10 @@
 		/* This chat was already in the list and is
 		 * being moved.
 		 */
-		((struct group *)cnode->parent)->totalsize--;
+		((GaimGroup *)cnode->parent)->totalsize--;
 		if (gaim_account_is_connected(chat->account)) {
-			((struct group *)cnode->parent)->online--;
-			((struct group *)cnode->parent)->currentsize--;
+			((GaimGroup *)cnode->parent)->online--;
+			((GaimGroup *)cnode->parent)->currentsize--;
 		}
 		if(cnode->next)
 			cnode->next->prev = cnode->prev;
@@ -477,10 +495,10 @@
 		cnode->prev = n;
 		cnode->parent = n->parent;
 		n->next = cnode;
-		((struct group *)n->parent)->totalsize++;
+		((GaimGroup *)n->parent)->totalsize++;
 		if (gaim_account_is_connected(chat->account)) {
-			((struct group *)n->parent)->online++;
-			((struct group *)n->parent)->currentsize++;
+			((GaimGroup *)n->parent)->online++;
+			((GaimGroup *)n->parent)->currentsize++;
 		}
 	} else {
 		if(((GaimBlistNode*)g)->child)
@@ -502,83 +520,111 @@
 		gaim_blist_save();
 }
 
-void  gaim_blist_add_buddy (struct buddy *buddy, struct group *group, GaimBlistNode *node)
+void  gaim_blist_add_buddy (GaimBuddy *buddy, GaimContact *contact, GaimGroup *group, GaimBlistNode *node)
 {
-	GaimBlistNode *n = node, *bnode = (GaimBlistNode*)buddy;
-	struct group *g = group;
+	GaimBlistNode *cnode, *bnode;
+	GaimGroup *g;
+	GaimContact *c;
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
+	gboolean save = FALSE;
 	struct _gaim_hbuddy *hb;
-	gboolean save = FALSE;
+
+	g_return_if_fail(buddy != NULL);
+
+	bnode = (GaimBlistNode *)buddy;
 
-	if (!n) {
-		if (!g) {
+	/* if we're moving to overtop of ourselves, do nothing */
+	if(bnode == node || (!node && bnode->parent &&
+				contact && bnode->parent == (GaimBlistNode*)contact
+				&& bnode == bnode->parent->child))
+		return;
+
+	if(node && GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		c = (GaimContact*)node->parent;
+		g = (GaimGroup*)node->parent->parent;
+	} else if(contact) {
+		c = contact;
+		g = (GaimGroup*)((GaimBlistNode*)c)->parent;
+	} else  {
+		if(group) {
+			g = group;
+		} else {
 			g = gaim_group_new(_("Buddies"));
 			gaim_blist_add_group(g,
 					gaim_blist_get_last_sibling(gaimbuddylist->root));
 		}
-	} else {
-		g = (struct group*)n->parent;
+		c = gaim_contact_new();
+		gaim_blist_add_contact(c, g,
+				gaim_blist_get_last_child((GaimBlistNode*)g));
 	}
 
-	/* if we're moving to overtop of ourselves, do nothing */
-	if(bnode == n)
-		return;
+	cnode = (GaimBlistNode *)c;
 
-	if (bnode->parent) {
-		/* This buddy was already in the list and is
-		 * being moved.
-		 */
-		((struct group *)bnode->parent)->totalsize--;
-		if (gaim_account_is_connected(buddy->account))
-			((struct group *)bnode->parent)->currentsize--;
-		if (GAIM_BUDDY_IS_ONLINE(buddy))
-			((struct group *)bnode->parent)->online--;
+	if(bnode->parent) {
+		if(GAIM_BUDDY_IS_ONLINE(buddy)) {
+			((GaimContact*)bnode->parent)->online--;
+			if(((GaimContact*)bnode->parent)->online == 0)
+				((GaimGroup*)bnode->parent->parent)->online--;
+		}
+		if(gaim_account_is_connected(buddy->account)) {
+			((GaimContact*)bnode->parent)->currentsize--;
+			if(((GaimContact*)bnode->parent)->currentsize == 0)
+				((GaimGroup*)bnode->parent->parent)->currentsize--;
+		}
+		((GaimContact*)bnode->parent)->totalsize--;
+		/* the group totalsize will be taken care of by remove_contact below */
+
+		if(bnode->parent->parent != (GaimBlistNode*)g)
+			serv_move_buddy(buddy, (GaimGroup *)bnode->parent->parent, g);
 
 		if(bnode->next)
 			bnode->next->prev = bnode->prev;
 		if(bnode->prev)
 			bnode->prev->next = bnode->next;
-		if(bnode->parent->child == bnode)
+		if(bnode->parent->child == bnode) {
 			bnode->parent->child = bnode->next;
+			if(!bnode->parent->child)
+				gaim_blist_remove_contact((GaimContact*)bnode->parent);
+		}
 
 		ops->remove(gaimbuddylist, bnode);
 
-		if (bnode->parent != ((GaimBlistNode*)g)) {
-			serv_move_buddy(buddy, (struct group*)bnode->parent, g);
-		}
 		save = TRUE;
 	}
 
-	if (n) {
-		if(n->next)
-			n->next->prev = (GaimBlistNode*)buddy;
-		((GaimBlistNode*)buddy)->next = n->next;
-		((GaimBlistNode*)buddy)->prev = n;
-		((GaimBlistNode*)buddy)->parent = n->parent;
-		n->next = (GaimBlistNode*)buddy;
-		((struct group *)n->parent)->totalsize++;
-		if (gaim_account_is_connected(buddy->account))
-			((struct group *)n->parent)->currentsize++;
-		if (GAIM_BUDDY_IS_ONLINE(buddy))
-			((struct group *)n->parent)->online++;
+	if(node && GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		if(node->next)
+			node->next->prev = bnode;
+		bnode->next = node->next;
+		bnode->prev = node;
+		bnode->parent = node->parent;
+		node->next = bnode;
 	} else {
-		if(((GaimBlistNode*)g)->child)
-			((GaimBlistNode*)g)->child->prev = (GaimBlistNode*)buddy;
-		((GaimBlistNode*)buddy)->prev = NULL;
-		((GaimBlistNode*)buddy)->next = ((GaimBlistNode*)g)->child;
-		((GaimBlistNode*)g)->child = (GaimBlistNode*)buddy;
-		((GaimBlistNode*)buddy)->parent = (GaimBlistNode*)g;
-		g->totalsize++;
-		if (gaim_account_is_connected(buddy->account))
-			g->currentsize++;
-		if (GAIM_BUDDY_IS_ONLINE(buddy))
-			g->online++;
+		if(cnode->child)
+			cnode->child->prev = bnode;
+		bnode->prev = NULL;
+		bnode->next = cnode->child;
+		cnode->child = bnode;
+		bnode->parent = cnode;
 	}
 
+	if(GAIM_BUDDY_IS_ONLINE(buddy)) {
+		((GaimContact*)bnode->parent)->online++;
+		if(((GaimContact*)bnode->parent)->online == 1)
+			((GaimGroup*)bnode->parent->parent)->online++;
+	}
+	if(gaim_account_is_connected(buddy->account)) {
+		((GaimContact*)bnode->parent)->currentsize++;
+		if(((GaimContact*)bnode->parent)->currentsize == 1)
+			((GaimGroup*)bnode->parent->parent)->currentsize++;
+	}
+	((GaimContact*)bnode->parent)->totalsize++;
+
+
 	hb = g_malloc(sizeof(struct _gaim_hbuddy));
 	hb->name = g_strdup(normalize(buddy->name));
 	hb->account = buddy->account;
-	hb->group = ((GaimBlistNode*)buddy)->parent;
+	hb->group = ((GaimBlistNode*)buddy)->parent->parent;
 
 	if (g_hash_table_lookup(gaimbuddylist->buddies, (gpointer)hb)) {
 		/* This guy already exists */
@@ -594,13 +640,28 @@
 		gaim_blist_save();
 }
 
-struct group *gaim_group_new(const char *name)
+GaimContact *gaim_contact_new()
 {
-	struct group *g = gaim_find_group(name);
+	struct gaim_blist_ui_ops *ops;
+	GaimContact *c = g_new0(GaimContact, 1);
+	((GaimBlistNode*)c)->type = GAIM_BLIST_CONTACT_NODE;
+
+	c->totalsize = c->currentsize = c->online = 0;
+
+	ops = gaim_get_blist_ui_ops();
+	if (ops != NULL && ops->new_node != NULL)
+		ops->new_node((GaimBlistNode *)c);
+
+	return c;
+}
+
+GaimGroup *gaim_group_new(const char *name)
+{
+	GaimGroup *g = gaim_find_group(name);
 
 	if (!g) {
 		struct gaim_blist_ui_ops *ops;
-		g= g_new0(struct group, 1);
+		g= g_new0(GaimGroup, 1);
 		g->name = g_strdup(name);
 		g->totalsize = 0;
 		g->currentsize = 0;
@@ -618,7 +679,81 @@
 	return g;
 }
 
-void  gaim_blist_add_group (struct group *group, GaimBlistNode *node)
+void gaim_blist_add_contact(GaimContact *contact, GaimGroup *group, GaimBlistNode *node)
+{
+	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
+	GaimGroup *g;
+	GaimBlistNode *gnode, *cnode;
+	gboolean save = FALSE;
+
+	if(!contact)
+		return;
+
+	if(node && (GAIM_BLIST_NODE_IS_CONTACT(node) ||
+				GAIM_BLIST_NODE_IS_CHAT(node)))
+		g = (GaimGroup*)node->parent;
+	else if(group)
+		g = group;
+	else {
+		g = gaim_group_new(_("Buddies"));
+		gaim_blist_add_group(g,
+				gaim_blist_get_last_sibling(gaimbuddylist->root));
+	}
+
+	gnode = (GaimBlistNode*)g;
+	cnode = (GaimBlistNode*)contact;
+
+	if(cnode->parent) {
+
+		ops->remove(gaimbuddylist, cnode);
+
+		if(gnode->child == cnode)
+			gnode->child = cnode->next;
+		if(cnode->prev)
+			cnode->prev->next = cnode->next;
+		if(cnode->next)
+			cnode->next->prev = cnode->prev;
+
+
+		if(contact->online > 0)
+			((GaimGroup*)cnode->parent)->online--;
+		if(contact->currentsize > 0)
+			((GaimGroup*)cnode->parent)->currentsize--;
+		((GaimGroup*)cnode->parent)->totalsize--;
+
+		save = TRUE;
+	}
+
+	if(node && (GAIM_BLIST_NODE_IS_CONTACT(node) ||
+				GAIM_BLIST_NODE_IS_CHAT(node))) {
+		if(node->next)
+			node->next->prev = cnode;
+		cnode->next = node->next;
+		cnode->prev = node;
+		cnode->parent = node->parent;
+		node->next = cnode;
+	} else {
+		if(gnode->child)
+			gnode->child->prev = cnode;
+		cnode->prev = NULL;
+		cnode->next = gnode->child;
+		gnode->child = cnode;
+		cnode->parent = gnode;
+	}
+
+	if(contact->online > 0)
+		g->online++;
+	if(contact->currentsize > 0)
+		g->currentsize++;
+	g->totalsize++;
+
+	if(ops && cnode->child)
+		ops->update(gaimbuddylist, cnode);
+	if (save)
+		gaim_blist_save();
+}
+
+void  gaim_blist_add_group (GaimGroup *group, GaimBlistNode *node)
 {
 	struct gaim_blist_ui_ops *ops;
 	GaimBlistNode *gnode = (GaimBlistNode*)group;
@@ -652,7 +787,7 @@
 		save = TRUE;
 	}
 
-	if (node) {
+	if (node && GAIM_BLIST_NODE_IS_GROUP(node)) {
 		gnode->next = node->next;
 		gnode->prev = node;
 		if(node->next)
@@ -675,33 +810,70 @@
 		gaim_blist_save();
 }
 
-void  gaim_blist_remove_buddy (struct buddy *buddy)
+void gaim_blist_remove_contact(GaimContact* contact)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 
-	GaimBlistNode *gnode, *node = (GaimBlistNode*)buddy;
-	struct group *group;
+	GaimBlistNode *gnode, *cnode = (GaimBlistNode*)contact;
+
+	gnode = cnode->parent;
+
+	if(cnode->child) {
+		while(cnode->child) {
+			gaim_blist_remove_buddy((GaimBuddy*)cnode->child);
+		}
+	} else {
+		if(ops)
+			ops->remove(gaimbuddylist, cnode);
+
+		if(gnode->child == cnode)
+			gnode->child = cnode->next;
+		if(cnode->prev)
+			cnode->prev->next = cnode->next;
+		if(cnode->next)
+			cnode->next->prev = cnode->prev;
+
+		g_free(contact);
+	}
+}
+
+void  gaim_blist_remove_buddy (GaimBuddy *buddy)
+{
+	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
+
+	GaimBlistNode *cnode, *node = (GaimBlistNode*)buddy;
+	GaimGroup *group;
 	struct _gaim_hbuddy hb, *key;
 	struct buddy *val;
 
-	gnode = node->parent;
-	group = (struct group *)gnode;
+	cnode = node->parent;
+	group = (GaimGroup *)cnode->parent;
 
-	if(gnode->child == node)
-		gnode->child = node->next;
+	if(GAIM_BUDDY_IS_ONLINE(buddy)) {
+		((GaimContact*)cnode)->online--;
+		if(((GaimContact*)cnode)->online == 0)
+			group->online--;
+	}
+	if(gaim_account_is_connected(buddy->account)) {
+		((GaimContact*)cnode)->currentsize--;
+		if(((GaimContact*)cnode)->currentsize == 0)
+			group->currentsize--;
+	}
+	((GaimContact*)cnode)->totalsize--;
+
 	if (node->prev)
 		node->prev->next = node->next;
 	if (node->next)
 		node->next->prev = node->prev;
-	group->totalsize--;
-	if (gaim_account_is_connected(buddy->account))
-		group->currentsize--;
-	if (GAIM_BUDDY_IS_ONLINE(buddy))
-		group->online--;
+	if(cnode->child == node) {
+		cnode->child = node->next;
+		if(!cnode->child)
+			gaim_blist_remove_contact((GaimContact*)cnode);
+	}
 
 	hb.name = normalize(buddy->name);
 	hb.account = buddy->account;
-	hb.group = ((GaimBlistNode*)buddy)->parent;
+	hb.group = ((GaimBlistNode*)buddy)->parent->parent;
 	if (g_hash_table_lookup_extended(gaimbuddylist->buddies, &hb, (gpointer *)&key, (gpointer *)&val)) {
 		g_hash_table_remove(gaimbuddylist->buddies, &hb);
 		g_free(key->name);
@@ -718,15 +890,15 @@
 	g_free(buddy);
 }
 
-void  gaim_blist_remove_chat (struct chat *chat)
+void  gaim_blist_remove_chat (GaimBlistChat *chat)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 
 	GaimBlistNode *gnode, *node = (GaimBlistNode*)chat;
-	struct group *group;
+	GaimGroup *group;
 
 	gnode = node->parent;
-	group = (struct group *)gnode;
+	group = (GaimGroup *)gnode;
 
 	if(gnode->child == node)
 		gnode->child = node->next;
@@ -746,7 +918,7 @@
 	g_free(chat);
 }
 
-void  gaim_blist_remove_group (struct group *group)
+void  gaim_blist_remove_group (GaimGroup *group)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
 	GaimBlistNode *node = (GaimBlistNode*)group;
@@ -787,7 +959,36 @@
 	g_free(group);
 }
 
-char *gaim_get_buddy_alias_only(struct buddy *b) {
+GaimBuddy *gaim_contact_get_priority_buddy(GaimContact *contact) {
+	GaimBuddy *top = NULL;
+	GaimBlistNode *bnode;
+
+	for(bnode = ((GaimBlistNode*)contact)->child; bnode; bnode = bnode->next) {
+		GaimBuddy *buddy;
+		if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+			continue;
+		buddy = (GaimBuddy*)bnode;
+		if(!top) {
+			top = buddy;
+		} else if(GAIM_BUDDY_IS_ONLINE(buddy)) {
+			if(!GAIM_BUDDY_IS_ONLINE(top)) {
+				top = buddy;
+			} else if(!(buddy->uc & UC_UNAVAILABLE) && !buddy->idle &&
+					(top->uc & UC_UNAVAILABLE || top->idle)) {
+				top = buddy;
+			} else if(!buddy->idle && top->idle) {
+				top = buddy;
+			} else if(top->uc & UC_UNAVAILABLE && top->idle &&
+					(!(buddy->uc & UC_UNAVAILABLE) || !buddy->idle)) {
+				top = buddy;
+			}
+		}
+	}
+
+	return top;
+}
+
+const char *gaim_get_buddy_alias_only(GaimBuddy *b) {
 	if(!b)
 		return NULL;
 
@@ -803,9 +1004,9 @@
 	return NULL;
 }
 
-char *  gaim_get_buddy_alias (struct buddy *buddy)
+const char *  gaim_get_buddy_alias (GaimBuddy *buddy)
 {
-	char *ret = gaim_get_buddy_alias_only(buddy);
+	const char *ret = gaim_get_buddy_alias_only(buddy);
 
 	if(!ret)
 		return buddy ? buddy->name : _("Unknown");
@@ -813,9 +1014,9 @@
 	return ret;
 }
 
-struct buddy *gaim_find_buddy(GaimAccount *account, const char *name)
+GaimBuddy *gaim_find_buddy(GaimAccount *account, const char *name)
 {
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 	struct _gaim_hbuddy hb;
 	GaimBlistNode *group;
 
@@ -862,25 +1063,25 @@
 	return ret;
 }
 
-struct group *gaim_find_group(const char *name)
+GaimGroup *gaim_find_group(const char *name)
 {
 	GaimBlistNode *node;
 	if (!gaimbuddylist)
 		return NULL;
 	node = gaimbuddylist->root;
 	while(node) {
-		if (!strcmp(((struct group*)node)->name, name))
-			return (struct group*)node;
+		if (!strcmp(((GaimGroup *)node)->name, name))
+			return (GaimGroup *)node;
 		node = node->next;
 	}
 	return NULL;
 }
 
-struct chat *
+GaimBlistChat *
 gaim_blist_find_chat(GaimAccount *account, const char *name)
 {
 	char *chat_name;
-	struct chat *chat;
+	GaimBlistChat *chat;
 	GaimPlugin *prpl;
 	GaimPluginProtocolInfo *prpl_info = NULL;
 	struct proto_chat_entry *pce;
@@ -894,7 +1095,7 @@
 		for (node = group->child; node != NULL; node = node->next) {
 			if (GAIM_BLIST_NODE_IS_CHAT(node)) {
 
-				chat = (struct chat *)node;
+				chat = (GaimBlistChat*)node;
 
 				prpl = gaim_find_prpl(gaim_account_get_protocol(chat->account));
 				prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);
@@ -918,97 +1119,126 @@
 	return NULL;
 }
 
-struct group *
-gaim_blist_chat_get_group(struct chat *chat)
+GaimGroup *
+gaim_blist_chat_get_group(GaimBlistChat *chat)
 {
 	g_return_val_if_fail(chat != NULL, NULL);
 
-	return (struct group *)(((GaimBlistNode *)chat)->parent);
+	return (GaimGroup *)(((GaimBlistNode *)chat)->parent);
 }
 
-struct group *gaim_find_buddys_group(struct buddy *buddy)
+GaimGroup *gaim_find_buddys_group(GaimBuddy *buddy)
 {
 	if (!buddy)
 		return NULL;
-	return (struct group*)(((GaimBlistNode*)buddy)->parent);
+	return (GaimGroup *)(((GaimBlistNode*)buddy)->parent->parent);
 }
 
-GSList *gaim_group_get_accounts(struct group *g)
+GSList *gaim_group_get_accounts(GaimGroup *g)
 {
 	GSList *l = NULL;
-	GaimBlistNode *child = ((GaimBlistNode *)g)->child;
+	GaimBlistNode *gnode, *cnode, *bnode;
+
+	gnode = (GaimBlistNode *)g;
 
-	while (child) {
-		GaimAccount *account = NULL;
-		if (GAIM_BLIST_NODE_IS_BUDDY(child))
-			account = ((struct buddy *)child)->account;
-		else if (GAIM_BLIST_NODE_IS_CHAT(child))
-			account = ((struct chat *)child)->account;
-		if (!g_slist_find(l, account))
-			l = g_slist_append(l, account);
-		child = child->next;
+	for(cnode = gnode->child;  cnode; cnode = cnode->next) {
+		if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+			if(!g_slist_find(l, ((GaimBlistChat *)cnode)->account))
+				l = g_slist_append(l, ((GaimBlistChat *)cnode)->account);
+		} else if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+			for(bnode = cnode->child; bnode; bnode = bnode->next) {
+				if(GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
+					if(!g_slist_find(l, ((GaimBuddy *)bnode)->account))
+						l = g_slist_append(l, ((GaimBuddy *)bnode)->account);
+				}
+			}
+		}
 	}
+
 	return l;
 }
 
 void gaim_blist_add_account(GaimAccount *account)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
-	GaimBlistNode *group, *buddy;
+	GaimBlistNode *gnode, *cnode, *bnode;
 
 	if(!gaimbuddylist)
 		return;
 
-	for(group = gaimbuddylist->root; group; group = group->next) {
-		if(!GAIM_BLIST_NODE_IS_GROUP(group))
+	if(!ops)
+		return;
+
+	for(gnode = gaimbuddylist->root; gnode; gnode = gnode->next) {
+		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(buddy = group->child; buddy; buddy = buddy->next) {
-			if(GAIM_BLIST_NODE_IS_BUDDY(buddy)) {
-				if (account == ((struct buddy*)buddy)->account) {
-					((struct group *)group)->currentsize++;
-					if(ops)
-						ops->update(gaimbuddylist, buddy);
-				}
-			} else if(GAIM_BLIST_NODE_IS_CHAT(buddy)) {
-				if (account == ((struct chat*)buddy)->account) {
-					((struct group *)group)->online++;
-					((struct group *)group)->currentsize++;
-					if(ops)
-						ops->update(gaimbuddylist, buddy);
-				}
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+					for(bnode = cnode->child; bnode; bnode = bnode->next) {
+						if(GAIM_BLIST_NODE_IS_BUDDY(bnode) &&
+								((GaimBuddy*)bnode)->account == account) {
+							((GaimContact*)cnode)->currentsize++;
+							if(((GaimContact*)cnode)->currentsize == 1)
+								((GaimGroup*)gnode)->currentsize++;
+							if(GAIM_BUDDY_IS_ONLINE((GaimBuddy*)bnode)) {
+								((GaimContact*)cnode)->online++;
+								if(((GaimContact*)cnode)->online == 1)
+									((GaimGroup*)gnode)->online++;
+							}
+							ops->update(gaimbuddylist, bnode);
+						}
+					}
+					ops->update(gaimbuddylist, cnode);
+			} else if(GAIM_BLIST_NODE_IS_CHAT(cnode) &&
+					((GaimBlistChat*)cnode)->account == account) {
+					((GaimGroup *)gnode)->online++;
+					((GaimGroup *)gnode)->currentsize++;
+					ops->update(gaimbuddylist, cnode);
 			}
 		}
+		ops->update(gaimbuddylist, gnode);
 	}
 }
 
 void gaim_blist_remove_account(GaimAccount *account)
 {
 	struct gaim_blist_ui_ops *ops = gaimbuddylist->ui_ops;
-	GaimBlistNode *group, *buddy;
+	GaimBlistNode *gnode, *cnode, *bnode;
 
 	if (!gaimbuddylist)
 		return;
 
-	for(group = gaimbuddylist->root; group; group = group->next) {
-		if(!GAIM_BLIST_NODE_IS_GROUP(group))
+	for(gnode = gaimbuddylist->root; gnode; gnode = gnode->next) {
+		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(buddy = group->child; buddy; buddy = buddy->next) {
-			if(GAIM_BLIST_NODE_IS_BUDDY(buddy)) {
-				if (account == ((struct buddy*)buddy)->account) {
-					if (GAIM_BUDDY_IS_ONLINE((struct buddy*)buddy))
-						((struct group *)group)->online--;
-					((struct buddy*)buddy)->present = GAIM_BUDDY_OFFLINE;
-					((struct group *)group)->currentsize--;
-					if(ops)
-						ops->remove(gaimbuddylist, buddy);
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+				for(bnode = cnode->child; bnode; bnode = bnode->next) {
+					if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+						continue;
+					if(account == ((GaimBuddy *)bnode)->account) {
+						if(((GaimBuddy*)bnode)->present == GAIM_BUDDY_ONLINE ||
+								((GaimBuddy*)bnode)->present == GAIM_BUDDY_SIGNING_ON) {
+							((GaimContact*)cnode)->online--;
+							if(((GaimContact*)cnode)->online == 0)
+								((GaimGroup*)gnode)->online--;
+						}
+						((GaimContact*)cnode)->currentsize--;
+						if(((GaimContact*)cnode)->currentsize == 0)
+							((GaimGroup*)gnode)->currentsize--;
+
+						((GaimBuddy*)bnode)->present = GAIM_BUDDY_OFFLINE;
+
+						if(ops)
+							ops->remove(gaimbuddylist, bnode);
+					}
 				}
-			} else if(GAIM_BLIST_NODE_IS_CHAT(buddy)) {
-				if (account == ((struct chat*)buddy)->account) {
-					((struct group *)group)->online--;
-					((struct group *)group)->currentsize--;
-					if(ops)
-						ops->remove(gaimbuddylist, buddy);
-				}
+			} else if(GAIM_BLIST_NODE_IS_CHAT(cnode) &&
+					((GaimBlistChat*)cnode)->account == account) {
+				((GaimGroup*)gnode)->currentsize--;
+				((GaimGroup*)gnode)->online--;
+				if(ops)
+					ops->remove(gaimbuddylist, cnode);
 			}
 		}
 	}
@@ -1040,7 +1270,7 @@
 					g_free(utf8);
 				}
 				if (!gaim_find_group(current)) {
-					struct group *g = gaim_group_new(current);
+					GaimGroup *g = gaim_group_new(current);
 					gaim_blist_add_group(g,
 							gaim_blist_get_last_sibling(gaimbuddylist->root));
 				}
@@ -1070,9 +1300,9 @@
 				}
 
 				if (!gaim_find_buddy(account, nm)) {
-					struct buddy *b = gaim_buddy_new(account, nm, sw);
-					struct group *g = gaim_find_group(current);
-					gaim_blist_add_buddy(b, g,
+					GaimBuddy *b = gaim_buddy_new(account, nm, sw);
+					GaimGroup *g = gaim_find_group(current);
+					gaim_blist_add_buddy(b, NULL, g,
 							gaim_blist_get_last_child((GaimBlistNode*)g));
 					bud = g_list_append(bud, g_strdup(nm));
 				}
@@ -1304,7 +1534,7 @@
 		char *file = gaim_user_dir();
 		GaimProtocol prpl_num;
 		int protocol;
-		
+
 		prpl_num = gaim_account_get_protocol(account);
 
 		protocol = prpl_num;
@@ -1394,23 +1624,33 @@
 	}
 }
 
-gboolean gaim_group_on_account(struct group *g, GaimAccount *account) {
-	GaimBlistNode *bnode;
-	for(bnode = g->node.child; bnode; bnode = bnode->next) {
-		struct buddy *b = (struct buddy *)bnode;
-		if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-			continue;
-		if((!account && gaim_account_is_connected(b->account))
-				|| b->account == account)
-			return TRUE;
+gboolean gaim_group_on_account(GaimGroup *g, GaimAccount *account) {
+	GaimBlistNode *cnode, *bnode;
+	for(cnode = ((GaimBlistNode *)g)->child; cnode; cnode = cnode->next) {
+		if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+			for(bnode = cnode->child; bnode; bnode = bnode->next) {
+				if(GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
+					GaimBuddy *buddy = (GaimBuddy *)bnode;
+					if((!account && gaim_account_is_connected(buddy->account))
+							|| buddy->account == account)
+						return TRUE;
+				}
+			}
+		} else if(GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+			GaimBlistChat *chat = (GaimBlistChat *)cnode;
+			if((!account && gaim_account_is_connected(chat->account))
+					|| chat->account == account)
+				return TRUE;
+		}
 	}
 	return FALSE;
 }
 
 static gboolean blist_safe_to_write = FALSE;
 
+GaimGroup *blist_parser_group = NULL;
+GaimContact *blist_parser_contact = NULL;
 static char *blist_parser_group_name = NULL;
-static char *blist_parser_person_name = NULL;
 static char *blist_parser_account_name = NULL;
 static int blist_parser_account_protocol = 0;
 static char *blist_parser_chat_alias = NULL;
@@ -1432,7 +1672,7 @@
 	BLIST_TAG_GROUP,
 	BLIST_TAG_CHAT,
 	BLIST_TAG_COMPONENT,
-	BLIST_TAG_PERSON,
+	BLIST_TAG_CONTACT,
 	BLIST_TAG_BUDDY,
 	BLIST_TAG_NAME,
 	BLIST_TAG_ALIAS,
@@ -1466,10 +1706,17 @@
 			}
 		}
 		if(blist_parser_group_name) {
-			struct group *g = gaim_group_new(blist_parser_group_name);
-			gaim_blist_add_group(g,
+			blist_parser_group = gaim_group_new(blist_parser_group_name);
+			gaim_blist_add_group(blist_parser_group,
 					gaim_blist_get_last_sibling(gaimbuddylist->root));
 		}
+	} else if(!strcmp(element_name, "contact")) {
+		tag_stack = g_list_prepend(tag_stack,
+				GINT_TO_POINTER(BLIST_TAG_CONTACT));
+
+		blist_parser_contact = gaim_contact_new();
+		gaim_blist_add_contact(blist_parser_contact, blist_parser_group,
+				gaim_blist_get_last_sibling(((GaimBlistNode*)blist_parser_group)->child));
 	} else if(!strcmp(element_name, "chat")) {
 		tag_stack = g_list_prepend(tag_stack, GINT_TO_POINTER(BLIST_TAG_CHAT));
 		for(i=0; attribute_names[i]; i++) {
@@ -1480,14 +1727,6 @@
 				blist_parser_account_protocol = atoi(attribute_values[i]);
 			}
 		}
-	} else if(!strcmp(element_name, "person")) {
-		tag_stack = g_list_prepend(tag_stack, GINT_TO_POINTER(BLIST_TAG_PERSON));
-		for(i=0; attribute_names[i]; i++) {
-			if(!strcmp(attribute_names[i], "name")) {
-				g_free(blist_parser_person_name);
-				blist_parser_person_name = g_strdup(attribute_values[i]);
-			}
-		}
 	} else if(!strcmp(element_name, "buddy")) {
 		tag_stack = g_list_prepend(tag_stack, GINT_TO_POINTER(BLIST_TAG_BUDDY));
 		for(i=0; attribute_names[i]; i++) {
@@ -1550,18 +1789,21 @@
 		tag_stack = g_list_delete_link(tag_stack, tag_stack);
 	} else if(!strcmp(element_name, "group")) {
 		if(blist_parser_group_settings) {
-			struct group *g = gaim_find_group(blist_parser_group_name);
+			GaimGroup *g = gaim_find_group(blist_parser_group_name);
 			g_hash_table_destroy(g->settings);
 			g->settings = blist_parser_group_settings;
 		}
 		tag_stack = g_list_delete_link(tag_stack, tag_stack);
 		blist_parser_group_settings = NULL;
+		blist_parser_group = NULL;
+		blist_parser_group_name = NULL;
 	} else if(!strcmp(element_name, "chat")) {
 		GaimAccount *account = gaim_accounts_find(blist_parser_account_name,
 				blist_parser_account_protocol);
 		if(account) {
-			struct chat *chat = gaim_chat_new(account, blist_parser_chat_alias, blist_parser_chat_components);
-			struct group *g = gaim_find_group(blist_parser_group_name);
+			GaimBlistChat *chat = gaim_blist_chat_new(account,
+					blist_parser_chat_alias, blist_parser_chat_components);
+			GaimGroup *g = gaim_find_group(blist_parser_group_name);
 			gaim_blist_add_chat(chat,g,
 					gaim_blist_get_last_child((GaimBlistNode*)g));
 			if(blist_parser_chat_settings) {
@@ -1576,18 +1818,18 @@
 		blist_parser_chat_components = NULL;
 		blist_parser_chat_settings = NULL;
 		tag_stack = g_list_delete_link(tag_stack, tag_stack);
-	} else if(!strcmp(element_name, "person")) {
-		g_free(blist_parser_person_name);
-		blist_parser_person_name = NULL;
+	} else if(!strcmp(element_name, "contact")) {
+		if(blist_parser_contact && !blist_parser_contact->node.child)
+			gaim_blist_remove_contact(blist_parser_contact);
+		blist_parser_contact = NULL;
 		tag_stack = g_list_delete_link(tag_stack, tag_stack);
 	} else if(!strcmp(element_name, "buddy")) {
 		GaimAccount *account = gaim_accounts_find(blist_parser_account_name,
 				blist_parser_account_protocol);
 		if(account) {
-			struct buddy *b = gaim_buddy_new(account, blist_parser_buddy_name, blist_parser_buddy_alias);
-			struct group *g = gaim_find_group(blist_parser_group_name);
-			gaim_blist_add_buddy(b,g,
-					gaim_blist_get_last_child((GaimBlistNode*)g));
+			GaimBuddy *b = gaim_buddy_new(account, blist_parser_buddy_name, blist_parser_buddy_alias);
+			gaim_blist_add_buddy(b,blist_parser_contact, blist_parser_group,
+					gaim_blist_get_last_child((GaimBlistNode*)blist_parser_contact));
 			if(blist_parser_buddy_settings) {
 				g_hash_table_destroy(b->settings);
 				b->settings = blist_parser_buddy_settings;
@@ -1797,24 +2039,6 @@
 			g_free(msg);
 		}
 	} else if(g_list_length(gaim_accounts_get_all())) {
-#if 0
-		GMainContext *ctx;
-
-		/* rob wants to inform the user that their buddy lists are
-		 * being converted */
-		msg = g_strdup_printf(_("Gaim is converting your old buddy lists "
-					"to a new format, which will now be located at %s"),
-				filename);
-		gaim_notify_info(NULL, NULL, _("Converting Buddy List"), msg);
-		g_free(msg);
-
-		/* now, let gtk actually display the dialog before we start anything */
-		ctx = g_main_context_default();
-
-		while(g_main_context_pending(ctx))
-			g_main_context_iteration(ctx, FALSE);
-#endif
-
 		/* read in the old lists, then save to the new format */
 		for(accts = gaim_accounts_get_all(); accts; accts = accts->next) {
 			do_import(accts->data, NULL);
@@ -1861,6 +2085,24 @@
 	g_free(data_val);
 }
 
+static void blist_print_cnode_settings(gpointer key, gpointer data,
+		gpointer user_data) {
+	char *key_val;
+	char *data_val;
+	FILE *file = user_data;
+
+	if(!key || !data)
+		return;
+
+	key_val = g_markup_escape_text(key, -1);
+	data_val = g_markup_escape_text(data, -1);
+
+	fprintf(file, "\t\t\t\t<setting name=\"%s\">%s</setting>\n", key_val,
+			data_val);
+	g_free(key_val);
+	g_free(data_val);
+}
+
 static void blist_print_chat_components(gpointer key, gpointer data,
 		gpointer user_data) {
 	char *key_val;
@@ -1879,54 +2121,62 @@
 	g_free(data_val);
 }
 
+static void print_buddy(FILE *file, GaimBuddy *buddy) {
+	char *bud_name = g_markup_escape_text(buddy->name, -1);
+	char *bud_alias = NULL;
+	char *acct_name = g_markup_escape_text(buddy->account->username, -1);
+	if(buddy->alias)
+		bud_alias= g_markup_escape_text(buddy->alias, -1);
+	fprintf(file, "\t\t\t\t<buddy protocol=\"%d\" "
+			"account=\"%s\">\n",
+			gaim_account_get_protocol(buddy->account),
+			acct_name);
+	fprintf(file, "\t\t\t\t\t<name>%s</name>\n", bud_name);
+	if(bud_alias) {
+		fprintf(file, "\t\t\t\t\t<alias>%s</alias>\n", bud_alias);
+	}
+	g_hash_table_foreach(buddy->settings, blist_print_buddy_settings, file);
+	fprintf(file, "\t\t\t\t</buddy>\n");
+	g_free(bud_name);
+	g_free(bud_alias);
+	g_free(acct_name);
+}
+
 static void gaim_blist_write(FILE *file, GaimAccount *exp_acct) {
 	GList *accounts;
 	GSList *buds;
-	GaimBlistNode *gnode,*bnode;
-	struct group *group;
-	struct buddy *bud;
+	GaimBlistNode *gnode, *cnode, *bnode;
 	fprintf(file, "<?xml version='1.0' encoding='UTF-8' ?>\n");
 	fprintf(file, "<gaim version=\"1\">\n");
 	fprintf(file, "\t<blist>\n");
 
 	for(gnode = gaimbuddylist->root; gnode; gnode = gnode->next) {
+		GaimGroup *group;
+
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		group = (struct group *)gnode;
+
+		group = (GaimGroup *)gnode;
 		if(!exp_acct || gaim_group_on_account(group, exp_acct)) {
 			char *group_name = g_markup_escape_text(group->name, -1);
 			fprintf(file, "\t\t<group name=\"%s\">\n", group_name);
 			g_hash_table_foreach(group->settings, blist_print_group_settings, file);
-			for(bnode = gnode->child; bnode; bnode = bnode->next) {
-				if(GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
-					bud = (struct buddy *)bnode;
-					if(!exp_acct || bud->account == exp_acct) {
-						char *bud_name = g_markup_escape_text(bud->name, -1);
-						char *bud_alias = NULL;
-						char *acct_name = g_markup_escape_text(bud->account->username, -1);
-						if(bud->alias)
-							bud_alias= g_markup_escape_text(bud->alias, -1);
-						fprintf(file, "\t\t\t<person name=\"%s\">\n",
-								bud_alias ? bud_alias : bud_name);
-						fprintf(file, "\t\t\t\t<buddy protocol=\"%d\" "
-								"account=\"%s\">\n",
-								gaim_account_get_protocol(bud->account),
-								acct_name);
-						fprintf(file, "\t\t\t\t\t<name>%s</name>\n", bud_name);
-						if(bud_alias) {
-							fprintf(file, "\t\t\t\t\t<alias>%s</alias>\n",
-									bud_alias);
+			for(cnode = gnode->child; cnode; cnode = cnode->next) {
+				if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+					fprintf(file, "\t\t\t<contact>\n");
+
+					for(bnode = cnode->child; bnode; bnode = bnode->next) {
+						if(GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
+							GaimBuddy *buddy = (GaimBuddy *)bnode;
+							if(!exp_acct || buddy->account == exp_acct) {
+								print_buddy(file, buddy);
+							}
 						}
-						g_hash_table_foreach(bud->settings,
-								blist_print_buddy_settings, file);
-						fprintf(file, "\t\t\t\t</buddy>\n");
-						fprintf(file, "\t\t\t</person>\n");
-						g_free(bud_name);
-						g_free(bud_alias);
-						g_free(acct_name);
 					}
-				} else if(GAIM_BLIST_NODE_IS_CHAT(bnode)) {
-					struct chat *chat = (struct chat *)bnode;
+
+					fprintf(file, "\t\t\t</contact>\n");
+				} else if(GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+					GaimBlistChat *chat = (GaimBlistChat *)cnode;
 					if(!exp_acct || chat->account == exp_acct) {
 						char *acct_name = g_markup_escape_text(chat->account->username, -1);
 						fprintf(file, "\t\t\t<chat protocol=\"%d\" account=\"%s\">\n",
@@ -1939,9 +2189,8 @@
 						}
 						g_hash_table_foreach(chat->components,
 								blist_print_chat_components, file);
-						/* works for chats too, I don't feel like renaming */
 						g_hash_table_foreach(chat->settings,
-								blist_print_buddy_settings, file);
+								blist_print_cnode_settings, file);
 						fprintf(file, "\t\t\t</chat>\n");
 						g_free(acct_name);
 					}
@@ -2026,20 +2275,20 @@
 	g_free(filename_real);
 }
 
-void gaim_group_set_setting(struct group *g, const char *key,
+void gaim_group_set_setting(GaimGroup *g, const char *key,
 		const char *value) {
 	if(!g)
 		return;
 	g_hash_table_replace(g->settings, g_strdup(key), g_strdup(value));
 }
 
-char *gaim_group_get_setting(struct group *g, const char *key) {
+char *gaim_group_get_setting(GaimGroup *g, const char *key) {
 	if(!g)
 		return NULL;
 	return g_strdup(g_hash_table_lookup(g->settings, key));
 }
 
-void gaim_chat_set_setting(struct chat *c, const char *key,
+void gaim_blist_chat_set_setting(GaimBlistChat *c, const char *key,
 		const char *value)
 {
 	if(!c)
@@ -2047,21 +2296,21 @@
 	g_hash_table_replace(c->settings, g_strdup(key), g_strdup(value));
 }
 
-char *gaim_chat_get_setting(struct chat *c, const char *key)
+char *gaim_blist_chat_get_setting(GaimBlistChat *c, const char *key)
 {
 	if(!c)
 		return NULL;
 	return g_strdup(g_hash_table_lookup(c->settings, key));
 }
 
-void gaim_buddy_set_setting(struct buddy *b, const char *key,
+void gaim_buddy_set_setting(GaimBuddy *b, const char *key,
 		const char *value) {
 	if(!b)
 		return;
 	g_hash_table_replace(b->settings, g_strdup(key), g_strdup(value));
 }
 
-char *gaim_buddy_get_setting(struct buddy *b, const char *key) {
+char *gaim_buddy_get_setting(GaimBuddy *b, const char *key) {
 	if(!b)
 		return NULL;
 	return g_strdup(g_hash_table_lookup(b->settings, key));
@@ -2078,14 +2327,14 @@
 	return blist_ui_ops;
 }
 
-int gaim_blist_get_group_size(struct group *group, gboolean offline) {
+int gaim_blist_get_group_size(GaimGroup *group, gboolean offline) {
 	if(!group)
 		return 0;
 
 	return offline ? group->totalsize : group->currentsize;
 }
 
-int gaim_blist_get_group_online_count(struct group *group) {
+int gaim_blist_get_group_online_count(GaimGroup *group) {
 	if(!group)
 		return 0;
 
--- a/src/blist.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/blist.h	Tue Sep 02 03:41:10 2003 +0000
@@ -23,16 +23,17 @@
 
 /* I can't believe I let ChipX86 inspire me to write good code. -Sean */
 
-#ifndef _LIST_H_
-#define _LIST_H_
+#ifndef _BLIST_H_
+#define _BLIST_H_
 
 #include <glib.h>
 
 typedef struct _GaimBlistNode GaimBlistNode;
 
-/* TODO Namespace these! */
-struct chat;
-struct buddy;
+typedef struct _GaimBlistChat GaimBlistChat;
+typedef struct _GaimGroup GaimGroup;
+typedef struct _GaimContact GaimContact;
+typedef struct _GaimBuddy GaimBuddy;
 
 #include "account.h"
 
@@ -41,6 +42,7 @@
 /**************************************************************************/
 enum gaim_blist_node_type {
 	GAIM_BLIST_GROUP_NODE,
+	GAIM_BLIST_CONTACT_NODE,
 	GAIM_BLIST_BUDDY_NODE,
 	GAIM_BLIST_CHAT_NODE,
 	GAIM_BLIST_OTHER_NODE
@@ -48,6 +50,7 @@
 
 #define GAIM_BLIST_NODE_IS_CHAT(n) ((n)->type == GAIM_BLIST_CHAT_NODE)
 #define GAIM_BLIST_NODE_IS_BUDDY(n) ((n)->type == GAIM_BLIST_BUDDY_NODE)
+#define GAIM_BLIST_NODE_IS_CONTACT(n) ((n)->type == GAIM_BLIST_CONTACT_NODE)
 #define GAIM_BLIST_NODE_IS_GROUP(n) ((n)->type == GAIM_BLIST_GROUP_NODE)
 
 enum gaim_buddy_presence_state {
@@ -57,8 +60,9 @@
 	GAIM_BUDDY_SIGNING_ON
 };
 
-#define GAIM_BUDDY_IS_ONLINE(b) ((b)->present == GAIM_BUDDY_ONLINE || \
-		(b)->present == GAIM_BUDDY_SIGNING_ON)
+#define GAIM_BUDDY_IS_ONLINE(b) ((b)->account->gc && \
+		((b)->present == GAIM_BUDDY_ONLINE || \
+		 (b)->present == GAIM_BUDDY_SIGNING_ON))
 
 
 /**************************************************************************/
@@ -80,11 +84,11 @@
 /**
  * A buddy.  This contains everything Gaim will ever need to know about someone on the buddy list.  Everything.
  */
-struct buddy {
+struct _GaimBuddy {
 	GaimBlistNode node;                     /**< The node that this buddy inherits from */
 	char *name;                             /**< The screenname of the buddy. */
 	char *alias;                            /**< The user-set alias of the buddy */
-	char *server_alias;                     /**< The server-specified alias of the buddy.  (i.e. MSN "Friendly Names") */ 
+	char *server_alias;                     /**< The server-specified alias of the buddy.  (i.e. MSN "Friendly Names") */
 	enum gaim_buddy_presence_state present;                            /**< This is 0 if the buddy appears offline, 1 if he appears online, and 2 if
 						    he has recently signed on */
 	int evil;                               /**< The warning level */
@@ -92,28 +96,39 @@
 	int idle;                               /**< The time the buddy has been idle in minutes. */
 	int uc;                                 /**< This is a cryptic bitmask that makes sense only to the prpl.  This will get changed */
 	void *proto_data;                       /**< This allows the prpl to associate whatever data it wants with a buddy */
-	GaimAccount *account;           /**< the account this buddy belongs to */ 
+	GaimAccount *account;           /**< the account this buddy belongs to */
 	GHashTable *settings;                   /**< per-buddy settings from the XML buddy list, set by plugins and the likes. */
 	guint timer;							/**< The timer handle. */
 };
 
 /**
+ * A contact.  This contains everything Gaim will ever need to know about a contact.
+ */
+struct _GaimContact {
+	GaimBlistNode node;						/**< The node that this contact inherits from. */
+	int totalsize;			       /**< The number of buddies in this contact */
+	int currentsize;		       /**< The number of buddies in this contact corresponding to online accounts */
+	int online;			       /**< The number of buddies in this contact who are currently online */
+};
+
+
+/**
  * A group.  This contains everything Gaim will ever need to know about a group.
  */
-struct group {
+struct _GaimGroup {
 	GaimBlistNode node;                    /**< The node that this group inherits from */
 	char *name;                            /**< The name of this group. */
-	int totalsize;			       /**< The number of buddies in this group */
-	int currentsize;		       /**< The number of buddies in this group corresponding to online accounts */
-	int online;			       /**< The number of buddies in this group who are currently online */
+	int totalsize;			       /**< The number of chats and contacts in this group */
+	int currentsize;		       /**< The number of chats and contacts in this group corresponding to online accounts */
+	int online;			       /**< The number of chats and contacts in this group who are currently online */
 	GHashTable *settings;                  /**< per-group settings from the XML buddy list, set by plugins and the likes. */
 };
 
 /**
- * A group.  This contains everything Gaim needs to put a chat room in the
+ * A chat.  This contains everything Gaim needs to put a chat room in the
  * buddy list.
  */
-struct chat {
+struct _GaimBlistChat {
 	GaimBlistNode node;      /**< The node that this chat inherits from */
 	char *alias;             /**< The display name of this chat. */
 	GHashTable *components;  /**< the stuff the protocol needs to know to join the chat */
@@ -144,7 +159,7 @@
 	void (*new_list)(struct gaim_buddy_list *list); /**< Sets UI-specific data on a buddy list. */
 	void (*new_node)(GaimBlistNode *node);      /**< Sets UI-specific data on a node. */
 	void (*show)(struct gaim_buddy_list *list);     /**< The core will call this when its finished doing it's core stuff */
-	void (*update)(struct gaim_buddy_list *list, 
+	void (*update)(struct gaim_buddy_list *list,
 		       GaimBlistNode *node);            /**< This will update a node in the buddy list. */
 	void (*remove)(struct gaim_buddy_list *list,
 		       GaimBlistNode *node);            /**< This removes a node from the list */
@@ -209,7 +224,7 @@
  * @param buddy   The buddy whose status has changed
  * @param status  The new status in cryptic prpl-understood code
  */
-void gaim_blist_update_buddy_status(struct buddy *buddy, int status);
+void gaim_blist_update_buddy_status(GaimBuddy *buddy, int status);
 
 
 /**
@@ -218,7 +233,7 @@
  * @param buddy    The buddy whose presence has changed
  * @param presence The new presence
  */
-void gaim_blist_update_buddy_presence(struct buddy *buddy, int presence);
+void gaim_blist_update_buddy_presence(GaimBuddy *buddy, int presence);
 
 
 /**
@@ -227,7 +242,7 @@
  * @param buddy  The buddy whose idle time has changed
  * @param idle   The buddy's idle time in minutes.
  */
-void gaim_blist_update_buddy_idle(struct buddy *buddy, int idle);
+void gaim_blist_update_buddy_idle(GaimBuddy *buddy, int idle);
 
 
 /**
@@ -236,14 +251,14 @@
  * @param buddy  The buddy whose warning level has changed
  * @param evil   The warning level as an int from 0 to 100 (or higher, I guess... but that'd be weird)
  */
-void gaim_blist_update_buddy_evil(struct buddy *buddy, int warning);
+void gaim_blist_update_buddy_evil(GaimBuddy *buddy, int warning);
 
 /**
  * Updates a buddy's icon.
  *
  * @param buddy  The buddy whose buddy icon has changed
  */
-void gaim_blist_update_buddy_icon(struct buddy *buddy);
+void gaim_blist_update_buddy_icon(GaimBuddy *buddy);
 
 
 
@@ -253,7 +268,7 @@
  * @param buddy  The buddy whose name will be changed.
  * @param name   The new name of the buddy.
  */
-void gaim_blist_rename_buddy(struct buddy *buddy, const char *name);
+void gaim_blist_rename_buddy(GaimBuddy *buddy, const char *name);
 
 
 /**
@@ -262,7 +277,7 @@
  * @param buddy  The buddy whose alias will be changed.
  * @param alias  The buddy's alias.
  */
-void gaim_blist_alias_buddy(struct buddy *buddy, const char *alias);
+void gaim_blist_alias_buddy(GaimBuddy *buddy, const char *alias);
 
 /**
  * Sets the server-sent alias of a buddy in the buddy list.
@@ -270,7 +285,7 @@
  * @param buddy  The buddy whose alias will be changed.
  * @param alias  The buddy's "official" alias.
  */
-void gaim_blist_server_alias_buddy(struct buddy *buddy, const char *alias);
+void gaim_blist_server_alias_buddy(GaimBuddy *buddy, const char *alias);
 
 /**
  * Aliases a chat in the buddy list.
@@ -278,7 +293,7 @@
  * @param chat  The chat whose alias will be changed.
  * @param alias The chat's new alias.
  */
-void gaim_blist_alias_chat(struct chat *chat, const char *alias);
+void gaim_blist_alias_chat(GaimBlistChat *chat, const char *alias);
 
 /**
  * Renames a group
@@ -286,7 +301,7 @@
  * @param group  The group to rename
  * @param name   The new name
  */
-void gaim_blist_rename_group(struct group *group, const char *name);
+void gaim_blist_rename_group(GaimGroup *group, const char *name);
 
 /**
  * Creates a new chat for the buddy list
@@ -296,7 +311,7 @@
  * @param components The info the prpl needs to join the chat
  * @return           A newly allocated chat
  */
-struct chat *gaim_chat_new(GaimAccount *account, const char *alias, GHashTable *components);
+GaimBlistChat *gaim_blist_chat_new(GaimAccount *account, const char *alias, GHashTable *components);
 
 /**
  * Gets the alias of the chat, or the chat name if the alias does not exist
@@ -304,7 +319,7 @@
  * @param chat    The chat
  * @return        The display name of the chat
  */
-char *gaim_chat_get_display_name(struct chat *chat);
+char *gaim_blist_chat_get_display_name(GaimBlistChat *chat);
 
 /**
  * Adds a new chat to the buddy list.
@@ -317,7 +332,7 @@
  * @param group  The group to add the new chat to.
  * @param node   The insertion point
  */
-void gaim_blist_add_chat(struct chat *chat, struct group *group, GaimBlistNode *node);
+void gaim_blist_add_chat(GaimBlistChat *chat, GaimGroup *group, GaimBlistNode *node);
 
 /**
  * Creates a new buddy
@@ -327,56 +342,91 @@
  * @param alias      The alias of the new buddy (or NULL if unaliased)
  * @return           A newly allocated buddy
  */
-struct buddy *gaim_buddy_new(GaimAccount *account, const char *screenname, const char *alias);
+GaimBuddy *gaim_buddy_new(GaimAccount *account, const char *screenname, const char *alias);
 
 /**
  * Adds a new buddy to the buddy list.
  *
- * The buddy will be inserted right after node or appended to the end
- * of group if node is NULL.  If both are NULL, the buddy will be added to
+ * The buddy will be inserted right after node or prepended to the
+ * group if node is NULL.  If both are NULL, the buddy will be added to
  * the "Buddies" group.
  *
  * @param buddy  The new buddy who gets added
  * @param group  The group to add the new buddy to.
- * @param node   The insertion point 
+ * @param node   The insertion point
  */
-void gaim_blist_add_buddy(struct buddy *buddy, struct group *group, GaimBlistNode *node);
+void gaim_blist_add_buddy(GaimBuddy *buddy, GaimContact *contact, GaimGroup *group, GaimBlistNode *node);
 
 /**
  * Creates a new group
  *
- * You can't have more than one group with the same name.  Sorry.  If you pass this the 
- * name of a group that already exists, it will return that group.
+ * You can't have more than one group with the same name.  Sorry.  If you pass
+ * this the * name of a group that already exists, it will return that group.
  *
  * @param name   The name of the new group
- * @return       A new group struct 
+ * @return       A new group struct
 */
-struct group *gaim_group_new(const char *name);
+GaimGroup *gaim_group_new(const char *name);
 
 /**
  * Adds a new group to the buddy list.
  *
- * The new group will be inserted after insert or appended to the end of
- * the list if node is NULL.
+ * The new group will be inserted after insert or prepended to the list if
+ * node is NULL.
+ *
+ * @param group  The group
+ * @param node   The insertion point
+ */
+void gaim_blist_add_group(GaimGroup *group, GaimBlistNode *node);
+
+/**
+ * Creates a new contact
  *
- * @param group  The group to add the new buddy to.
- * @param node   The insertion point 
+ * @return       A new contact struct
  */
-void gaim_blist_add_group(struct group *group, GaimBlistNode *node);
+GaimContact *gaim_contact_new();
+
+/**
+ * Adds a new contact to the buddy list.
+ *
+ * The new contact will be inserted after insert or prepended to the list if
+ * node is NULL.
+ *
+ * @param contact The contact
+ * @param group   The group to add the contact to
+ * @param node    The insertion point
+ */
+void gaim_blist_add_contact(GaimContact *contact, GaimGroup *group, GaimBlistNode *node);
+
+/**
+ * Returns the highest priority buddy for a given contact.
+ *
+ * @param contact  The contact
+ * @return The highest priority buddy
+ */
+GaimBuddy *gaim_contact_get_priority_buddy(GaimContact *contact);
 
 /**
  * Removes a buddy from the buddy list and frees the memory allocated to it.
  *
  * @param buddy   The buddy to be removed
  */
-void gaim_blist_remove_buddy(struct buddy *buddy);
+void gaim_blist_remove_buddy(GaimBuddy *buddy);
+
+/**
+ * Removes a contact, and any buddies it contains, and frees the memory
+ * allocated to it.
+ *
+ * @param contact The contact to be removed
+ */
+void gaim_blist_remove_contact(GaimContact *contact);
 
 /**
  * Removes a chat from the buddy list and frees the memory allocated to it.
  *
  * @param chat   The chat to be removed
  */
-void gaim_blist_remove_chat(struct chat *chat);
+void gaim_blist_remove_chat(GaimBlistChat *chat);
 
 /**
  * Removes a group from the buddy list and frees the memory allocated to it and to
@@ -384,7 +434,7 @@
  *
  * @param group   The group to be removed
  */
-void gaim_blist_remove_group(struct group *group);
+void gaim_blist_remove_group(GaimGroup *group);
 
 /**
  * Returns the alias of a buddy.
@@ -392,7 +442,7 @@
  * @param buddy   The buddy whose name will be returned.
  * @return        The alias (if set), server alias (if option is set), or NULL.
  */
-char *gaim_get_buddy_alias_only(struct buddy *buddy);
+const char *gaim_get_buddy_alias_only(GaimBuddy *buddy);
 
 
 /**
@@ -401,7 +451,7 @@
  * @param buddy   The buddy whose name will be returned.
  * @return        The alias (if set), server alias (if option is set), screenname, or "Unknown"
  */
-char *gaim_get_buddy_alias(struct buddy *buddy);
+const char *gaim_get_buddy_alias(GaimBuddy *buddy);
 
 /**
  * Finds the buddy struct given a screenname and an account
@@ -411,7 +461,7 @@
  * @param account The account this buddy belongs to
  * @return        The buddy or NULL if the buddy does not exist
  */
-struct buddy *gaim_find_buddy(GaimAccount *account, const char *name);
+GaimBuddy *gaim_find_buddy(GaimAccount *account, const char *name);
 
 /**
  * Finds all buddies struct given a screenname and an account
@@ -430,7 +480,16 @@
  * @param name    The groups name
  * @return        The group or NULL if the group does not exist
  */
-struct group *gaim_find_group(const char *name);   
+GaimGroup *gaim_find_group(const char *name);
+
+/**
+ * Finds a contact
+ *
+ * @param group   The group to look in
+ * @param name    The name to look for
+ * @return        The contact or NULL if the contact does not exist
+ */
+GaimContact *gaim_find_contact(GaimGroup *group, const char *name);
 
 /**
  * Finds a chat by name.
@@ -439,7 +498,7 @@
  *
  * @return The chat, or @c NULL if the chat does not exist.
  */
-struct chat *gaim_blist_find_chat(GaimAccount *account, const char *name);
+GaimBlistChat *gaim_blist_find_chat(GaimAccount *account, const char *name);
 
 /**
  * Returns the group of which the chat is a member.
@@ -448,7 +507,7 @@
  *
  * @return The parent group, or @c NULL if the chat is not in a group.
  */
-struct group *gaim_blist_chat_get_group(struct chat *chat);
+GaimGroup *gaim_blist_chat_get_group(GaimBlistChat *chat);
 
 /**
  * Returns the group of which the buddy is a member.
@@ -456,7 +515,7 @@
  * @param buddy   The buddy
  * @return        The group or NULL if the buddy is not in a group
  */
-struct group *gaim_find_buddys_group(struct buddy *buddy);
+GaimGroup *gaim_find_buddys_group(GaimBuddy *buddy);
 
 
 /**
@@ -465,7 +524,7 @@
  * @param group   The group
  * @return        A list of gaim_accounts
  */
-GSList *gaim_group_get_accounts(struct group *g);
+GSList *gaim_group_get_accounts(GaimGroup *g);
 
 /**
  * Determines whether an account owns any buddies in a given group
@@ -473,7 +532,7 @@
  * @param g       The group to search through.
  * @param account The account.
  */
-gboolean gaim_group_on_account(struct group *g, GaimAccount *account);
+gboolean gaim_group_on_account(GaimGroup *g, GaimAccount *account);
 
 /**
  * Called when an account gets signed on.  Tells the UI to update all the
@@ -488,7 +547,7 @@
  * Called when an account gets signed off.  Sets the presence of all the buddies to 0
  * and tells the UI to update them.
  *
- * @param account   The account 
+ * @param account   The account
  */
 void gaim_blist_remove_account(GaimAccount *account);
 
@@ -500,7 +559,7 @@
  * @param offline Count buddies in offline accounts
  * @return The number of buddies in the group
  */
-int gaim_blist_get_group_size(struct group *group, gboolean offline);
+int gaim_blist_get_group_size(GaimGroup *group, gboolean offline);
 
 /**
  * Determines the number of online buddies in a group
@@ -508,7 +567,7 @@
  * @param group The group
  * @return The number of online buddies in the group, or 0 if the group is NULL
  */
-int gaim_blist_get_group_online_count(struct group *group);
+int gaim_blist_get_group_online_count(GaimGroup *group);
 
 /*@}*/
 
@@ -543,7 +602,7 @@
  * @param key    The key used to retrieve the data
  * @param value  The data to set
  */
-void gaim_group_set_setting(struct group *g, const char *key, const char *value);
+void gaim_group_set_setting(GaimGroup *g, const char *key, const char *value);
 
 /**
  * Retrieves data from the XML buddy list set by gaim_group_set_setting())
@@ -552,7 +611,7 @@
  * @param key    The key to retrieve the data with
  * @return       The associated data or NULL if no data is associated
  */
-char *gaim_group_get_setting(struct group *g, const char *key);
+char *gaim_group_get_setting(GaimGroup *g, const char *key);
 
 /**
  * Associates some data with the chat in the xml buddy list
@@ -561,7 +620,7 @@
  * @param key    The key used to retrieve the data
  * @param value  The data to set
  */
-void gaim_chat_set_setting(struct chat *c, const char *key, const char *value);
+void gaim_blist_chat_set_setting(GaimBlistChat *c, const char *key, const char *value);
 
 /**
  * Retrieves data from the XML buddy list set by gaim_chat_set_setting())
@@ -570,7 +629,7 @@
  * @param key    The key to retrieve the data with
  * @return       The associated data or NULL if no data is associated
  */
-char *gaim_chat_get_setting(struct chat *c, const char *key);
+char *gaim_blist_chat_get_setting(GaimBlistChat *c, const char *key);
 
 /**
  * Associates some data with the buddy in the xml buddy list
@@ -579,7 +638,7 @@
  * @param key    The key used to retrieve the data
  * @param value  The data to set
  */
-void gaim_buddy_set_setting(struct buddy *b, const char *key, const char *value);
+void gaim_buddy_set_setting(GaimBuddy *b, const char *key, const char *value);
 
 /**
  * Retrieves data from the XML buddy list set by gaim_buddy_set_setting())
@@ -588,7 +647,7 @@
  * @param key    The key to retrieve the data with
  * @return       The associated data or NULL if no data is associated
  */
-char *gaim_buddy_get_setting(struct buddy *b, const char *key);
+char *gaim_buddy_get_setting(GaimBuddy *b, const char *key);
 
 /*@}*/
 
@@ -641,4 +700,4 @@
 }
 #endif
 
-#endif /* _LIST_H_ */
+#endif /* _BLIST_H_ */
--- a/src/connection.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/connection.c	Tue Sep 02 03:41:10 2003 +0000
@@ -305,7 +305,7 @@
 	}
 
 	if (gc->state == GAIM_CONNECTED) {
-		GaimBlistNode *gnode,*bnode;
+		GaimBlistNode *gnode,*cnode,*bnode;
 		GList *wins;
 		GList *add_buds=NULL;
 
@@ -352,9 +352,15 @@
 		for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
 			if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 				continue;
-			for(bnode = gnode->child; bnode; bnode = bnode->next) {
-				if(GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
-					struct buddy *b = (struct buddy *)bnode;
+			for(cnode = gnode->child; cnode; cnode = cnode->next) {
+				if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
+					continue;
+				for(bnode = cnode->child; bnode; bnode = bnode->next) {
+					GaimBuddy *b;
+					if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+						continue;
+
+					b = (GaimBuddy *)bnode;
 					if(b->account == gc->account) {
 						add_buds = g_list_append(add_buds, b->name);
 					}
--- a/src/conversation.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/conversation.c	Tue Sep 02 03:41:10 2003 +0000
@@ -1195,7 +1195,7 @@
 gaim_conversation_autoset_title(GaimConversation *conv)
 {
 	GaimAccount *account;
-	struct buddy *b;
+	GaimBuddy *b;
 	const char *text, *name;
 
 	g_return_if_fail(conv != NULL);
@@ -1437,7 +1437,7 @@
 	GaimAccount *account;
 	GaimConversationUiOps *ops;
 	GaimWindow *win;
-	struct buddy *b;
+	GaimBuddy *b;
 	GaimUnseenState unseen;
 	/* int logging_font_options = 0; */
 
@@ -1471,7 +1471,7 @@
 			if (who == NULL) {
 				if (flags & GAIM_MESSAGE_SEND) {
 					b = gaim_find_buddy(account,
-										gaim_account_get_username(account));
+							gaim_account_get_username(account));
 
 					if (b != NULL && strcmp(b->name, gaim_get_buddy_alias(b)))
 						who = gaim_get_buddy_alias(b);
@@ -2270,8 +2270,8 @@
 	type = gaim_conversation_get_type(conv);
 
 	if (type == GAIM_CONV_IM) {
-		struct buddy *b;
-		struct group *grp = NULL;
+		GaimBuddy *b;
+		GaimGroup *grp = NULL;
 		GList *wins, *convs;
 
 		b = gaim_find_buddy(gaim_conversation_get_account(conv),
@@ -2284,8 +2284,8 @@
 		for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) {
 			GaimWindow *win2;
 			GaimConversation *conv2;
-			struct buddy *b2;
-			struct group *g2 = NULL;
+			GaimBuddy *b2;
+			GaimGroup *g2 = NULL;
 
 			win2 = (GaimWindow *)wins->data;
 
@@ -2313,8 +2313,8 @@
 		conv_placement_new_window(conv);
 	}
 	else if (type == GAIM_CONV_CHAT) {
-		struct chat *chat;
-		struct group *group = NULL;
+		GaimBlistChat *chat;
+		GaimGroup *group = NULL;
 		GList *wins, *convs;
 
 		chat = gaim_blist_find_chat(gaim_conversation_get_account(conv),
@@ -2327,8 +2327,8 @@
 		for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) {
 			GaimWindow *win2;
 			GaimConversation *conv2;
-			struct chat *chat2;
-			struct group *group2 = NULL;
+			GaimBlistChat *chat2;
+			GaimGroup *group2 = NULL;
 
 			win2 = (GaimWindow *)wins->data;
 
--- a/src/dialogs.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/dialogs.c	Tue Sep 02 03:41:10 2003 +0000
@@ -379,16 +379,16 @@
 }
 
 static void
-do_remove_chat(struct chat *chat)
+do_remove_chat(GaimBlistChat *chat)
 {
 	gaim_blist_remove_chat(chat);
 	gaim_blist_save();
 }
 
 static void
-do_remove_buddy(struct buddy *b)
+do_remove_buddy(GaimBuddy *b)
 {
-	struct group *g;
+	GaimGroup *g;
 	GaimConversation *c;
 	gchar *name;
 	GaimAccount *account;
@@ -414,33 +414,45 @@
 	g_free(name);
 }
 
-void do_remove_group(struct group *g)
+void do_remove_group(GaimGroup *g)
 {
-	GaimBlistNode *b = ((GaimBlistNode*)g)->child;
-	while (b) {
-		if(GAIM_BLIST_NODE_IS_BUDDY(b)) {
-			struct buddy *bd = (struct buddy *)b;
-			GaimConversation *c = gaim_find_conversation_with_account(bd->name, bd->account);
-			if (gaim_account_is_connected(bd->account)) {
-				serv_remove_buddy(bd->account->gc, bd->name, g->name);
-				gaim_blist_remove_buddy(bd);
-
-				if (c != NULL)
-					gaim_conversation_update(c, GAIM_CONV_UPDATE_REMOVE);
+	GaimBlistNode *cnode, *bnode;
+	cnode = ((GaimBlistNode*)g)->child;
+	while(cnode) {
+		if(GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
+			bnode = cnode->child;
+			cnode = cnode->next;
+			while(bnode) {
+				GaimBuddy *b;
+				if(GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
+					b = (GaimBuddy*)bnode;
+					bnode = bnode->next;
+					GaimConversation *c = gaim_find_conversation_with_account(b->name, b->account);
+					if(gaim_account_is_connected(b->account)) {
+						serv_remove_buddy(b->account->gc, b->name, g->name);
+						gaim_blist_remove_buddy(b);
+						if(c)
+							gaim_conversation_update(c,
+									GAIM_CONV_UPDATE_REMOVE);
+					}
+				} else {
+					bnode = bnode->next;
+				}
 			}
-		} else if(GAIM_BLIST_NODE_IS_CHAT(b)) {
-			struct chat *chat = (struct chat *)b;
-			if (gaim_account_is_connected(chat->account)) {
+		} else if(GAIM_BLIST_NODE_IS_CHAT(cnode)) {
+			GaimBlistChat *chat = (GaimBlistChat *)cnode;
+			cnode = cnode->next;
+			if(gaim_account_is_connected(chat->account))
 				gaim_blist_remove_chat(chat);
-			}
+		} else {
+			cnode = cnode->next;
 		}
-		b = b->next;
 	}
 	gaim_blist_remove_group(g);
 	gaim_blist_save();
 }
 
-void show_confirm_del(struct buddy *b)
+void show_confirm_del(GaimBuddy *b)
 {
 	char *text;
 	if (!b)
@@ -455,9 +467,9 @@
 	g_free(text);
 }
 
-void show_confirm_del_chat(struct chat *chat)
+void show_confirm_del_blist_chat(GaimBlistChat *chat)
 {
-	char *name = gaim_chat_get_display_name(chat);
+	char *name = gaim_blist_chat_get_display_name(chat);
 	char *text = g_strdup_printf(_("You are about to remove the chat %s from your buddy list.  Do you want to continue?"), name);
 
 	gaim_request_action(NULL, NULL, _("Remove Chat"), text, -1, chat, 2,
@@ -468,7 +480,7 @@
 	g_free(text);
 }
 
-void show_confirm_del_group(struct group *g)
+void show_confirm_del_group(GaimGroup *g)
 {
 	char *text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list.  Do you want to continue?"),
 			       g->name);
@@ -777,8 +789,8 @@
 {
 	const char *grp, *who, *whoalias;
 	GaimConversation *c;
-	struct buddy *b;
-	struct group *g;
+	GaimBuddy *b;
+	GaimGroup *g;
 	void *icon_data;
 	void *icon_data2;
 	int icon_len;
@@ -795,7 +807,7 @@
 			gaim_blist_add_group(g, NULL);
 		}
 		b = gaim_buddy_new(a->gc->account, who, whoalias);
-		gaim_blist_add_buddy(b, g, NULL);
+		gaim_blist_add_buddy(b, NULL, g, NULL);
 		serv_add_buddy(a->gc, who);
 
 		if (c != NULL)
@@ -819,7 +831,7 @@
 {
 	GList *tmp = NULL;
 	char *tmp2;
-	struct group *g;
+	GaimGroup *g;
 
 	GaimBlistNode *gnode = gaim_get_blist()->root;
 
@@ -829,7 +841,7 @@
 	} else {
 		while (gnode) {
 			if(GAIM_BLIST_NODE_IS_GROUP(gnode)) {
-				g = (struct group *)gnode;
+				g = (GaimGroup *)gnode;
 				tmp2 = g->name;
 				tmp = g_list_append(tmp, tmp2);
 			}
@@ -848,7 +860,7 @@
 static void
 add_group_cb(GaimConnection *gc, const char *group_name)
 {
-	struct group *g;
+	GaimGroup *g;
 
 	g = gaim_group_new(group_name);
 	gaim_blist_add_group(g, NULL);
@@ -994,8 +1006,8 @@
 			g_free, g_free);
 	GList *tmp;
 
-	struct chat *chat;
-	struct group *group;
+	GaimBlistChat *chat;
+	GaimGroup *group;
 	const char *group_name;
 
 	for(tmp = ac->entries; tmp; tmp = tmp->next) {
@@ -1011,7 +1023,7 @@
 		}
 	}
 
-	chat = gaim_chat_new(ac->account, gtk_entry_get_text(GTK_ENTRY(ac->alias_entry)), components);
+	chat = gaim_blist_chat_new(ac->account, gtk_entry_get_text(GTK_ENTRY(ac->alias_entry)), components);
 
 	group_name = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ac->group_combo)->entry));
 	if (!(group = gaim_find_group(group_name))) {
@@ -1239,7 +1251,7 @@
 	gtk_option_menu_set_history(GTK_OPTION_MENU(ac->account_menu), place);
 }
 
-void show_add_chat(GaimAccount *account, struct group *group) {
+void show_add_chat(GaimAccount *account, GaimGroup *group) {
     struct addchat *ac = g_new0(struct addchat, 1);
     struct gaim_gtk_buddy_list *gtkblist;
     GList *c;
@@ -1255,18 +1267,18 @@
     gtkblist = GAIM_GTK_BLIST(gaim_get_blist());
 
     if (account) {
-	ac->account = account;
-    } else {
-	/* Select an account with chat capabilities */
-	for (c = gaim_connections_get_all(); c != NULL; c = c->next) {
-	    gc = c->data;
-
-	    if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat) {
-		ac->account = gc->account;
-		break;
-	    }
+		ac->account = account;
+	} else {
+		/* Select an account with chat capabilities */
+		for (c = gaim_connections_get_all(); c != NULL; c = c->next) {
+			gc = c->data;
+
+			if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat) {
+				ac->account = gc->account;
+				break;
+			}
+		}
 	}
-    }
 
     if (!ac->account) {
 		gaim_notify_error(NULL, NULL,
@@ -2963,14 +2975,14 @@
 }
 
 static void
-alias_chat_cb(struct chat *chat, const char *new_alias)
+alias_chat_cb(GaimBlistChat *chat, const char *new_alias)
 {
 	gaim_blist_alias_chat(chat, new_alias);
 	gaim_blist_save();
 }
 
 void
-alias_dialog_chat(struct chat *chat)
+alias_dialog_blist_chat(GaimBlistChat *chat)
 {
 	gaim_request_input(NULL, _("Alias Chat"), _("Alias chat"),
 					   _("Please enter an aliased name for this chat."),
@@ -2980,7 +2992,7 @@
 }
 
 static void
-alias_buddy_cb(struct buddy *buddy, GaimRequestFields *fields)
+alias_buddy_cb(GaimBuddy *buddy, GaimRequestFields *fields)
 {
 	const char *alias;
 
@@ -2993,7 +3005,7 @@
 }
 
 void
-alias_dialog_bud(struct buddy *b)
+alias_dialog_bud(GaimBuddy *b)
 {
 	GaimRequestFields *fields;
 	GaimRequestFieldGroup *group;
@@ -3487,13 +3499,13 @@
 /*  The dialog for renaming groups                                        */
 /*------------------------------------------------------------------------*/
 
-static void do_rename_group(struct group *g, const char *new_name)
+static void do_rename_group(GaimGroup *g, const char *new_name)
 {
 	gaim_blist_rename_group(g, new_name);
 	gaim_blist_save();
 }
 
-void show_rename_group(GtkWidget *unused, struct group *g)
+void show_rename_group(GtkWidget *unused, GaimGroup *g)
 {
 	gaim_request_input(NULL, _("Rename Group"), _("New group name"),
 					   _("Please enter a new name for the selected group."),
--- a/src/gaim.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/gaim.h	Tue Sep 02 03:41:10 2003 +0000
@@ -43,9 +43,9 @@
 extern void show_find_email(GaimConnection *);
 extern void show_find_info(GaimConnection *);
 extern void show_set_info(GaimConnection *);
-extern void show_confirm_del(struct buddy *);
-extern void show_confirm_del_group(struct group *);
-extern void show_confirm_del_chat(struct chat *);
+extern void show_confirm_del(GaimBuddy *);
+extern void show_confirm_del_group(GaimGroup *);
+extern void show_confirm_del_blist_chat(GaimBlistChat *);
 
 /* Functions in gaimrc.c */
 extern gint sort_awaymsg_list(gconstpointer, gconstpointer);
--- a/src/gtkblist.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/gtkblist.h	Tue Sep 02 03:41:10 2003 +0000
@@ -54,8 +54,8 @@
 
 	GtkWidget *treeview;            /**< It's a treeview... d'uh. */
 	GtkTreeStore *treemodel;        /**< This is the treemodel.  */
-	GtkTreeViewColumn *idle_column, 
-		*warning_column, 
+	GtkTreeViewColumn *idle_column,
+		*warning_column,
 		*buddy_icon_column;
 
 	GtkItemFactory *ift;
@@ -68,7 +68,7 @@
 
 	guint      timeout;              /**< The timeout for the tooltip. */
 	GdkRectangle rect;               /**< This is the bounding rectangle of the
-					       cell we're currently hovering over.  This is 
+					       cell we're currently hovering over.  This is
 					       used for tooltips. */
 	GtkWidget *tipwindow;            /**< The window used by the tooltip */
 
@@ -99,7 +99,7 @@
  * Returns the base image to represent the account, based on the currently selected theme
  *
  * @param account  The account.
- * 
+ *
  * @return         The icon
  */
 GdkPixbuf *create_prpl_icon(GaimAccount *account);
@@ -120,8 +120,8 @@
 
 /**
  * Useful for the docklet plugin and also for the win32 tray icon
- * This is called when one of those is clicked--it will show/hide the 
- * buddy list/login window--depending on which is active 
+ * This is called when one of those is clicked--it will show/hide the
+ * buddy list/login window--depending on which is active
  */
 void gaim_gtk_blist_docklet_toggle();
 void gaim_gtk_blist_docklet_add();
--- a/src/gtkconv.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/gtkconv.c	Tue Sep 02 03:41:10 2003 +0000
@@ -456,7 +456,7 @@
 add_cb(GtkWidget *widget, GaimConversation *conv)
 {
 	GaimConnection *gc;
-	struct buddy *b;
+	GaimBuddy *b;
 	const char *name;
 
 	gc   = gaim_conversation_get_gc(conv);
@@ -734,7 +734,7 @@
 {
 	GaimWindow *win = (GaimWindow *)data;
 	GaimConversation *conv;
-	struct buddy *b;
+	GaimBuddy *b;
 
 	conv = gaim_window_get_active_conversation(win);
 
@@ -991,7 +991,7 @@
 menu_chat_add_cb(GtkWidget *w, GaimConversation *conv)
 {
 	GaimConnection *gc;
-	struct buddy *b;
+	GaimBuddy *b;
 	char *name;
 
 	gc   = gaim_conversation_get_gc(conv);
@@ -1468,9 +1468,8 @@
 		if (gaim_im_get_type_again_timeout(im))
 			gaim_im_stop_type_again_timeout(im);
 
-		/* XXX The (char *) should go away! Somebody add consts to stuff! */
 		serv_send_typing(gaim_conversation_get_gc(conv),
-						 (char *)gaim_conversation_get_name(conv),
+						 gaim_conversation_get_name(conv),
 						 GAIM_NOT_TYPING);
 	}
 	else {
@@ -2462,9 +2461,7 @@
 static GList *
 generate_invite_user_names(GaimConnection *gc)
 {
-	GaimBlistNode *gnode,*bnode;
-	struct group *g;
-	struct buddy *buddy;
+	GaimBlistNode *gnode,*cnode,*bnode;
 	static GList *tmp = NULL;
 
 	if (tmp)
@@ -2476,14 +2473,21 @@
 		for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
 			if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 				continue;
-			g = (struct group *)gnode;
-			for(bnode = gnode->child; bnode; bnode = bnode->next) {
-				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+			for(cnode = gnode->child; cnode; cnode = cnode->next) {
+				if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 					continue;
-				buddy = (struct buddy *)bnode;
-
-				if (buddy->account == gc->account && GAIM_BUDDY_IS_ONLINE(buddy))
-					tmp = g_list_append(tmp, buddy->name);
+				for(bnode = cnode->child; bnode; bnode = bnode->next) {
+					GaimBuddy *buddy;
+
+					if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+						continue;
+
+					buddy = (GaimBuddy *)bnode;
+
+					if (buddy->account == gc->account &&
+							GAIM_BUDDY_IS_ONLINE(buddy))
+						tmp = g_list_append(tmp, buddy->name);
+				}
 			}
 		}
 	}
@@ -3637,14 +3641,19 @@
 
 	if (sd->target == gdk_atom_intern("GAIM_BLIST_NODE", FALSE)) {
 		GaimBlistNode *n = NULL;
+		GaimBuddy *b;
 		memcpy(&n, sd->data, sizeof(n));
 
-		if (!GAIM_BLIST_NODE_IS_BUDDY(n))
+		if (GAIM_BLIST_NODE_IS_CONTACT(n))
+			b = gaim_contact_get_priority_buddy((GaimContact*)n);
+		else if (GAIM_BLIST_NODE_IS_BUDDY(n))
+			b = (GaimBuddy*)n;
+		else
 			return;
 
 		c = gaim_conversation_new(GAIM_CONV_IM,
-								  ((struct buddy *)n)->account,
-								  ((struct buddy *)n)->name);
+								  ((GaimBuddy *)n)->account,
+								  ((GaimBuddy *)n)->name);
 
 		gaim_window_add_conversation(win, c);
 	}
@@ -4847,7 +4856,7 @@
 	GaimGtkConversation *gtkconv;
 	GaimAccount *account;
 	const char *name;
-	struct buddy *b;
+	GaimBuddy *b;
 
 	gtkconv = GAIM_GTK_CONVERSATION(conv);
 	name = gaim_conversation_get_name(conv);
@@ -5198,7 +5207,7 @@
 	GError *err = NULL;
 	gboolean animate = TRUE;
 
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 
 	void *data;
 	int len, delay;
--- a/src/gtkpounce.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/gtkpounce.c	Tue Sep 02 03:41:10 2003 +0000
@@ -710,7 +710,7 @@
 }
 
 static void
-new_pounce_cb(GtkWidget *w, struct buddy *b)
+new_pounce_cb(GtkWidget *w, GaimBuddy *b)
 {
 	if (b == NULL)
 		gaim_gtkpounce_dialog_show(NULL, NULL, NULL);
--- a/src/log.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/log.c	Tue Sep 02 03:41:10 2003 +0000
@@ -171,7 +171,7 @@
 	return fd;
 }
 
-static FILE *open_system_log_file(char *name)
+static FILE *open_system_log_file(const char *name)
 {
 	int x;
 
@@ -232,7 +232,7 @@
 }
 
 void system_log(enum log_event what, GaimConnection *gc,
-				struct buddy *who, int why)
+				GaimBuddy *who, int why)
 {
 	GaimAccount *account = NULL;
 	FILE *fd;
@@ -255,7 +255,7 @@
 
 	if (gaim_prefs_get_bool("/gaim/gtk/logging/individual_logs")) {
 		if (why & OPT_LOG_MY_SIGNON)
-			fd = open_system_log_file(gc ? (char *)gaim_account_get_username(account) : NULL);
+			fd = open_system_log_file(gc ? gaim_account_get_username(account) : NULL);
 		else
 			fd = open_system_log_file(who->name);
 	} else
--- a/src/log.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/log.h	Tue Sep 02 03:41:10 2003 +0000
@@ -57,7 +57,7 @@
 extern GList *log_conversations;
 
 FILE *open_log_file (const char *, int);
-void system_log(enum log_event, GaimConnection *, struct buddy *, int);
+void system_log(enum log_event, GaimConnection *, GaimBuddy *, int);
 void rm_log(struct log_conversation *);
 struct log_conversation *find_log_info(const char *);
 void update_log_convs();
--- a/src/prefs.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/prefs.c	Tue Sep 02 03:41:10 2003 +0000
@@ -102,8 +102,6 @@
 	gaim_prefs_add_none("/plugins/lopl");
 	gaim_prefs_add_none("/plugins/prpl");
 
-	/* XXX: this is where you would want to put prefs declarations */
-
 	/* Away */
 	gaim_prefs_add_none("/core/away");
 	gaim_prefs_add_bool("/core/away/away_when_idle", TRUE);
--- a/src/protocols/gg/gg.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/gg/gg.c	Tue Sep 02 03:41:10 2003 +0000
@@ -1,6 +1,6 @@
 /*
  * gaim - Gadu-Gadu Protocol Plugin
- * $Id: gg.c 7147 2003-08-25 15:42:39Z lschiere $
+ * $Id: gg.c 7221 2003-09-02 03:41:10Z faceprint $
  *
  * Copyright (C) 2001 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
  * 
@@ -251,7 +251,7 @@
 {
 	GList *m = NULL;
 	struct proto_buddy_menu *pbm;
-	struct buddy *b = gaim_find_buddy(gc->account, who);
+	GaimBuddy *b = gaim_find_buddy(gc->account, who);
 	static char buf[AGG_BUF_LEN];
 
 	if (!b) {
@@ -773,8 +773,8 @@
 		gaim_debug(GAIM_DEBUG_MISC, "gg",
 				   "import_buddies_server_results: uin: %s\n", name);
 		if (!gaim_find_buddy(gc->account, name)) {
-			struct buddy *b;
-			struct group *g;
+			GaimBuddy *b;
+			GaimGroup *g;
 			/* Default group if none specified on server */
 			gchar *group = g_strdup("Gadu-Gadu");
 			if (strlen(data_tbl[5])) {
@@ -791,7 +791,7 @@
 				gaim_blist_add_group(g, NULL);
 			}
 			b = gaim_buddy_new(gc->account, name, strlen(show) ? show : NULL);
-			gaim_blist_add_buddy(b,g,NULL);
+			gaim_blist_add_buddy(b,NULL,g,NULL);
 			gaim_blist_save();
 			g_free(group);
 		}
@@ -1006,7 +1006,7 @@
 	gchar *u = gg_urlencode(gaim_account_get_username(gc->account));
 	gchar *p = gg_urlencode(gaim_account_get_password(gc->account));
 
-	GaimBlistNode *gnode, *bnode;
+	GaimBlistNode *gnode, *cnode, *bnode;
 
 	he->gc = gc;
 	he->type = AGG_HTTP_USERLIST_EXPORT;
@@ -1018,42 +1018,46 @@
 	g_free(p);
 
 	for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
-		struct group *g = (struct group *)gnode;
+		GaimGroup *g = (GaimGroup *)gnode;
 		int num_added=0;
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(bnode = gnode->child; bnode; bnode = bnode->next) {
-			struct buddy *b = (struct buddy *)bnode;
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
+				continue;
+			for(bnode = cnode->child; bnode; bnode = bnode->next) {
+				GaimBuddy *b = (GaimBuddy *)bnode;
 
-			if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-				continue;
+				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+					continue;
 
-			if(b->account == gc->account) {
-				gchar *newdata;
-				/* GG Number */
-				gchar *name = gg_urlencode(b->name);
-				/* GG Pseudo */
-				gchar *show = gg_urlencode(b->alias ? b->alias : b->name);
-				/* Group Name */
-				gchar *gname = gg_urlencode(g->name);
+				if(b->account == gc->account) {
+					gchar *newdata;
+					/* GG Number */
+					gchar *name = gg_urlencode(b->name);
+					/* GG Pseudo */
+					gchar *show = gg_urlencode(b->alias ? b->alias : b->name);
+					/* Group Name */
+					gchar *gname = gg_urlencode(g->name);
 
-				ptr = he->request;
-				newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s",
-						show, show, show, show, "", gname, name);
+					ptr = he->request;
+					newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s",
+							show, show, show, show, "", gname, name);
 
-				if(num_added > 0)
-					he->request = g_strconcat(ptr, "%0d%0a", newdata, NULL);
-				else
-					he->request = g_strconcat(ptr, newdata, NULL);
+					if(num_added > 0)
+						he->request = g_strconcat(ptr, "%0d%0a", newdata, NULL);
+					else
+						he->request = g_strconcat(ptr, newdata, NULL);
 
-				num_added++;
+					num_added++;
+
+					g_free(newdata);
+					g_free(ptr);
 
-				g_free(newdata);
-				g_free(ptr);
-
-				g_free(gname);
-				g_free(show);
-				g_free(name);
+					g_free(gname);
+					g_free(show);
+					g_free(name);
+				}
 			}
 		}
 	}
@@ -1254,12 +1258,12 @@
 	}
 }
 
-static const char *agg_list_icon(GaimAccount *a, struct buddy *b)
+static const char *agg_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "gadu-gadu";
 }
 
-static void agg_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void agg_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	int status;
 	if (b->present == GAIM_BUDDY_OFFLINE)
--- a/src/protocols/irc/irc.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/irc/irc.c	Tue Sep 02 03:41:10 2003 +0000
@@ -36,8 +36,8 @@
 
 static void irc_buddy_append(char *name, struct irc_buddy *ib, GString *string);
 
-static const char *irc_blist_icon(GaimAccount *a, struct buddy *b);
-static void irc_blist_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne);
+static const char *irc_blist_icon(GaimAccount *a, GaimBuddy *b);
+static void irc_blist_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne);
 static GList *irc_away_states(GaimConnection *gc);
 /* static GList *irc_chat_info(GaimConnection *gc); */
 static void irc_login(GaimAccount *account);
@@ -91,12 +91,12 @@
 	g_string_append_printf(string, "%s ", name);
 }
 
-static const char *irc_blist_icon(GaimAccount *a, struct buddy *b)
+static const char *irc_blist_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "irc";
 }
 
-static void irc_blist_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void irc_blist_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	if (b->present == GAIM_BUDDY_OFFLINE)
 		*se = "offline";
--- a/src/protocols/irc/msgs.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/irc/msgs.c	Tue Sep 02 03:41:10 2003 +0000
@@ -481,7 +481,7 @@
 static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc)
 {
 	GaimConnection *gc = gaim_account_get_connection(irc->account);
-	struct buddy *buddy = gaim_find_buddy(irc->account, name);
+	GaimBuddy *buddy = gaim_find_buddy(irc->account, name);
 
 	if (!gc || !buddy)
 		return;
--- a/src/protocols/jabber/jabber.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/jabber/jabber.c	Tue Sep 02 03:41:10 2003 +0000
@@ -959,7 +959,7 @@
  */
 static void jabber_remove_gaim_buddy(GaimConnection *gc, const char *buddyname)
 {
-	struct buddy *b;
+	GaimBuddy *b;
 
 	if ((b = gaim_find_buddy(gc->account, buddyname)) != NULL) {
 		gaim_debug(GAIM_DEBUG_INFO, "jabber",
@@ -1492,7 +1492,7 @@
 static void jabber_handlepresence(gjconn gjc, jpacket p)
 {
 	char *to, *from, *type;
-	struct buddy *b = NULL;
+	GaimBuddy *b = NULL;
 	gaim_jid gjid;
 	char *buddy;
 	xmlnode y;
@@ -1787,7 +1787,7 @@
 	xmlnode g;
 	char *who, *name, *sub, *ask;
 	gaim_jid gjid;
-	struct buddy *b = NULL;
+	GaimBuddy *b = NULL;
 	struct jabber_buddy_data *jbd = NULL;
 	char *buddyname, *groupname = NULL;
 
@@ -1822,7 +1822,7 @@
 	 */
 	if (BUD_SUB_TO_PEND(sub, ask) || BUD_SUBD_TO(sub, ask)) {
 		if ((b = gaim_find_buddy(GJ_GC(gjc)->account, buddyname)) == NULL) {
-			struct group *g;
+			GaimGroup *g;
 			b = gaim_buddy_new(GJ_GC(gjc)->account, buddyname, name);
 			if (groupname) {
 				if (!(g = gaim_find_group(groupname))) {
@@ -1835,23 +1835,23 @@
 			}
 			gaim_debug(GAIM_DEBUG_INFO, "jabber",
 					   "adding buddy [4]: %s\n", buddyname);
-			gaim_blist_add_buddy(b, g, NULL);
+			gaim_blist_add_buddy(b, NULL, g, NULL);
 			gaim_blist_save();
 		} else {
 			gboolean save = FALSE;
-			struct group *c_grp = gaim_find_buddys_group(b);
+			GaimGroup *c_grp = gaim_find_buddys_group(b);
 
 			/*
 			 * If the buddy's in a new group or his/her alias is changed...
 			 */
 			if(groupname && c_grp && strcmp(c_grp->name, groupname)) {
-				struct group *g = gaim_find_group(groupname);
+				GaimGroup *g = gaim_find_group(groupname);
 				if(!g) {
 					g = gaim_group_new(groupname);
 					gaim_blist_add_group(g, NULL);
 				}
 
-				gaim_blist_add_buddy(b, g, NULL);
+				gaim_blist_add_buddy(b, NULL, g, NULL);
 				save = TRUE;
 			}
 
@@ -2563,8 +2563,8 @@
 	xmlnode x, y;
 	char *realwho;
 	gjconn gjc;
-	struct buddy *buddy = NULL;
-	struct group *buddy_group = NULL;
+	GaimBuddy *buddy = NULL;
+	GaimGroup *buddy_group = NULL;
 	const char *my_alias = NULL;
 	const char *my_group = NULL;
 
@@ -2859,12 +2859,12 @@
 		g_hash_table_foreach(jd->buddies, set_invisible_to_buddy_status, GINT_TO_POINTER(invisible));
 }
 
-static const char *jabber_list_icon(GaimAccount *a, struct buddy *b)
+static const char *jabber_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "jabber";
 }
 
-static void jabber_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void jabber_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE);
 
@@ -3326,7 +3326,7 @@
 
 }
 
-static char *jabber_tooltip_text(struct buddy *b)
+static char *jabber_tooltip_text(GaimBuddy *b)
 {
 	struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE);
 	jab_res_info jri = jabber_find_resource(b->account->gc, b->name);
@@ -3354,7 +3354,7 @@
 	return ret;
 }
 
-static char *jabber_status_text(struct buddy *b)
+static char *jabber_status_text(GaimBuddy *b)
 {
 	struct jabber_buddy_data *jbd = jabber_find_buddy(b->account->gc, b->name, FALSE);
 	char *ret = NULL;
@@ -3379,7 +3379,7 @@
 static GList *jabber_buddy_menu(GaimConnection *gc, const char *who) {
 	GList *m = NULL;
 	struct proto_buddy_menu *pbm;
-	struct buddy *b = gaim_find_buddy(gc->account, who);
+	GaimBuddy *b = gaim_find_buddy(gc->account, who);
 
 	if(b->uc == UC_ERROR)
 	{
--- a/src/protocols/msn/buddyicon.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/msn/buddyicon.c	Tue Sep 02 03:41:10 2003 +0000
@@ -204,7 +204,7 @@
 	MsnMessage *new_msg;
 	MsnSwitchBoard *swboard;
 	MsnBuddyIconXfer *buddyicon;
-	struct buddy *b;
+	GaimBuddy *b;
 	GHashTable *table;
 	const char *command;
 
--- a/src/protocols/msn/msn.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/msn/msn.c	Tue Sep 02 03:41:10 2003 +0000
@@ -270,13 +270,13 @@
  **************************************************************************/
 
 static const char *
-msn_list_icon(GaimAccount *a, struct buddy *b)
+msn_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "msn";
 }
 
 static void
-msn_list_emblems(struct buddy *b, char **se, char **sw,
+msn_list_emblems(GaimBuddy *b, char **se, char **sw,
 				 char **nw, char **ne)
 {
 	MsnUser *user;
@@ -308,7 +308,7 @@
 }
 
 static char *
-msn_status_text(struct buddy *b)
+msn_status_text(GaimBuddy *b)
 {
 	if (b->uc & UC_UNAVAILABLE)
 		return g_strdup(msn_away_get_text(MSN_AWAY_TYPE(b->uc)));
@@ -317,7 +317,7 @@
 }
 
 static char *
-msn_tooltip_text(struct buddy *b)
+msn_tooltip_text(GaimBuddy *b)
 {
 	char *text = NULL;
 	/* MsnUser *user = b->proto_data; */
@@ -403,7 +403,7 @@
 	GaimAccount *account = gaim_connection_get_account(gc);
 	MsnUser *user;
 	struct proto_buddy_menu *pbm;
-	struct buddy *b;
+	GaimBuddy *b;
 	GList *m = NULL;
 
 	b = gaim_find_buddy(gc->account, who);
@@ -1116,7 +1116,7 @@
 }
 
 static void
-msn_buddy_free(struct buddy *b)
+msn_buddy_free(GaimBuddy *b)
 {
 	if (b->proto_data != NULL) {
 		msn_user_destroy(b->proto_data);
--- a/src/protocols/msn/notification.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/msn/notification.c	Tue Sep 02 03:41:10 2003 +0000
@@ -43,9 +43,9 @@
 {
 	MsnSession *session = servconn->session;
 	GaimConnection *gc = session->account->gc;
-	struct buddy *b;
+	GaimBuddy *b;
 	MsnGroup *group = NULL;
-	struct group *g = NULL;
+	GaimGroup *g = NULL;
 	int group_id;
 
 	group_id = msn_user_get_group_id(user);
@@ -96,7 +96,7 @@
 		b = gaim_buddy_new(gc->account,
 						   msn_user_get_passport(user), NULL);
 
-		gaim_blist_add_buddy(b, g, NULL);
+		gaim_blist_add_buddy(b, NULL, g, NULL);
 	}
 
 	b->proto_data = user;
@@ -520,7 +520,7 @@
 	MsnSession *session = servconn->session;
 	GaimConnection *gc = session->account->gc;
 	const char *passport, *type, *value;
-	struct buddy *b;
+	GaimBuddy *b;
 	MsnUser *user;
 
 	if (param_count < 4)
@@ -574,7 +574,7 @@
 	GaimConnection *gc = servconn->session->account->gc;
 	int status = 0;
 	const char *state, *passport, *friend;
-	struct buddy *b;
+	GaimBuddy *b;
 
 	state    = params[1];
 	passport = params[2];
@@ -625,7 +625,7 @@
 {
 	MsnSession *session = servconn->session;
 	MsnGroup *group;
-	struct group *g;
+	GaimGroup *g;
 	const char *name;
 	int group_num, num_groups, group_id;
 
--- a/src/protocols/msn/switchboard.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/msn/switchboard.c	Tue Sep 02 03:41:10 2003 +0000
@@ -105,7 +105,7 @@
 	else {
 		const char *username;
 		GaimConversation *conv;
-		struct buddy *b;
+		GaimBuddy *b;
 		char buf[MSN_BUF_LEN];
 
 		if ((b = gaim_find_buddy(account, user)) != NULL)
--- a/src/protocols/napster/napster.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/napster/napster.c	Tue Sep 02 03:41:10 2003 +0000
@@ -511,12 +511,12 @@
 	g_free(ndata);
 }
 
-static const char* nap_list_icon(GaimAccount *a, struct buddy *b)
+static const char* nap_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "napster";
 }
 
-static void nap_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void nap_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	if (b->present == GAIM_BUDDY_OFFLINE)
 		*se = "offline";
--- a/src/protocols/oscar/oscar.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/oscar/oscar.c	Tue Sep 02 03:41:10 2003 +0000
@@ -1832,7 +1832,7 @@
 	/* Server stored icon stuff */
 	if (info->iconcsumlen) {
 		char *b16, *saved_b16;
-		struct buddy *b;
+		GaimBuddy *b;
 
 		free(bi->iconcsum);
 		bi->iconcsum = malloc(info->iconcsumlen);
@@ -2436,8 +2436,8 @@
 
 	if (g_list_find(gaim_connections_get_all(), gc)) {
 		struct oscar_data *od = gc->proto_data;
-		struct buddy *buddy = gaim_find_buddy(gc->account, data->name);
-		struct group *group = gaim_find_buddys_group(buddy);
+		GaimBuddy *buddy = gaim_find_buddy(gc->account, data->name);
+		GaimGroup *group = gaim_find_buddys_group(buddy);
 		if (buddy && group) {
 			gaim_debug(GAIM_DEBUG_INFO, "oscar",
 					   "ssi: adding buddy %s to group %s\n",
@@ -2470,7 +2470,7 @@
 
 static void gaim_auth_sendrequest(GaimConnection *gc, const char *name) {
 	struct name_data *data = g_new(struct name_data, 1);
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 	gchar *dialog_msg, *nombre;
 
 	buddy = gaim_find_buddy(gc->account, name);
@@ -2501,7 +2501,7 @@
 	if (g_list_find(gaim_connections_get_all(), gc)) {
 		struct oscar_data *od = gc->proto_data;
 #ifdef NOSSI
-		struct buddy *buddy;
+		GaimBuddy *buddy;
 		gchar message;
 		message = 0;
 		buddy = gaim_find_buddy(gc->account, data->name);
@@ -3511,7 +3511,7 @@
 
 	if (iconlen > 0) {
 		char *b16;
-		struct buddy *b = gaim_find_buddy(gc->account, sn);
+		GaimBuddy *b = gaim_find_buddy(gc->account, sn);
 		set_icon_data(gc, sn, icon, iconlen);
 		b16 = tobase16(iconcsum, iconcsumlen);
 		if (b16) {
@@ -4056,7 +4056,7 @@
 {
 	GaimConnection *gc = sess->aux_data;
 	gchar who[16], *utf8;
-	struct buddy *b;
+	GaimBuddy *b;
 	va_list ap;
 	struct aim_icq_info *info;
 
@@ -4415,7 +4415,7 @@
 static void oscar_get_away(GaimConnection *g, const char *who) {
 	struct oscar_data *od = (struct oscar_data *)g->proto_data;
 	if (od->icq) {
-		struct buddy *budlight = gaim_find_buddy(g->account, who);
+		GaimBuddy *budlight = gaim_find_buddy(g->account, who);
 		if (budlight)
 			if ((budlight->uc & 0xffff0000) >> 16)
 				aim_im_sendch2_geticqaway(od->sess, who, (budlight->uc & 0xffff0000) >> 16);
@@ -4639,8 +4639,8 @@
 	aim_add_buddy(od->sess, od->conn, name);
 #else
 	if ((od->sess->ssi.received_data) && !(aim_ssi_itemlist_exists(od->sess->ssi.local, name))) {
-		struct buddy *buddy = gaim_find_buddy(gc->account, name);
-		struct group *group = gaim_find_buddys_group(buddy);
+		GaimBuddy *buddy = gaim_find_buddy(gc->account, name);
+		GaimGroup *group = gaim_find_buddys_group(buddy);
 		if (buddy && group) {
 			gaim_debug(GAIM_DEBUG_INFO, "oscar",
 					   "ssi: adding buddy %s to group %s\n", name, group->name);
@@ -4669,8 +4669,8 @@
 #else
 	if (od->sess->ssi.received_data) {
 		while (buddies) {
-			struct buddy *buddy = gaim_find_buddy(gc->account, (const char *)buddies->data);
-			struct group *group = gaim_find_buddys_group(buddy);
+			GaimBuddy *buddy = gaim_find_buddy(gc->account, (const char *)buddies->data);
+			GaimGroup *group = gaim_find_buddys_group(buddy);
 			if (buddy && group) {
 				gaim_debug(GAIM_DEBUG_INFO, "oscar",
 						   "ssi: adding buddy %s to group %s\n", (const char *)buddies->data, group->name);
@@ -4849,7 +4849,7 @@
 					char *gname_utf8 = gaim_try_conv_to_utf8(gname);
 					char *alias = aim_ssi_getalias(sess->ssi.local, gname, curitem->name);
 					char *alias_utf8 = gaim_try_conv_to_utf8(alias);
-					struct buddy *buddy = gaim_find_buddy(gc->account, curitem->name);
+					GaimBuddy *buddy = gaim_find_buddy(gc->account, curitem->name);
 					/* Should gname be freed here? -- elb */
 					/* Not with the current code, but that might be cleaner -- med */
 					free(alias);
@@ -4860,7 +4860,7 @@
 							buddy->alias = g_strdup(alias_utf8);
 						}
 					} else {
-						struct group *g;
+						GaimGroup *g;
 						buddy = gaim_buddy_new(gc->account, curitem->name, alias_utf8);
 
 						if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
@@ -4870,7 +4870,7 @@
 
 						gaim_debug(GAIM_DEBUG_INFO, "oscar",
 								   "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans"));
-						gaim_blist_add_buddy(buddy, g, NULL);
+						gaim_blist_add_buddy(buddy, NULL, g, NULL);
 						export = TRUE;
 					}
 					free(gname_utf8);
@@ -4935,9 +4935,9 @@
 		gaim_blist_save();
 
 	{ /* Add from local list to server list */
-		GaimBlistNode *gnode, *bnode;
-		struct group *group;
-		struct buddy *buddy;
+		GaimBlistNode *gnode, *cnode, *bnode;
+		GaimGroup *group;
+		GaimBuddy *buddy;
 		struct gaim_buddy_list *blist;
 		GSList *cur;
 
@@ -4946,37 +4946,42 @@
 			for (gnode = blist->root; gnode; gnode = gnode->next) {
 				if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 					continue;
-				group = (struct group *)gnode;
-				for (bnode = gnode->child; bnode; bnode = bnode->next) {
-					if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+				group = (GaimGroup *)gnode;
+				for (cnode = gnode->child; cnode; cnode = cnode->next) {
+					if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 						continue;
-					buddy = (struct buddy *)bnode;
-					if (buddy->account == gc->account) {
-						gchar *servernick = gaim_buddy_get_setting(buddy, "servernick");
-						if (servernick) {
-							serv_got_alias(gc, buddy->name, servernick);
-							g_free(servernick);
-						}
-						if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
-							/* Store local alias on server */
-							char *alias = aim_ssi_getalias(sess->ssi.local, group->name, buddy->name);
-							if (!alias && buddy->alias && strlen(buddy->alias))
-								aim_ssi_aliasbuddy(sess, group->name, buddy->name, buddy->alias);
-							free(alias);
-						} else {
-							gaim_debug(GAIM_DEBUG_INFO, "oscar",
-									   "ssi: adding buddy %s from local list to server list\n", buddy->name);
-							aim_ssi_addbuddy(sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
+					for (bnode = cnode->child; bnode; bnode = bnode->next) {
+						if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+							continue;
+						buddy = (GaimBuddy *)bnode;
+						if (buddy->account == gc->account) {
+							gchar *servernick = gaim_buddy_get_setting(buddy, "servernick");
+							if (servernick) {
+								serv_got_alias(gc, buddy->name, servernick);
+								g_free(servernick);
+							}
+							if (aim_ssi_itemlist_exists(sess->ssi.local, buddy->name)) {
+								/* Store local alias on server */
+								char *alias = aim_ssi_getalias(sess->ssi.local, group->name, buddy->name);
+								if (!alias && buddy->alias && strlen(buddy->alias))
+									aim_ssi_aliasbuddy(sess, group->name, buddy->name, buddy->alias);
+								free(alias);
+							} else {
+								gaim_debug(GAIM_DEBUG_INFO, "oscar",
+										"ssi: adding buddy %s from local list to server list\n", buddy->name);
+								aim_ssi_addbuddy(sess, buddy->name, group->name, gaim_get_buddy_alias_only(buddy), NULL, NULL, 0);
+							}
 						}
 					}
 				}
 			}
+
 		/* Permit list */
 		if (gc->account->permit) {
 			for (cur=gc->account->permit; cur; cur=cur->next)
 				if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
 					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "ssi: adding permit %s from local list to server list\n", (char *)cur->data);
+							"ssi: adding permit %s from local list to server list\n", (char *)cur->data);
 					aim_ssi_addpermit(sess, cur->data);
 				}
 		}
@@ -4986,7 +4991,7 @@
 			for (cur=gc->account->deny; cur; cur=cur->next)
 				if (!aim_ssi_itemlist_finditem(sess->ssi.local, NULL, cur->data, AIM_SSI_TYPE_DENY)) {
 					gaim_debug(GAIM_DEBUG_INFO, "oscar",
-							   "ssi: adding deny %s from local list to server list\n", (char *)cur->data);
+							"ssi: adding deny %s from local list to server list\n", (char *)cur->data);
 					aim_ssi_adddeny(sess, cur->data);
 				}
 		}
@@ -5063,7 +5068,7 @@
 	char *sn, *msg;
 	gchar *dialog_msg, *nombre;
 	struct name_data *data;
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 
 	va_start(ap, fr);
 	sn = va_arg(ap, char *);
@@ -5102,7 +5107,7 @@
 	char *sn, *msg;
 	gchar *dialog_msg, *nombre;
 	struct name_data *data;
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 
 	va_start(ap, fr);
 	sn = va_arg(ap, char *);
@@ -5141,7 +5146,7 @@
 	char *sn, *msg;
 	gchar *dialog_msg, *nombre;
 	fu8_t reply;
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 
 	va_start(ap, fr);
 	sn = va_arg(ap, char *);
@@ -5177,7 +5182,7 @@
 	GaimConnection *gc = sess->aux_data;
 	va_list ap;
 	char *sn;
-	struct buddy *buddy;
+	GaimBuddy *buddy;
 
 	va_start(ap, fr);
 	sn = va_arg(ap, char *);
@@ -5344,7 +5349,7 @@
 	return 0;
 }
 
-static const char *oscar_list_icon(GaimAccount *a, struct buddy *b) {
+static const char *oscar_list_icon(GaimAccount *a, GaimBuddy *b) {
 	if (!b || (b && b->name && b->name[0] == '+')) {
 		if (a != NULL && isdigit(*gaim_account_get_username(a)))
 			return "icq";
@@ -5357,7 +5362,7 @@
 	return "aim";
 }
 
-static void oscar_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void oscar_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	char *emblems[4] = {NULL,NULL,NULL,NULL};
 	int i = 0;
@@ -5413,7 +5418,7 @@
 	*ne = emblems[3];
 }
 
-static char *oscar_tooltip_text(struct buddy *b) {
+static char *oscar_tooltip_text(GaimBuddy *b) {
 	GaimConnection *gc = b->account->gc;
 	struct oscar_data *od = gc->proto_data;
 	struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
@@ -5471,7 +5476,7 @@
 	return yay;
 }
 
-static char *oscar_status_text(struct buddy *b) {
+static char *oscar_status_text(GaimBuddy *b) {
 	GaimConnection *gc = b->account->gc;
 	struct oscar_data *od = gc->proto_data;
 	gchar *ret = NULL;
@@ -5896,7 +5901,7 @@
 		m = g_list_append(m, pbm);
 #endif
 	} else {
-		struct buddy *b = gaim_find_buddy(gc->account, who);
+		GaimBuddy *b = gaim_find_buddy(gc->account, who);
 		struct buddyinfo *bi;
 
 		if (b)
@@ -6022,29 +6027,33 @@
 {
 	struct oscar_data *od = gc->proto_data;
 	gchar *nombre, *text, *tmp;
-	GaimBlistNode *gnode,*bnode;
+	GaimBlistNode *gnode, *cnode, *bnode;
 	int num=0;
 
 	text = g_strdup(_("You are awaiting authorization from the following buddies:<BR>"));
 
 	for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
-		struct group *group = (struct group *)gnode;
+		GaimGroup *group = (GaimGroup *)gnode;
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for (bnode = gnode->child; bnode; bnode = bnode->next) {
-			struct buddy *buddy = (struct buddy *)bnode;
-			if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+		for (cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 				continue;
-			if (buddy->account == gc->account && aim_ssi_waitingforauth(od->sess->ssi.local, group->name, buddy->name)) {
-				if (gaim_get_buddy_alias_only(buddy))
-					nombre = g_strdup_printf(" %s (%s)", buddy->name, gaim_get_buddy_alias_only(buddy));
-				else
-					nombre = g_strdup_printf(" %s", buddy->name);
-				tmp = g_strdup_printf("%s<BR>%s", text, nombre);
-				g_free(text);
-				text = tmp;
-				g_free(nombre);
-				num++;
+			for (bnode = cnode->child; bnode; bnode = bnode->next) {
+				GaimBuddy *buddy = (GaimBuddy *)bnode;
+				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+					continue;
+				if (buddy->account == gc->account && aim_ssi_waitingforauth(od->sess->ssi.local, group->name, buddy->name)) {
+					if (gaim_get_buddy_alias_only(buddy))
+						nombre = g_strdup_printf(" %s (%s)", buddy->name, gaim_get_buddy_alias_only(buddy));
+					else
+						nombre = g_strdup_printf(" %s", buddy->name);
+					tmp = g_strdup_printf("%s<BR>%s", text, nombre);
+					g_free(text);
+					text = tmp;
+					g_free(nombre);
+					num++;
+				}
 			}
 		}
 	}
--- a/src/protocols/toc/toc.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/toc/toc.c	Tue Sep 02 03:41:10 2003 +0000
@@ -248,9 +248,9 @@
 
 static void toc_build_config(GaimAccount *account, char *s, int len, gboolean show)
 {
-	GaimBlistNode *gnode,*bnode;
-	struct group *g;
-	struct buddy *b;
+	GaimBlistNode *gnode, *cnode, *bnode;
+	GaimGroup *g;
+	GaimBuddy *b;
 	GSList *plist = account->permit;
 	GSList *dlist = account->deny;
 
@@ -261,19 +261,24 @@
 
 	pos += g_snprintf(&s[pos], len - pos, "m %d\n", account->perm_deny);
 	for(gnode = gaim_get_blist()->root; gnode && len > pos; gnode = gnode->next) {
-		g = (struct group *)gnode;
+		g = (GaimGroup *)gnode;
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
 		if(gaim_group_on_account(g, account)) {
 			pos += g_snprintf(&s[pos], len - pos, "g %s\n", g->name);
-			for(bnode = gnode->child; bnode && len > pos; bnode = bnode->next) {
-				b = (struct buddy *)bnode;
-				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+			for(cnode = gnode->child; cnode; cnode = cnode->next) {
+				if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 					continue;
-				if(b->account == account) {
-					pos += g_snprintf(&s[pos], len - pos, "b %s%s%s\n", b->name,
-							(show && b->alias) ? ":" : "",
-							(show && b->alias) ? b->alias : "");
+				for(bnode = gnode->child; bnode && len > pos; bnode = bnode->next) {
+					b = (GaimBuddy *)bnode;
+					if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+						continue;
+					if(b->account == account) {
+						pos += g_snprintf(&s[pos], len - pos, "b %s%s%s\n",
+								b->name,
+								(show && b->alias) ? ":" : "",
+								(show && b->alias) ? b->alias : "");
+					}
 				}
 			}
 		}
@@ -1332,10 +1337,10 @@
 	sflap_send(gc, "", 0, TYPE_KEEPALIVE);
 }
 
-static const char *toc_list_icon(GaimAccount *a, struct buddy *b)
+static const char *toc_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	if (!b || (b && b->name && b->name[0] == '+')) {
-		if (a != NULL && isdigit(*gaim_account_get_username(a))) 
+		if (a != NULL && isdigit(*gaim_account_get_username(a)))
 			return "icq";
 		else
 			return "aim";
@@ -1346,7 +1351,7 @@
 	return "aim";
 }
 
-static void toc_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void toc_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	char *emblems[4] = {NULL,NULL,NULL,NULL};
 	int i = 0;
--- a/src/protocols/yahoo/yahoo.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/yahoo/yahoo.c	Tue Sep 02 03:41:10 2003 +0000
@@ -466,8 +466,8 @@
 {
 	GSList *l = pkt->hash;
 	gboolean export = FALSE;
-	struct buddy *b;
-	struct group *g;
+	GaimBuddy *b;
+	GaimGroup *g;
 
 	while (l) {
 		char **lines;
@@ -498,7 +498,7 @@
 						gaim_blist_add_group(g, NULL);
 					}
 					b = gaim_buddy_new(gc->account, *bud, NULL);
-					gaim_blist_add_buddy(b, g, NULL);
+					gaim_blist_add_buddy(b, NULL, g, NULL);
 					export = TRUE;
 				}
 			g_strfreev(buddies);
@@ -541,7 +541,7 @@
 		else
 			serv_got_typing_stopped(gc, from);
 	} else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) {
-		struct buddy *bud = gaim_find_buddy(gc->account, from);
+		GaimBuddy *bud = gaim_find_buddy(gc->account, from);
 		void *free1=NULL, *free2=NULL;
 		if (!bud) {
 			gaim_debug(GAIM_DEBUG_WARNING, "yahoo",
@@ -1064,12 +1064,12 @@
 	g_free(yd);
 }
 
-static const char *yahoo_list_icon(GaimAccount *a, struct buddy *b)
+static const char *yahoo_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "yahoo";
 }
 
-static void yahoo_list_emblems(struct buddy *b, char **se, char **sw, char **nw, char **ne)
+static void yahoo_list_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne)
 {
 	int i = 0;
 	char *emblems[4] = {NULL,NULL,NULL,NULL};
@@ -1135,7 +1135,7 @@
 	g_free(game);
 }
 
-static char *yahoo_status_text(struct buddy *b)
+static char *yahoo_status_text(GaimBuddy *b)
 {
 	struct yahoo_data *yd = (struct yahoo_data*)b->account->gc->proto_data;
 
@@ -1153,7 +1153,7 @@
 	return NULL;
 }
 
-static char *yahoo_tooltip_text(struct buddy *b)
+static char *yahoo_tooltip_text(GaimBuddy *b)
 {
 	struct yahoo_data *yd = (struct yahoo_data*)b->account->gc->proto_data;
 	if ((b->uc & UC_UNAVAILABLE) || ((b->uc >> 2) == YAHOO_STATUS_CUSTOM)) {
@@ -1179,7 +1179,7 @@
 	GList *m = NULL;
 	struct proto_buddy_menu *pbm;
 	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
-	struct buddy *b = gaim_find_buddy(gc->account, who); /* this should never be null. if it is,
+	GaimBuddy *b = gaim_find_buddy(gc->account, who); /* this should never be null. if it is,
 						  segfault and get the bug report. */
 	static char buf2[1024];
 
@@ -1407,7 +1407,7 @@
 {
 	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
 	struct yahoo_packet *pkt;
-	struct group *g;
+	GaimGroup *g;
 	char *group = NULL;
 
 	if (!yd->logged_in)
--- a/src/protocols/zephyr/zephyr.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/protocols/zephyr/zephyr.c	Tue Sep 02 03:41:10 2003 +0000
@@ -316,7 +316,7 @@
 		if (!g_ascii_strcasecmp(notice.z_opcode, LOCATE_LOCATE)) {
 			int nlocs;
 			char *user;
-			struct buddy *b;
+			GaimBuddy *b;
 
 			if (ZParseLocations(&notice, NULL, &nlocs, &user) != ZERR_NONE)
 				return;
@@ -438,7 +438,7 @@
 
 static gint check_loc(gpointer data)
 {
-	GaimBlistNode *gnode,*bnode;
+	GaimBlistNode *gnode, *cnode, *bnode;
 	ZAsyncLocateData_t ald;
 
 	ald.user = NULL;
@@ -448,17 +448,21 @@
 	for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(bnode = gnode->child; bnode; bnode = bnode->next) {
-			struct buddy *b = (struct buddy *)bnode;
-			if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 				continue;
-			if(b->account->gc == zgc) {
-				char *chk;
-				chk = zephyr_normalize(b->name);
-				/* doesn't matter if this fails or not; we'll just move on to the next one */
-				ZRequestLocations(chk, &ald, UNACKED, ZAUTH);
-				free(ald.user);
-				free(ald.version);
+			for(bnode = gnode->child; bnode; bnode = bnode->next) {
+				GaimBuddy *b = (GaimBuddy *)bnode;
+				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+					continue;
+				if(b->account->gc == zgc) {
+					char *chk;
+					chk = zephyr_normalize(b->name);
+					/* doesn't matter if this fails or not; we'll just move on to the next one */
+					ZRequestLocations(chk, &ald, UNACKED, ZAUTH);
+					free(ald.user);
+					free(ald.version);
+				}
 			}
 		}
 	}
@@ -565,21 +569,21 @@
 {
 	FILE *fd;
 	gchar buff[BUFSIZ], *filename;
-        struct group *g;
-        struct buddy *b;
+	GaimGroup *g;
+	GaimBuddy *b;
 
 	if (!(g = gaim_find_group(_("Anyone")))) {
 		g = gaim_group_new(_("Anyone"));
 		gaim_blist_add_group(g, NULL);
 	}
-        
+
 	filename = g_strconcat(gaim_home_dir(), "/.anyone", NULL);
 	if ((fd = fopen(filename, "r")) != NULL) {
 		while (fgets(buff, BUFSIZ, fd)) {
 			strip_comments(buff);
 			if (buff[0]) {
                                 b = gaim_buddy_new(zgc->account, buff, NULL);
-				gaim_blist_add_buddy(b, g, NULL);
+				gaim_blist_add_buddy(b, NULL, g, NULL);
                         }
 		}
 		fclose(fd);
@@ -665,8 +669,8 @@
 
 static void write_anyone()
 {
-	GaimBlistNode *gnode,*bnode;
-	struct buddy *b;
+	GaimBlistNode *gnode, *cnode, *bnode;
+	GaimBuddy *b;
 	char *ptr, *fname, *ptr2;
 	FILE *fd;
 
@@ -680,23 +684,27 @@
 	for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) {
 		if(!GAIM_BLIST_NODE_IS_GROUP(gnode))
 			continue;
-		for(bnode = gnode->child; bnode; bnode = bnode->next) {
-			if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+		for(cnode = gnode->child; cnode; cnode = cnode->next) {
+			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 				continue;
-			b = (struct buddy *)bnode;
-			if(b->account->gc == zgc) {
-				if ((ptr = strchr(b->name, '@')) != NULL) {
-					ptr2 = ptr + 1;
-					/* We should only strip the realm name if the principal
-					   is in the user's realm
-					   */
-					if (!g_ascii_strcasecmp(ptr2,ZGetRealm())) {
-						*ptr = '\0';
+			for(bnode = gnode->child; bnode; bnode = bnode->next) {
+				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+					continue;
+				b = (GaimBuddy *)bnode;
+				if(b->account->gc == zgc) {
+					if ((ptr = strchr(b->name, '@')) != NULL) {
+						ptr2 = ptr + 1;
+						/* We should only strip the realm name if the principal
+						   is in the user's realm
+						   */
+						if (!g_ascii_strcasecmp(ptr2,ZGetRealm())) {
+							*ptr = '\0';
+						}
 					}
+					fprintf(fd, "%s\n", b->name);
+					if (ptr)
+						*ptr = '@';
 				}
-				fprintf(fd, "%s\n", b->name);
-				if (ptr)
-					*ptr = '@';
 			}
 		}
 	}
@@ -951,7 +959,7 @@
 	}
 }
 
-static const char *zephyr_list_icon(GaimAccount *a, struct buddy *b)
+static const char *zephyr_list_icon(GaimAccount *a, GaimBuddy *b)
 {
 	return "zephyr";
 }
--- a/src/prpl.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/prpl.c	Tue Sep 02 03:41:10 2003 +0000
@@ -123,7 +123,7 @@
 	struct icon_data tmp;
 	GList *l;
 	struct icon_data *id;
-	struct buddy *b;
+	GaimBuddy *b;
 	/* i'm going to vent here a little bit about normalize().  normalize()
 	 * uses a static buffer, so when we call functions that use normalize() from
 	 * functions that use normalize(), whose parameters are the result of running
@@ -279,7 +279,7 @@
 	GaimAccount *account;
 	char buf[BUF_LONG];
 	struct got_add *ga;
-	struct buddy *b;
+	GaimBuddy *b;
 
 	account = gaim_connection_get_account(gc);
 	b = gaim_find_buddy(gc->account, who);
--- a/src/prpl.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/prpl.h	Tue Sep 02 03:41:10 2003 +0000
@@ -202,25 +202,25 @@
 	 * Returns the base icon name for the given buddy and account.
 	 * If buddy is NULL, it will return the name to use for the account's icon
 	 */
-	const char *(*list_icon)(GaimAccount *account, struct buddy *buddy);
+	const char *(*list_icon)(GaimAccount *account, GaimBuddy *buddy);
 
 	/**
 	 * Fills the four char**'s with string identifiers for "emblems"
 	 * that the UI will interpret and display as relevant
 	 */
-	void (*list_emblems)(struct buddy *buddy, char **se, char **sw,
+	void (*list_emblems)(GaimBuddy *buddy, char **se, char **sw,
 						  char **nw, char **ne);
 
 	/**
 	 * Gets a short string representing this buddy's status.  This will
 	 * be shown on the buddy list.
 	 */
-	char *(*status_text)(struct buddy *buddy);
+	char *(*status_text)(GaimBuddy *buddy);
 
 	/**
 	 * Gets a string to put in the buddy list tooltip.
 	 */
-	char *(*tooltip_text)(struct buddy *buddy);
+	char *(*tooltip_text)(GaimBuddy *buddy);
 
 	GList *(*away_states)(GaimConnection *gc);
 	GList *(*actions)(GaimConnection *gc);
@@ -300,7 +300,7 @@
 	void (*rename_group)(GaimConnection *, const char *old_group,
 						 const char *new_group, GList *members);
 
-	void (*buddy_free)(struct buddy *);
+	void (*buddy_free)(GaimBuddy *);
 
 	/* this is really bad. */
 	void (*convo_closed)(GaimConnection *, const char *who);
--- a/src/server.c	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/server.c	Tue Sep 02 03:41:10 2003 +0000
@@ -516,7 +516,7 @@
 /*
  * Set buddy's alias on server roster/list
  */
-void serv_alias_buddy(struct buddy *b)
+void serv_alias_buddy(GaimBuddy *b)
 {
 	GaimPluginProtocolInfo *prpl_info = NULL;
 
@@ -529,7 +529,7 @@
 }
 
 void serv_got_alias(GaimConnection *gc, const char *who, const char *alias) {
-	struct buddy *b = gaim_find_buddy(gc->account, who);
+	GaimBuddy *b = gaim_find_buddy(gc->account, who);
 
 	if(!b)
 		return;
@@ -543,7 +543,7 @@
  * Note: For now we'll not deal with changing gc's at the same time, but
  * it should be possible.  Probably needs to be done, someday.
  */
-void serv_move_buddy(struct buddy *b, struct group *og, struct group *ng)
+void serv_move_buddy(GaimBuddy *b, GaimGroup *og, GaimGroup *ng)
 {
 	GaimPluginProtocolInfo *prpl_info = NULL;
 
@@ -560,7 +560,7 @@
 /*
  * Rename a group on server roster/list.
  */
-void serv_rename_group(GaimConnection *g, struct group *old_group,
+void serv_rename_group(GaimConnection *g, GaimGroup *old_group,
 					   const char *new_name)
 {
 	GaimPluginProtocolInfo *prpl_info = NULL;
@@ -570,15 +570,22 @@
 
 	if (prpl_info && old_group && new_name) {
 		GList *tobemoved = NULL;
-		GaimBlistNode *b = ((GaimBlistNode*)old_group)->child;
+		GaimBlistNode *cnode, *bnode;
 
-		while (b) {
-			if(GAIM_BLIST_NODE_IS_BUDDY(b)) {
-				struct buddy *bd = (struct buddy *)b;
-				if (bd->account == g->account)
-					tobemoved = g_list_append(tobemoved, bd->name);
+		for(cnode = ((GaimBlistNode*)old_group)->child; cnode; cnode = cnode->next) {
+			if(!GAIM_BLIST_NODE_IS_CONTACT(cnode))
+				continue;
+			for(bnode = cnode->child; bnode; bnode = bnode->next) {
+				GaimBuddy *b;
+				if(!GAIM_BLIST_NODE_IS_BUDDY(bnode))
+					continue;
+				b = (GaimBuddy*)bnode;
+
+				if(b->account == g->account)
+					tobemoved = g_list_append(tobemoved, b->name);
+
 			}
-			b = b->next;
+
 		}
 
 		if (prpl_info->rename_group) {
@@ -890,8 +897,8 @@
 	if (gc->away) {
 		time_t t = time(NULL);
 		char *tmpmsg;
-		struct buddy *b = gaim_find_buddy(gc->account, name);
-		char *alias = b ? gaim_get_buddy_alias(b) : name;
+		GaimBuddy *b = gaim_find_buddy(gc->account, name);
+		const char *alias = b ? gaim_get_buddy_alias(b) : name;
 		int row;
 		struct last_auto_response *lar;
 
@@ -1073,7 +1080,7 @@
 {
 	GaimAccount *account;
 	GaimConversation *c;
-	struct buddy *b;
+	GaimBuddy *b;
 	GSList *buddies;
 
 	account = gaim_connection_get_account(gc);
@@ -1233,7 +1240,7 @@
 void serv_got_typing(GaimConnection *gc, const char *name, int timeout,
 					 GaimTypingState state) {
 
-	struct buddy *b;
+	GaimBuddy *b;
 	GaimConversation *cnv = gaim_find_conversation_with_account(name, gc->account);
 	GaimIm *im;
 
@@ -1265,7 +1272,7 @@
 
 	GaimConversation *c = gaim_find_conversation_with_account(name, gc->account);
 	GaimIm *im;
-	struct buddy *b;
+	GaimBuddy *b;
 
 	if (!c)
 		return;
--- a/src/server.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/server.h	Tue Sep 02 03:41:10 2003 +0000
@@ -71,10 +71,10 @@
 int  serv_chat_send(GaimConnection *, int, const char *);
 void serv_got_popup(const char *, const char *, int, int);
 void serv_get_away(GaimConnection *, const char *);
-void serv_alias_buddy(struct buddy *);
+void serv_alias_buddy(GaimBuddy *);
 void serv_got_alias(GaimConnection *gc, const char *who, const char *alias);
-void serv_move_buddy(struct buddy *, struct group *, struct group *);
-void serv_rename_group(GaimConnection *, struct group *, const char *);
+void serv_move_buddy(GaimBuddy *, GaimGroup *, GaimGroup *);
+void serv_rename_group(GaimConnection *, GaimGroup *, const char *);
 void serv_got_eviled(GaimConnection *gc, const char *name, int lev);
 void serv_got_typing(GaimConnection *gc, const char *name, int timeout,
 					 GaimTypingState state);
--- a/src/ui.h	Tue Sep 02 03:34:37 2003 +0000
+++ b/src/ui.h	Tue Sep 02 03:41:10 2003 +0000
@@ -140,13 +140,13 @@
 void *gaim_gtk_notify_uri(const char *uri);
 
 /* Functions in dialogs.c */
-extern void alias_dialog_bud(struct buddy *);
-extern void alias_dialog_chat(struct chat *);
+extern void alias_dialog_bud(GaimBuddy *);
+extern void alias_dialog_blist_chat(GaimBlistChat *);
 extern void show_warn_dialog(GaimConnection *, char *);
 extern void show_im_dialog();
 extern void show_info_dialog();
 extern void show_add_buddy(GaimConnection *, char *, char *, char *);
-extern void show_add_chat(GaimAccount *, struct group *);
+extern void show_add_chat(GaimAccount *, GaimGroup *);
 extern void show_add_group(GaimConnection *);
 extern void destroy_all_dialogs();
 extern void show_import_dialog();
@@ -171,7 +171,7 @@
 extern void show_font_dialog(GaimConversation *c, GtkWidget *font);
 extern void cancel_font(GtkWidget *widget, GaimConversation *c);
 extern void apply_font(GtkWidget *widget, GtkFontSelection *fontsel);
-extern void show_rename_group(GtkWidget *, struct group *);
+extern void show_rename_group(GtkWidget *, GaimGroup *);
 extern void destroy_fontsel(GtkWidget *w, gpointer d);
 extern void join_chat();