gobjectification: 811d6e22: Did some more hiding of PurpleBuddyList, ...

aluink at soc.pidgin.im aluink at soc.pidgin.im
Thu Jun 25 16:55:24 EDT 2009


-----------------------------------------------------------------
Revision: 811d6e22fc676b5d2f87ff0d8fff750662e4bc7b
Ancestor: 1dfb6c9f81757d612bf7a3f3a7f5fcc63b09d790
Author: aluink at soc.pidgin.im
Date: 2009-06-25T20:50:03
Branch: im.pidgin.gobjectification
URL: http://d.pidgin.im/viewmtn/revision/info/811d6e22fc676b5d2f87ff0d8fff750662e4bc7b

Modified files:
        finch/finch.c finch/gntblist.c libpurple/blist-node.c
        libpurple/blist.c libpurple/blist.h libpurple/buddy.c
        libpurple/chat.c libpurple/contact.c libpurple/core.c
        libpurple/example/nullclient.c libpurple/group.c
        pidgin/gtkblist.c pidgin/gtkmain.c pidgin/gtkutils.c

ChangeLog: 

Did some more hiding of PurpleBuddyList, more needed

-------------- next part --------------
============================================================
--- finch/finch.c	8c094d9ed8ac527472c39e24646f71cea6ccbc54
+++ finch/finch.c	88fa159de790254697e241f6bee2cb3f7bb00ceb
@@ -353,10 +353,6 @@ init_libpurple(int argc, char **argv)
 		abort();
 	}
 
-	/* TODO: Move blist loading into purple_blist_init() */
-	purple_set_blist(purple_blist_new());
-	purple_blist_load();
-
 	/* TODO: should this be moved into finch_prefs_init() ? */
 	finch_prefs_update_old();
 
============================================================
--- finch/gntblist.c	92abdff048dd558f9d7866251d45896c3d36a1ec
+++ finch/gntblist.c	1774d8bf4e33e26cbe8e36326552fa05cc99624c
@@ -498,7 +498,7 @@ node_remove(PurpleBuddyList *list, Purpl
 static void
 node_remove(PurpleBuddyList *list, PurpleBlistNode *node)
 {
-	FinchBlist *ggblist = FINCH_GET_DATA(list);
+	FinchBlist *ggblist = purple_blist_get_ui_data();
 	PurpleBlistNode *parent;
 
 	if (ggblist == NULL || FINCH_GET_DATA(node) == NULL)
@@ -536,7 +536,7 @@ node_update(PurpleBuddyList *list, Purpl
            happens, so maybe someone will figure it out. */
 	g_return_if_fail(node != NULL);
 
-	if (FINCH_GET_DATA(list)== NULL)
+	if (purple_blist_get_ui_data()== NULL)
 		return;   /* XXX: this is probably the place to auto-join chats */
 
 	if (ggblist->window == NULL)
@@ -554,21 +554,21 @@ node_update(PurpleBuddyList *list, Purpl
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		PurpleBuddy *buddy = (PurpleBuddy*)node;
-		add_node((PurpleBlistNode*)buddy, FINCH_GET_DATA(list));
+		add_node((PurpleBlistNode*)buddy, purple_blist_get_ui_data());
 		node_update(list, purple_blist_node_get_parent(node));
 	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
-		add_node(node, FINCH_GET_DATA(list));
+		add_node(node, purple_blist_get_ui_data());
 	} else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		if (FINCH_GET_DATA(node)== NULL) {
 			/* The core seems to expect the UI to add the buddies. */
 			for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node))
-				add_node(node, FINCH_GET_DATA(list));
+				add_node(node, purple_blist_get_ui_data());
 		}
 	} else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
 		if (!ggblist->manager->can_add_node(node))
 			node_remove(list, node);
 		else
-			add_node(node, FINCH_GET_DATA(list));
+			add_node(node, purple_blist_get_ui_data());
 	}
 	if (ggblist->tnode == node) {
 		draw_tooltip(ggblist);
@@ -582,7 +582,7 @@ new_list(PurpleBuddyList *list)
 		return;
 
 	ggblist = g_new0(FinchBlist, 1);
-	FINCH_SET_DATA(list, ggblist);
+	purple_blist_set_ui_data(ggblist);
 	ggblist->manager = finch_blist_manager_find(purple_prefs_get_string(PREF_ROOT "/grouping"));
 	if (!ggblist->manager)
 		ggblist->manager = &default_manager;
@@ -2007,7 +2007,7 @@ reset_blist_window(GntWidget *window, gp
 {
 	PurpleBlistNode *node;
 	purple_signals_disconnect_by_handle(finch_blist_get_handle());
-	FINCH_SET_DATA(purple_get_blist(), NULL);
+	purple_blist_set_ui_data(NULL);
 
 	node = purple_blist_get_root();
 	while (node) {
============================================================
--- libpurple/blist-node.c	a55977fb4417c186f0c2d19d975ca18c4a66d904
+++ libpurple/blist-node.c	4762c4aa4334d0174ed66a2605ecfcae8afc94a0
@@ -156,242 +156,8 @@ purple_blist_update_node_icon(PurpleBlis
     ops->update(purplebuddylist, node);
 }
 
-void purple_blist_add_chat(PurpleChat *chat, PurpleGroup *group, PurpleBlistNode *node)
-{
-	PurpleBlistNode *cnode = (PurpleBlistNode*)chat;
-	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 
-	g_return_if_fail(chat != NULL);
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT((PurpleBlistNode *)chat));
 
-	if (node == NULL) {
-		if (group == NULL)
-			group = purple_group_new(_("Chats"));
-
-		/* Add group to blist if isn't already on it. Fixes #2752. */
-		if (!purple_find_group(group->name)) {
-			purple_blist_add_group(group,
-					purple_blist_get_last_sibling(purplebuddylist->root));
-		}
-	} else {
-		group = (PurpleGroup*)node->parent;
-	}
-
-	/* if we're moving to overtop of ourselves, do nothing */
-	if (cnode == node)
-		return;
-
-	if (cnode->parent) {
-		/* This chat was already in the list and is
-		 * being moved.
-		 */
-		((PurpleGroup *)cnode->parent)->totalsize--;
-		if (purple_account_is_connected(chat->account)) {
-			((PurpleGroup *)cnode->parent)->online--;
-			((PurpleGroup *)cnode->parent)->currentsize--;
-		}
-		if (cnode->next)
-			cnode->next->prev = cnode->prev;
-		if (cnode->prev)
-			cnode->prev->next = cnode->next;
-		if (cnode->parent->child == cnode)
-			cnode->parent->child = cnode->next;
-
-		if (ops && ops->remove)
-			ops->remove(purplebuddylist, cnode);
-		/* ops->remove() cleaned up the cnode's ui_data, so we need to
-		 * reinitialize it */
-		if (ops && ops->new_node)
-			ops->new_node(cnode);
-
-		purple_blist_schedule_save();
-	}
-
-	if (node != NULL) {
-		if (node->next)
-			node->next->prev = cnode;
-		cnode->next = node->next;
-		cnode->prev = node;
-		cnode->parent = node->parent;
-		node->next = cnode;
-		((PurpleGroup *)node->parent)->totalsize++;
-		if (purple_account_is_connected(chat->account)) {
-			((PurpleGroup *)node->parent)->online++;
-			((PurpleGroup *)node->parent)->currentsize++;
-		}
-	} else {
-		if (((PurpleBlistNode *)group)->child)
-			((PurpleBlistNode *)group)->child->prev = cnode;
-		cnode->next = ((PurpleBlistNode *)group)->child;
-		cnode->prev = NULL;
-		((PurpleBlistNode *)group)->child = cnode;
-		cnode->parent = (PurpleBlistNode *)group;
-		group->totalsize++;
-		if (purple_account_is_connected(chat->account)) {
-			group->online++;
-			group->currentsize++;
-		}
-	}
-
-	purple_blist_schedule_save();
-
-	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)cnode);
-
-	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
-			cnode);
-}
-
-void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node)
-{
-	PurpleBlistNode *cnode, *bnode;
-	PurpleGroup *g;
-	PurpleContact *c;
-	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
-	struct _purple_hbuddy *hb, *hb2;
-	GHashTable *account_buddies;
-
-	g_return_if_fail(buddy != NULL);
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY((PurpleBlistNode*)buddy));
-
-	bnode = (PurpleBlistNode *)buddy;
-
-	/* if we're moving to overtop of ourselves, do nothing */
-	if (bnode == node || (!node && bnode->parent &&
-				contact && bnode->parent == (PurpleBlistNode*)contact
-				&& bnode == bnode->parent->child))
-		return;
-
-	if (node && PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-		c = (PurpleContact*)node->parent;
-		g = (PurpleGroup*)node->parent->parent;
-	} else if (contact) {
-		c = contact;
-		g = PURPLE_GROUP(PURPLE_BLIST_NODE(c)->parent);
-	} else {
-		g = group;
-		if (g == NULL)
-			g = purple_group_new(_("Buddies"));
-		/* Add group to blist if isn't already on it. Fixes #2752. */
-		if (!purple_find_group(g->name)) {
-			purple_blist_add_group(g,
-					purple_blist_get_last_sibling(purplebuddylist->root));
-		}
-		c = purple_contact_new();
-		purple_blist_add_contact(c, g,
-				purple_blist_get_last_child((PurpleBlistNode*)g));
-	}
-
-	cnode = (PurpleBlistNode *)c;
-
-	if (bnode->parent) {
-		if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-			((PurpleContact*)bnode->parent)->online--;
-			if (((PurpleContact*)bnode->parent)->online == 0)
-				((PurpleGroup*)bnode->parent->parent)->online--;
-		}
-		if (purple_account_is_connected(buddy->account)) {
-			((PurpleContact*)bnode->parent)->currentsize--;
-			if (((PurpleContact*)bnode->parent)->currentsize == 0)
-				((PurpleGroup*)bnode->parent->parent)->currentsize--;
-		}
-		((PurpleContact*)bnode->parent)->totalsize--;
-		/* the group totalsize will be taken care of by remove_contact below */
-
-		if (bnode->parent->parent != (PurpleBlistNode*)g)
-			serv_move_buddy(buddy, (PurpleGroup *)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)
-			bnode->parent->child = bnode->next;
-
-		if (ops && ops->remove)
-			ops->remove(purplebuddylist, bnode);
-
-		purple_blist_schedule_save();
-
-		if (bnode->parent->parent != (PurpleBlistNode*)g) {
-			hb = g_new(struct _purple_hbuddy, 1);
-			hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
-			hb->account = buddy->account;
-			hb->group = bnode->parent->parent;
-			g_hash_table_remove(purplebuddylist->buddies, hb);
-
-			account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, buddy->account);
-			g_hash_table_remove(account_buddies, hb);
-
-			g_free(hb->name);
-			g_free(hb);
-		}
-
-		if (!bnode->parent->child) {
-			purple_blist_remove_contact((PurpleContact*)bnode->parent);
-		} else {
-			purple_contact_invalidate_priority_buddy((PurpleContact*)bnode->parent);
-			if (ops && ops->update)
-				ops->update(purplebuddylist, bnode->parent);
-		}
-	}
-
-	if (node && PURPLE_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 (cnode->child)
-			cnode->child->prev = bnode;
-		bnode->prev = NULL;
-		bnode->next = cnode->child;
-		cnode->child = bnode;
-		bnode->parent = cnode;
-	}
-
-	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-		if (++(PURPLE_CONTACT(bnode->parent)->online) == 1)
-			PURPLE_GROUP(bnode->parent->parent)->online++;
-	}
-	if (purple_account_is_connected(buddy->account)) {
-		if (++(PURPLE_CONTACT(bnode->parent)->currentsize) == 1)
-			PURPLE_GROUP(bnode->parent->parent)->currentsize++;
-	}
-	PURPLE_CONTACT(bnode->parent)->totalsize++;
-
-	hb = g_new(struct _purple_hbuddy, 1);
-	hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
-	hb->account = buddy->account;
-	hb->group = ((PurpleBlistNode*)buddy)->parent->parent;
-
-	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
-
-	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, buddy->account);
-
-	hb2 = g_new(struct _purple_hbuddy, 1);
-	hb2->name = g_strdup(hb->name);
-	hb2->account = buddy->account;
-	hb2->group = ((PurpleBlistNode*)buddy)->parent->parent;
-
-	g_hash_table_replace(account_buddies, hb2, buddy);
-
-	purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
-
-	purple_blist_schedule_save();
-
-	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode*)buddy);
-
-	/* Signal that the buddy has been added */
-	purple_signal_emit(purple_blist_get_handle(), "buddy-added", buddy);
-
-	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
-			PURPLE_BLIST_NODE(buddy));
-}
-
 void purple_blist_merge_contact(PurpleContact *source, PurpleBlistNode *node)
 {
 	PurpleBlistNode *sourcenode = (PurpleBlistNode*)source;
============================================================
--- libpurple/blist.c	848dbef53512b4331a50101522d658751b14c978
+++ libpurple/blist.c	57b6cf2a35c60e7673fdc3f66bba4461e314a401
@@ -31,6 +31,7 @@
 #include "notify.h"
 #include "prefs.h"
 #include "privacy.h"
+#include "private.h"
 #include "prpl.h"
 #include "server.h"
 #include "signals.h"
@@ -38,6 +39,41 @@
 #include "value.h"
 #include "xmlnode.h"
 
+static GType purple_blist_get_gtype(void);
+
+/** @copydoc _PurpleBlist */
+typedef struct _PurpleBuddyListClass PurpleBuddyListClass;
+#define PURPLE_BUDDY_LIST_TYPE                  (purple_blist_get_gtype ())
+#define PURPLE_BUDDY_LIST(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_BUDDY_LIST_TYPE, PurpleBuddyList))
+#define PURPLE_IS_BUDDY_LIST(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_BUDDY_LIST_TYPE))
+#define PURPLE_BUDDY_LIST_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_BUDDY_LIST_TYPE, PurpleBuddyListClass))
+#define PURPLE_IS_BUDDY_LIST_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_BUDDY_LIST_TYPE))
+#define PURPLE_GET_BUDDY_LIST_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_BUDDY_LIST_TYPE, PurpleBuddyListClass))
+
+/**
+ * The Buddy List
+ */
+struct _PurpleBuddyList {
+  PurpleObject parent;
+	PurpleBlistNode *root;          /**< The first node in the buddy list */
+	GHashTable *buddies;          /**< Every buddy in this list */
+  
+  /**
+   * A hash table used for efficient lookups of buddies by name.
+   * PurpleAccount* => GHashTable*, with the inner hash table being
+   * struct _purple_hbuddy => PurpleBuddy*
+   */
+  GHashTable *buddies_cache;
+
+  guint          save_timer;
+  gboolean       blist_loaded;
+	void *ui_data;                /**< UI-specific data. */
+};
+
+struct _PurpleBuddyListClass {
+  PurpleObjectClass parent;
+};
+
 static PurpleBlistUiOps *blist_ui_ops = NULL;
 
 PurpleBuddyList *purplebuddylist = NULL;
@@ -228,6 +264,33 @@ purple_blist_schedule_save()
  * Reading from disk                                                 *
  *********************************************************************/
 
+void
+parse_group(xmlnode *groupnode)
+{
+	const char *name = xmlnode_get_attrib(groupnode, "name");
+	PurpleGroup *group;
+	xmlnode *cnode;
+
+	if (!name)
+		name = _("Buddies");
+
+  group = purple_group_new(name);
+  purple_blist_add_group(group,
+     purple_blist_get_last_sibling(purplebuddylist->root));
+
+	for (cnode = groupnode->child; cnode; cnode = cnode->next) {
+		if (cnode->type != XMLNODE_TYPE_TAG)
+			continue;
+		if (purple_strequal(cnode->name, "setting"))
+			parse_setting((PurpleBlistNode*)group, cnode);
+		else if (purple_strequal(cnode->name, "contact") ||
+				purple_strequal(cnode->name, "person"))
+			parse_contact(group, cnode);
+		else if (purple_strequal(cnode->name, "chat"))
+			parse_chat(group, cnode);
+	}
+}
+
 /* TODO: Make static and rename to load_blist */
 void
 purple_blist_load()
@@ -304,47 +367,6 @@ purple_blist_load()
  * Public API functions                                                      *
  *****************************************************************************/
 
-PurpleBuddyList *purple_blist_new()
-{
-	PurpleBlistUiOps *ui_ops;
-	GList *account;
-	PurpleBuddyList *gbl = g_object_new(PURPLE_BUDDY_LIST_TYPE, NULL);
-	PURPLE_DBUS_REGISTER_POINTER(gbl, PurpleBuddyList);
-
-	ui_ops = purple_blist_get_ui_ops();
-
-  #warning: This has to be set here or we cant add the buddies cache
-  if(purplebuddylist) /* In case we're creating a replacement list */
-    purple_blist_destroy();
-  purple_set_blist(gbl);
-
-	gbl->buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash,
-					 (GEqualFunc)_purple_blist_hbuddy_equal,
-					 (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL);
-
-	gbl->buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal,
-					 NULL, (GDestroyNotify)g_hash_table_destroy);
-
-	for (account = purple_accounts_get_all(); account != NULL; account = account->next)
-	{
-		purple_blist_buddies_cache_add_account(account->data);
-	}
-
-	if (ui_ops != NULL && ui_ops->new_list != NULL)
-		ui_ops->new_list(gbl);
-
-  gbl->save_timer = 0;
-  gbl->blist_loaded = FALSE;
-
-	return gbl;
-}
-
-void
-purple_set_blist(PurpleBuddyList *list)
-{
-	purplebuddylist = list;
-}
-
 PurpleBuddyList *
 purple_get_blist()
 {
@@ -401,6 +423,47 @@ purple_strings_are_different(const char 
 			((one == NULL || *one == '\0') && (two == NULL || *two == '\0')));
 }
 
+/*
+ * TODO: Maybe remove the call to this from server.c and call it
+ * from oscar.c and toc.c instead?
+ */
+void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name)
+{
+	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+	struct _purple_hbuddy *hb, *hb2;
+	GHashTable *account_buddies;
+
+	g_return_if_fail(buddy != NULL);
+
+	hb = g_new(struct _purple_hbuddy, 1);
+	hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
+	hb->account = buddy->account;
+	hb->group = ((PurpleBlistNode *)buddy)->parent->parent;
+	g_hash_table_remove(purplebuddylist->buddies, hb);
+	
+	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, buddy->account);
+	g_hash_table_remove(account_buddies, hb);
+
+	g_free(hb->name);
+	hb->name = g_strdup(purple_normalize(buddy->account, name));
+	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+
+	hb2 = g_new(struct _purple_hbuddy, 1);
+	hb2->name = g_strdup(hb->name);
+	hb2->account = buddy->account;
+	hb2->group = ((PurpleBlistNode *)buddy)->parent->parent;
+
+	g_hash_table_replace(account_buddies, hb2, buddy);
+
+	g_free(buddy->name);
+	buddy->name = g_strdup(name);
+
+	purple_blist_schedule_save();
+
+	if (ops && ops->update)
+		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
+}
+
 void purple_blist_add_contact(PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
@@ -812,7 +875,21 @@ void purple_blist_remove_group(PurpleGro
 	purple_group_destroy(group);
 }
 
+PurpleGroup *purple_find_group(const char *name)
+{
+	PurpleBlistNode *node;
 
+	g_return_val_if_fail(purplebuddylist != NULL, NULL);
+	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
+
+	for (node = purplebuddylist->root; node != NULL; node = node->next) {
+		if (!purple_utf8_strcasecmp(((PurpleGroup *)node)->name, name))
+			return (PurpleGroup *)node;
+	}
+
+	return NULL;
+}
+
 PurpleBuddy *purple_find_buddy(PurpleAccount *account, const char *name)
 {
 	PurpleBuddy *buddy;
@@ -1045,6 +1122,346 @@ gboolean purple_group_on_account(PurpleG
 	return FALSE;
 }
 
+void purple_blist_add_chat(PurpleChat *chat, PurpleGroup *group, PurpleBlistNode *node)
+{
+	PurpleBlistNode *cnode = (PurpleBlistNode*)chat;
+	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+
+	g_return_if_fail(chat != NULL);
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT((PurpleBlistNode *)chat));
+
+	if (node == NULL) {
+		if (group == NULL)
+			group = purple_group_new(_("Chats"));
+
+		/* Add group to blist if isn't already on it. Fixes #2752. */
+		if (!purple_find_group(group->name)) {
+			purple_blist_add_group(group,
+					purple_blist_get_last_sibling(purplebuddylist->root));
+		}
+	} else {
+		group = (PurpleGroup*)node->parent;
+	}
+
+	/* if we're moving to overtop of ourselves, do nothing */
+	if (cnode == node)
+		return;
+
+	if (cnode->parent) {
+		/* This chat was already in the list and is
+		 * being moved.
+		 */
+		((PurpleGroup *)cnode->parent)->totalsize--;
+		if (purple_account_is_connected(chat->account)) {
+			((PurpleGroup *)cnode->parent)->online--;
+			((PurpleGroup *)cnode->parent)->currentsize--;
+		}
+		if (cnode->next)
+			cnode->next->prev = cnode->prev;
+		if (cnode->prev)
+			cnode->prev->next = cnode->next;
+		if (cnode->parent->child == cnode)
+			cnode->parent->child = cnode->next;
+
+		if (ops && ops->remove)
+			ops->remove(purplebuddylist, cnode);
+		/* ops->remove() cleaned up the cnode's ui_data, so we need to
+		 * reinitialize it */
+		if (ops && ops->new_node)
+			ops->new_node(cnode);
+
+		purple_blist_schedule_save();
+	}
+
+	if (node != NULL) {
+		if (node->next)
+			node->next->prev = cnode;
+		cnode->next = node->next;
+		cnode->prev = node;
+		cnode->parent = node->parent;
+		node->next = cnode;
+		((PurpleGroup *)node->parent)->totalsize++;
+		if (purple_account_is_connected(chat->account)) {
+			((PurpleGroup *)node->parent)->online++;
+			((PurpleGroup *)node->parent)->currentsize++;
+		}
+	} else {
+		if (((PurpleBlistNode *)group)->child)
+			((PurpleBlistNode *)group)->child->prev = cnode;
+		cnode->next = ((PurpleBlistNode *)group)->child;
+		cnode->prev = NULL;
+		((PurpleBlistNode *)group)->child = cnode;
+		cnode->parent = (PurpleBlistNode *)group;
+		group->totalsize++;
+		if (purple_account_is_connected(chat->account)) {
+			group->online++;
+			group->currentsize++;
+		}
+	}
+
+	purple_blist_schedule_save();
+
+	if (ops && ops->update)
+		ops->update(purplebuddylist, (PurpleBlistNode *)cnode);
+
+	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
+			cnode);
+}
+
+void purple_blist_add_buddy(PurpleBuddy *buddy, PurpleContact *contact, PurpleGroup *group, PurpleBlistNode *node)
+{
+	PurpleBlistNode *cnode, *bnode;
+	PurpleGroup *g;
+	PurpleContact *c;
+	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+	struct _purple_hbuddy *hb, *hb2;
+	GHashTable *account_buddies;
+
+	g_return_if_fail(buddy != NULL);
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY((PurpleBlistNode*)buddy));
+
+	bnode = (PurpleBlistNode *)buddy;
+
+	/* if we're moving to overtop of ourselves, do nothing */
+	if (bnode == node || (!node && bnode->parent &&
+				contact && bnode->parent == (PurpleBlistNode*)contact
+				&& bnode == bnode->parent->child))
+		return;
+
+	if (node && PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+		c = (PurpleContact*)node->parent;
+		g = (PurpleGroup*)node->parent->parent;
+	} else if (contact) {
+		c = contact;
+		g = PURPLE_GROUP(PURPLE_BLIST_NODE(c)->parent);
+	} else {
+		g = group;
+		if (g == NULL)
+			g = purple_group_new(_("Buddies"));
+		/* Add group to blist if isn't already on it. Fixes #2752. */
+		if (!purple_find_group(g->name)) {
+			purple_blist_add_group(g,
+					purple_blist_get_last_sibling(purplebuddylist->root));
+		}
+		c = purple_contact_new();
+		purple_blist_add_contact(c, g,
+				purple_blist_get_last_child((PurpleBlistNode*)g));
+	}
+
+	cnode = (PurpleBlistNode *)c;
+
+	if (bnode->parent) {
+		if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
+			((PurpleContact*)bnode->parent)->online--;
+			if (((PurpleContact*)bnode->parent)->online == 0)
+				((PurpleGroup*)bnode->parent->parent)->online--;
+		}
+		if (purple_account_is_connected(buddy->account)) {
+			((PurpleContact*)bnode->parent)->currentsize--;
+			if (((PurpleContact*)bnode->parent)->currentsize == 0)
+				((PurpleGroup*)bnode->parent->parent)->currentsize--;
+		}
+		((PurpleContact*)bnode->parent)->totalsize--;
+		/* the group totalsize will be taken care of by remove_contact below */
+
+		if (bnode->parent->parent != (PurpleBlistNode*)g)
+			serv_move_buddy(buddy, (PurpleGroup *)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)
+			bnode->parent->child = bnode->next;
+
+		if (ops && ops->remove)
+			ops->remove(purplebuddylist, bnode);
+
+		purple_blist_schedule_save();
+
+		if (bnode->parent->parent != (PurpleBlistNode*)g) {
+			hb = g_new(struct _purple_hbuddy, 1);
+			hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
+			hb->account = buddy->account;
+			hb->group = bnode->parent->parent;
+			g_hash_table_remove(purplebuddylist->buddies, hb);
+
+			account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, buddy->account);
+			g_hash_table_remove(account_buddies, hb);
+
+			g_free(hb->name);
+			g_free(hb);
+		}
+
+		if (!bnode->parent->child) {
+			purple_blist_remove_contact((PurpleContact*)bnode->parent);
+		} else {
+			purple_contact_invalidate_priority_buddy((PurpleContact*)bnode->parent);
+			if (ops && ops->update)
+				ops->update(purplebuddylist, bnode->parent);
+		}
+	}
+
+	if (node && PURPLE_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 (cnode->child)
+			cnode->child->prev = bnode;
+		bnode->prev = NULL;
+		bnode->next = cnode->child;
+		cnode->child = bnode;
+		bnode->parent = cnode;
+	}
+
+	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
+		if (++(PURPLE_CONTACT(bnode->parent)->online) == 1)
+			PURPLE_GROUP(bnode->parent->parent)->online++;
+	}
+	if (purple_account_is_connected(buddy->account)) {
+		if (++(PURPLE_CONTACT(bnode->parent)->currentsize) == 1)
+			PURPLE_GROUP(bnode->parent->parent)->currentsize++;
+	}
+	PURPLE_CONTACT(bnode->parent)->totalsize++;
+
+	hb = g_new(struct _purple_hbuddy, 1);
+	hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
+	hb->account = buddy->account;
+	hb->group = ((PurpleBlistNode*)buddy)->parent->parent;
+
+	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+
+	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, buddy->account);
+
+	hb2 = g_new(struct _purple_hbuddy, 1);
+	hb2->name = g_strdup(hb->name);
+	hb2->account = buddy->account;
+	hb2->group = ((PurpleBlistNode*)buddy)->parent->parent;
+
+	g_hash_table_replace(account_buddies, hb2, buddy);
+
+	purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
+
+	purple_blist_schedule_save();
+
+	if (ops && ops->update)
+		ops->update(purplebuddylist, (PurpleBlistNode*)buddy);
+
+	/* Signal that the buddy has been added */
+	purple_signal_emit(purple_blist_get_handle(), "buddy-added", buddy);
+
+	purple_signal_emit(purple_blist_get_handle(), "blist-node-added",
+			PURPLE_BLIST_NODE(buddy));
+}
+
+PurpleChat *
+purple_blist_find_chat(PurpleAccount *account, const char *name)
+{
+	char *chat_name;
+	PurpleChat *chat;
+	PurplePlugin *prpl;
+	PurplePluginProtocolInfo *prpl_info = NULL;
+	struct proto_chat_entry *pce;
+	PurpleBlistNode *node, *group;
+	GList *parts;
+	char *normname;
+
+	g_return_val_if_fail(purplebuddylist != NULL, NULL);
+	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
+
+	if (!purple_account_is_connected(account))
+		return NULL;
+
+	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+
+	if (prpl_info->find_blist_chat != NULL)
+		return prpl_info->find_blist_chat(account, name);
+
+	normname = g_strdup(purple_normalize(account, name));
+	for (group = purplebuddylist->root; group != NULL; group = group->next) {
+		for (node = group->child; node != NULL; node = node->next) {
+			if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
+
+				chat = (PurpleChat*)node;
+
+				if (account != chat->account)
+					continue;
+
+				parts = prpl_info->chat_info(
+					purple_account_get_connection(chat->account));
+
+				pce = parts->data;
+				chat_name = g_hash_table_lookup(chat->components,
+												pce->identifier);
+				g_list_foreach(parts, (GFunc)g_free, NULL);
+				g_list_free(parts);
+
+				if (chat->account == account && chat_name != NULL &&
+					normname != NULL && !strcmp(purple_normalize(account, chat_name), normname)) {
+					g_free(normname);
+					return chat;
+				}
+			}
+		}
+	}
+
+	g_free(normname);
+	return NULL;
+}
+
+PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name,
+		PurpleGroup *group)
+{
+	struct _purple_hbuddy hb;
+	PurpleBuddy *ret;
+
+	g_return_val_if_fail(purplebuddylist != NULL, NULL);
+	g_return_val_if_fail(account != NULL, NULL);
+	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
+
+	hb.name = g_strdup(purple_normalize(account, name));
+	hb.account = account;
+	hb.group = (PurpleBlistNode*)group;
+
+	ret = g_hash_table_lookup(purplebuddylist->buddies, &hb);
+	g_free(hb.name);
+
+	return ret;
+}
+
+PurpleGroup *
+purple_chat_get_group(PurpleChat *chat)
+{
+	g_return_val_if_fail(chat != NULL, NULL);
+
+	return (PurpleGroup *)(((PurpleBlistNode *)chat)->parent);
+}
+
+static void
+append_buddy(gpointer key, gpointer value, gpointer user_data)
+{
+	GSList **list = user_data;
+	*list = g_slist_prepend(*list, value);
+}
+
+GSList *
+purple_blist_get_buddies()
+{
+	GSList *buddies = NULL;
+
+	if (!purplebuddylist)
+		return NULL;
+
+	g_hash_table_foreach(purplebuddylist->buddies, append_buddy, &buddies);
+	return buddies;
+}
+
+
 void
 purple_blist_request_add_buddy(PurpleAccount *account, const char *username,
 							 const char *group, const char *alias)
@@ -1102,6 +1519,12 @@ void
 }
 
 void
+purple_blist_init(void)
+{
+  purplebuddylist = g_object_new(PURPLE_BUDDY_LIST_TYPE, NULL);
+}
+
+void
 purple_blist_uninit(void)
 {
 	PurpleBlistNode *node, *next_node;
@@ -1249,10 +1672,38 @@ purple_blist_instance_init(GTypeInstance
 static void
 purple_blist_instance_init(GTypeInstance *instance, gpointer class)
 {
+  PurpleBlistUiOps *ui_ops;
+	GList *account;
+  PurpleBuddyList *gbl = PURPLE_BUDDY_LIST(instance);
+	PURPLE_DBUS_REGISTER_POINTER(gbl, PurpleBuddyList);
 
+	ui_ops = purple_blist_get_ui_ops();
+
+  #warning: This has to be set here or we cant add the buddies cache
+  purplebuddylist = gbl;
+
+	gbl->buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash,
+					 (GEqualFunc)_purple_blist_hbuddy_equal,
+					 (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL);
+
+	gbl->buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+					 NULL, (GDestroyNotify)g_hash_table_destroy);
+
+	for (account = purple_accounts_get_all(); account != NULL; account = account->next)
+	{
+		purple_blist_buddies_cache_add_account(account->data);
+	}
+
+	if (ui_ops != NULL && ui_ops->new_list != NULL)
+		ui_ops->new_list(gbl);
+
+  gbl->save_timer = 0;
+  gbl->blist_loaded = FALSE;
+
+	purple_blist_load();
 }
 
-GType
+static GType
 purple_blist_get_gtype(void)
 {
 	static GType type = 0;
============================================================
--- libpurple/blist.h	5f470b36e09fe44795e394e2dc1db4fbac5eb390
+++ libpurple/blist.h	d31474274e3055856afc575bb16a73429a28e2b7
@@ -121,17 +121,8 @@ typedef struct _PurpleChatClass PurpleCh
 #define PURPLE_IS_CHAT_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_CHAT_TYPE))
 #define PURPLE_GET_CHAT_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_CHAT_TYPE, PurpleChatClass))
 
-/** @copydoc _PurpleBlist */
 typedef struct _PurpleBuddyList PurpleBuddyList;
-typedef struct _PurpleBuddyListClass PurpleBuddyListClass;
-#define PURPLE_BUDDY_LIST_TYPE                  (purple_blist_get_gtype ())
-#define PURPLE_BUDDY_LIST(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_BUDDY_LIST_TYPE, PurpleBuddyList))
-#define PURPLE_IS_BUDDY_LIST(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_BUDDY_LIST_TYPE))
-#define PURPLE_BUDDY_LIST_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_BUDDY_LIST_TYPE, PurpleBuddyListClass))
-#define PURPLE_IS_BUDDY_LIST_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_BUDDY_LIST_TYPE))
-#define PURPLE_GET_BUDDY_LIST_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_BUDDY_LIST_TYPE, PurpleBuddyListClass))
 
-
 #include "account.h"
 #include "buddyicon.h"
 #include "status.h"
@@ -248,30 +239,6 @@ struct _PurpleChatClass {
 #endif
 #if !(defined PURPLE_HIDE_STRUCTS) || (defined _PURPLE_BLIST_C_)
 
-/**
- * The Buddy List
- */
-struct _PurpleBuddyList {
-  PurpleObject parent;
-	PurpleBlistNode *root;          /**< The first node in the buddy list */
-	GHashTable *buddies;          /**< Every buddy in this list */
-  
-  /**
-   * A hash table used for efficient lookups of buddies by name.
-   * PurpleAccount* => GHashTable*, with the inner hash table being
-   * struct _purple_hbuddy => PurpleBuddy*
-   */
-  GHashTable *buddies_cache;
-
-  guint          save_timer;
-  gboolean       blist_loaded;
-	void *ui_data;                /**< UI-specific data. */
-};
-
-struct _PurpleBuddyListClass {
-  PurpleObjectClass parent;
-};
-
 #endif /* PURPLE_HIDE_STRUCTS && PURPLE_BLIST_STRUCTS */
 
 /**
@@ -282,7 +249,7 @@ struct _PurpleBlistUiOps
  */
 struct _PurpleBlistUiOps
 {
-	void (*new_list)(PurpleBuddyList *list); /**< Sets UI-specific data on a buddy list. */
+	void (*new_list)(); /**< Sets UI-specific data on a buddy list. */
 	void (*new_node)(PurpleBlistNode *node); /**< Sets UI-specific data on a node. */
 	void (*show)(PurpleBuddyList *list);     /**< The core will call this when it's finished doing its core stuff */
 	void (*update)(PurpleBuddyList *list,
@@ -357,13 +324,6 @@ PurpleBuddyList *purple_blist_new(void);
 PurpleBuddyList *purple_blist_new(void);
 
 /**
- * Sets the main buddy list.
- *
- * @param blist The buddy list you want to use.
- */
-void purple_set_blist(PurpleBuddyList *blist);
-
-/**
  * Returns the main buddy list.
  *
  * @return The main buddy list.
@@ -1313,16 +1273,6 @@ void *purple_blist_get_handle(void);
 void *purple_blist_get_handle(void);
 
 /**
- * Initializes the buddy list subsystem.
- */
-void purple_blist_init(void);
-
-/**
- * Uninitializes the buddy list subsystem.
- */
-void purple_blist_uninit(void);
-
-/**
  * Get the GType for PurpleBlistNode
  */
 GType purple_blist_node_get_gtype(void);
@@ -1347,11 +1297,6 @@ GType purple_chat_get_gtype(void);
  */
 GType purple_chat_get_gtype(void);
 
-/**
- * Get the GType for PurpleChat
- */
-GType purple_blist_get_gtype(void);
-
 /*@}*/
 
 #ifdef __cplusplus
============================================================
--- libpurple/buddy.c	de743f7f3cee9667dd2b93a33df681af5fd7119a
+++ libpurple/buddy.c	fb407ea19d330477168e7a1877e19c95393e4a01
@@ -84,25 +84,6 @@ parse_buddy(PurpleGroup *group, PurpleCo
 	g_free(alias);
 }
 
-static void
-append_buddy(gpointer key, gpointer value, gpointer user_data)
-{
-	GSList **list = user_data;
-	*list = g_slist_prepend(*list, value);
-}
-
-GSList *
-purple_blist_get_buddies()
-{
-	GSList *buddies = NULL;
-
-	if (!purplebuddylist)
-		return NULL;
-
-	g_hash_table_foreach(purplebuddylist->buddies, append_buddy, &buddies);
-	return buddies;
-}
-
 void
 purple_blist_update_buddy_status(PurpleBuddy *buddy, PurpleStatus *old_status)
 {
@@ -163,47 +144,6 @@ purple_blist_update_buddy_icon(PurpleBud
 	purple_blist_update_node_icon((PurpleBlistNode *)buddy);
 }
 
-/*
- * TODO: Maybe remove the call to this from server.c and call it
- * from oscar.c and toc.c instead?
- */
-void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name)
-{
-	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
-	struct _purple_hbuddy *hb, *hb2;
-	GHashTable *account_buddies;
-
-	g_return_if_fail(buddy != NULL);
-
-	hb = g_new(struct _purple_hbuddy, 1);
-	hb->name = g_strdup(purple_normalize(buddy->account, buddy->name));
-	hb->account = buddy->account;
-	hb->group = ((PurpleBlistNode *)buddy)->parent->parent;
-	g_hash_table_remove(purplebuddylist->buddies, hb);
-	
-	account_buddies = g_hash_table_lookup(purplebuddylist->buddies_cache, buddy->account);
-	g_hash_table_remove(account_buddies, hb);
-
-	g_free(hb->name);
-	hb->name = g_strdup(purple_normalize(buddy->account, name));
-	g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
-
-	hb2 = g_new(struct _purple_hbuddy, 1);
-	hb2->name = g_strdup(hb->name);
-	hb2->account = buddy->account;
-	hb2->group = ((PurpleBlistNode *)buddy)->parent->parent;
-
-	g_hash_table_replace(account_buddies, hb2, buddy);
-
-	g_free(buddy->name);
-	buddy->name = g_strdup(name);
-
-	purple_blist_schedule_save();
-
-	if (ops && ops->update)
-		ops->update(purplebuddylist, (PurpleBlistNode *)buddy);
-}
-
 void purple_blist_alias_buddy(PurpleBuddy *buddy, const char *alias)
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
@@ -468,49 +408,12 @@ const char *purple_buddy_get_local_alias
 	return buddy->name;
 }
 
-PurpleBuddy *purple_find_buddy_in_group(PurpleAccount *account, const char *name,
-		PurpleGroup *group)
-{
-	struct _purple_hbuddy hb;
-	PurpleBuddy *ret;
-
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
-	g_return_val_if_fail(account != NULL, NULL);
-	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
-
-	hb.name = g_strdup(purple_normalize(account, name));
-	hb.account = account;
-	hb.group = (PurpleBlistNode*)group;
-
-	ret = g_hash_table_lookup(purplebuddylist->buddies, &hb);
-	g_free(hb.name);
-
-	return ret;
-}
-
-PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy)
-{
-	g_return_val_if_fail(buddy != NULL, NULL);
-
-	return PURPLE_CONTACT(PURPLE_BLIST_NODE(buddy)->parent);
-}
-
 PurplePresence *purple_buddy_get_presence(const PurpleBuddy *buddy)
 {
 	g_return_val_if_fail(buddy != NULL, NULL);
 	return buddy->presence;
 }
 
-PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy)
-{
-	g_return_val_if_fail(buddy != NULL, NULL);
-
-	if (((PurpleBlistNode *)buddy)->parent == NULL)
-		return NULL;
-
-	return (PurpleGroup *)(((PurpleBlistNode*)buddy)->parent->parent);
-}
-
 xmlnode *
 buddy_to_xmlnode(PurpleBlistNode *bnode)
 {
============================================================
--- libpurple/chat.c	8595dfb9c5997c5fedfede29389284799fdc9e0d
+++ libpurple/chat.c	03ee904bb0786df9e46b166cff0f8d4389023c92
@@ -222,70 +222,6 @@ const char *purple_chat_get_name(PurpleC
 	return ret;
 }
 
-PurpleChat *
-purple_blist_find_chat(PurpleAccount *account, const char *name)
-{
-	char *chat_name;
-	PurpleChat *chat;
-	PurplePlugin *prpl;
-	PurplePluginProtocolInfo *prpl_info = NULL;
-	struct proto_chat_entry *pce;
-	PurpleBlistNode *node, *group;
-	GList *parts;
-	char *normname;
-
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
-	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
-
-	if (!purple_account_is_connected(account))
-		return NULL;
-
-	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
-
-	if (prpl_info->find_blist_chat != NULL)
-		return prpl_info->find_blist_chat(account, name);
-
-	normname = g_strdup(purple_normalize(account, name));
-	for (group = purplebuddylist->root; group != NULL; group = group->next) {
-		for (node = group->child; node != NULL; node = node->next) {
-			if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
-
-				chat = (PurpleChat*)node;
-
-				if (account != chat->account)
-					continue;
-
-				parts = prpl_info->chat_info(
-					purple_account_get_connection(chat->account));
-
-				pce = parts->data;
-				chat_name = g_hash_table_lookup(chat->components,
-												pce->identifier);
-				g_list_foreach(parts, (GFunc)g_free, NULL);
-				g_list_free(parts);
-
-				if (chat->account == account && chat_name != NULL &&
-					normname != NULL && !strcmp(purple_normalize(account, chat_name), normname)) {
-					g_free(normname);
-					return chat;
-				}
-			}
-		}
-	}
-
-	g_free(normname);
-	return NULL;
-}
-
-PurpleGroup *
-purple_chat_get_group(PurpleChat *chat)
-{
-	g_return_val_if_fail(chat != NULL, NULL);
-
-	return (PurpleGroup *)(((PurpleBlistNode *)chat)->parent);
-}
-
 PurpleAccount *
 purple_chat_get_account(PurpleChat *chat)
 {
============================================================
--- libpurple/contact.c	a8ae7dc696106f0e24928b9645bdf1afddf16fb7
+++ libpurple/contact.c	4af19eec0312a1158acd589fbf45edf7339fb908
@@ -213,6 +213,13 @@ PurpleContact *purple_contact_new()
 	return contact;
 }
 
+PurpleContact *purple_buddy_get_contact(PurpleBuddy *buddy)
+{
+	g_return_val_if_fail(buddy != NULL, NULL);
+
+	return PURPLE_CONTACT(PURPLE_BLIST_NODE(buddy)->parent);
+}
+
 void
 purple_contact_destroy(PurpleContact *contact)
 {
============================================================
--- libpurple/core.c	edc7cf35019bb3ebb8925f0b76a75aa160aa74e0
+++ libpurple/core.c	ddb7889d2a1720941bb0e529b9c5e8cc08d61095
@@ -41,6 +41,7 @@
 #include "pounce.h"
 #include "prefs.h"
 #include "privacy.h"
+#include "private.h"
 #include "proxy.h"
 #include "savedstatuses.h"
 #include "signals.h"
@@ -127,6 +128,9 @@ purple_core_init(const char *ui)
 		if (ops->debug_ui_init != NULL)
 			ops->debug_ui_init();
 	}
+  
+  if (ops != NULL && ops->ui_init != NULL)
+    ops->ui_init();
 
 #ifdef HAVE_DBUS
 	purple_dbus_init();
@@ -164,6 +168,7 @@ purple_core_init(const char *ui)
 	purple_log_init();
 	purple_network_init();
 	purple_privacy_init();
+  purple_blist_init();
 	purple_pounces_init();
 	purple_proxy_init();
 	purple_dnsquery_init();
@@ -180,9 +185,6 @@ purple_core_init(const char *ui)
 	 */
 	purple_network_get_my_ip(-1);
 
-	if (ops != NULL && ops->ui_init != NULL)
-		ops->ui_init();
-
 	/* The UI may have registered some theme types, so refresh them */
 	purple_theme_manager_refresh();
 
============================================================
--- libpurple/example/nullclient.c	29bb6e52a8623a7c20ad0c4e78c35efa8aa72c43
+++ libpurple/example/nullclient.c	47a85444846d0e2b543ece02710fecab89140be4
@@ -210,10 +210,6 @@ init_libpurple(void)
 		abort();
 	}
 
-	/* Create and load the buddylist. */
-	purple_set_blist(purple_blist_new());
-	purple_blist_load();
-
 	/* Load the preferences. */
 	purple_prefs_load();
 
============================================================
--- libpurple/group.c	9dc8d909ae3e494356bc245b70eec0340e56d16f
+++ libpurple/group.c	9de45f5f7fd9161877144547a6ef9b25a13f5382
@@ -73,33 +73,6 @@ group_to_xmlnode(PurpleBlistNode *gnode)
 	return node;
 }
 
-void
-parse_group(xmlnode *groupnode)
-{
-	const char *name = xmlnode_get_attrib(groupnode, "name");
-	PurpleGroup *group;
-	xmlnode *cnode;
-
-	if (!name)
-		name = _("Buddies");
-
-	group = purple_group_new(name);
-	purple_blist_add_group(group,
-			purple_blist_get_last_sibling(purplebuddylist->root));
-
-	for (cnode = groupnode->child; cnode; cnode = cnode->next) {
-		if (cnode->type != XMLNODE_TYPE_TAG)
-			continue;
-		if (purple_strequal(cnode->name, "setting"))
-			parse_setting((PurpleBlistNode*)group, cnode);
-		else if (purple_strequal(cnode->name, "contact") ||
-				purple_strequal(cnode->name, "person"))
-			parse_contact(group, cnode);
-		else if (purple_strequal(cnode->name, "chat"))
-			parse_chat(group, cnode);
-	}
-}
-
 /*
  * TODO: If merging, prompt the user if they want to merge.
  */
@@ -236,6 +209,16 @@ void purple_blist_rename_group(PurpleGro
 	g_free(old_name);
 }
 
+PurpleGroup *purple_buddy_get_group(PurpleBuddy *buddy)
+{
+	g_return_val_if_fail(buddy != NULL, NULL);
+
+	if (((PurpleBlistNode *)buddy)->parent == NULL)
+		return NULL;
+
+	return (PurpleGroup *)(((PurpleBlistNode*)buddy)->parent->parent);
+}
+
 void
 purple_group_destroy(PurpleGroup *group)
 {
@@ -244,21 +227,6 @@ purple_group_destroy(PurpleGroup *group)
   g_object_unref(G_OBJECT(group));
 }
 
-PurpleGroup *purple_find_group(const char *name)
-{
-	PurpleBlistNode *node;
-
-	g_return_val_if_fail(purplebuddylist != NULL, NULL);
-	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
-
-	for (node = purplebuddylist->root; node != NULL; node = node->next) {
-		if (!purple_utf8_strcasecmp(((PurpleGroup *)node)->name, name))
-			return (PurpleGroup *)node;
-	}
-
-	return NULL;
-}
-
 const char *purple_group_get_name(PurpleGroup *group)
 {
 	g_return_val_if_fail(group != NULL, NULL);
============================================================
--- pidgin/gtkblist.c	cd75b9b4d5f0a9ec8e3479448b45766084033548
+++ pidgin/gtkblist.c	c5197b43c71a9509252e22bdbe94a1e6412fb8c6
@@ -1005,7 +1005,7 @@ make_blist_request_dialog(PidginBlistReq
 	img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION,
 		gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE));
 
-	gtkblist = PIDGIN_BLIST(purple_get_blist());
+	gtkblist = purple_blist_get_ui_data();
 	blist_window = gtkblist ? GTK_WINDOW(gtkblist->window) : NULL;
 
 	data->window = gtk_dialog_new_with_buttons(title,
@@ -4256,7 +4256,7 @@ static gboolean pidgin_blist_refresh_tim
 			|| !GTK_WIDGET_VISIBLE(gtkblist->window))
 		return TRUE;
 
-	for(gnode = list->root; gnode; gnode = gnode->next) {
+	for(gnode = purple_blist_get_root(); gnode; gnode = gnode->next) {
 		if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))
 			continue;
 		for(cnode = gnode->child; cnode; cnode = cnode->next) {
@@ -4349,7 +4349,7 @@ sign_on_off_cb(PurpleConnection *gc, Pur
 static void
 sign_on_off_cb(PurpleConnection *gc, PurpleBuddyList *blist)
 {
-	PidginBuddyList *gtkblist = PIDGIN_BLIST(blist);
+	PidginBuddyList *gtkblist = purple_blist_get_ui_data();
 
 	update_menu_bar(gtkblist);
 }
@@ -4604,7 +4604,7 @@ static void pidgin_blist_new_list(Purple
 												g_direct_equal, NULL, g_free);
 	gtkblist->priv = g_new0(PidginBuddyListPrivate, 1);
 
-	blist->ui_data = gtkblist;
+	purple_blist_set_ui_data(gtkblist);
 }
 
 static void pidgin_blist_new_node(PurpleBlistNode *node)
@@ -5346,7 +5346,7 @@ treeview_style_set (GtkWidget *widget,
 		    gpointer data)
 {
 	PurpleBuddyList *list = data;
-	PurpleBlistNode *node = list->root;
+	PurpleBlistNode *node = purple_blist_get_root();
 	while (node) {
 		pidgin_blist_update_group(list, node);
 		node = node->next;
@@ -5609,7 +5609,7 @@ static void pidgin_blist_show(PurpleBudd
 		return;
 	}
 
-	gtkblist = PIDGIN_BLIST(list);
+	gtkblist = purple_blist_get_ui_data();
 	priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist);
 
 	if (priv->current_theme)
@@ -5970,11 +5970,11 @@ static void redo_buddy_list(PurpleBuddyL
 {
 	PurpleBlistNode *node;
 
-	gtkblist = PIDGIN_BLIST(list);
+	gtkblist = purple_blist_get_ui_data();
 	if(!gtkblist || !gtkblist->treeview)
 		return;
 
-	node = list->root;
+	node = purple_blist_get_root();
 
 	while (node)
 	{
@@ -6007,7 +6007,7 @@ pidgin_blist_update_refresh_timeout()
 	PidginBuddyList *gtkblist;
 
 	blist = purple_get_blist();
-	gtkblist = PIDGIN_BLIST(purple_get_blist());
+	gtkblist = purple_blist_get_ui_data();
 
 	gtkblist->refresh_timer = purple_timeout_add_seconds(30,(GSourceFunc)pidgin_blist_refresh_timer, blist);
 }
@@ -6680,7 +6680,7 @@ static void pidgin_blist_update(PurpleBu
 static void pidgin_blist_update(PurpleBuddyList *list, PurpleBlistNode *node)
 {
 	if (list)
-		gtkblist = PIDGIN_BLIST(list);
+		gtkblist = purple_blist_get_ui_data();
 	if(!gtkblist || !gtkblist->treeview || !node)
 		return;
 
@@ -6792,13 +6792,13 @@ groups_tree(void)
 	g_list_free(list);
 	list = NULL;
 
-	if (purple_get_blist()->root == NULL)
+	if (purple_blist_get_root() == NULL)
 	{
 		list  = g_list_append(list, (gpointer)_("Buddies"));
 	}
 	else
 	{
-		for (gnode = purple_get_blist()->root;
+		for (gnode = purple_blist_get_root();
 			 gnode != NULL;
 			 gnode = gnode->next)
 		{
@@ -7248,7 +7248,7 @@ static void account_signon_cb(PurpleConn
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleBlistNode *gnode, *cnode;
-	for(gnode = purple_get_blist()->root; gnode; gnode = gnode->next)
+	for(gnode = purple_blist_get_root(); gnode; gnode = gnode->next)
 	{
 		if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))
 			continue;
============================================================
--- pidgin/gtkmain.c	f36172267a94857d601ece461df9c39d211c82f0
+++ pidgin/gtkmain.c	757d35546d07e4de3a9f8a7871ef6053526e2498
@@ -806,10 +806,6 @@ int main(int argc, char *argv[])
 		return 0;
 	}
 
-	/* TODO: Move blist loading into purple_blist_init() */
-	purple_set_blist(purple_blist_new());
-	purple_blist_load();
-
 	/* load plugins we had when we quit */
 	purple_plugins_load_saved(PIDGIN_PREFS_ROOT "/plugins/loaded");
 
============================================================
--- pidgin/gtkutils.c	bd845edb06c1a57c115f26e167911774c6b31a28
+++ pidgin/gtkutils.c	5d665ed041878b9f2a465ab9e8642a53d109ccc5
@@ -2157,7 +2157,7 @@ add_completion_list(PidginCompletionData
 	g_completion_clear_items(data->completion);
 #endif /* NEW_STYLE_COMPLETION */
 
-	for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next)
+	for (gnode = purple_blist_get_root(); gnode != NULL; gnode = gnode->next)
 	{
 		if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
 			continue;


More information about the Commits mailing list