changeset 20456:db286cc82bd1

propagate from branch 'im.pidgin.pidgin' (head f43d7ef3f18aadf88e22f93a8131f4fac26d5b53) to branch 'im.pidgin.cpw.khc.msnp14' (head c9e104b21b211b41266f2b10a225152a47c166cc)
author Ka-Hing Cheung <khc@hxbc.us>
date Tue, 19 Jun 2007 17:28:41 +0000
parents ef2e720f1b8f (current diff) 9c17cdcfc799 (diff)
children c9bcf4f11e30
files libpurple/internal.h libpurple/protocols/msn/msn-utils.c libpurple/protocols/msn/msn-utils.h libpurple/protocols/msn/msn.c
diffstat 118 files changed, 1354 insertions(+), 878 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Sat Jun 16 07:03:31 2007 +0000
+++ b/ChangeLog.API	Tue Jun 19 17:28:41 2007 +0000
@@ -13,21 +13,13 @@
 		    UIs can now use better scheduling for whole-second timers.  For
 		    example, clients based on the glib event loop can now use
 		    g_timeout_add_seconds.
-		* gtk_imhtml_setup_entry
-		* pidgin_create_window
 		* purple_blist_node_get_type
 		* purple_conversation_do_command
 		* purple_conversation_get_extended_menu
 		* purple_core_ensure_single_instance
 		    This is for UIs to use to ensure only one copy is running.
 		* purple_dbus_is_owner
-		* purple_dbusify_const_GList
-		* purple_dbusify_const_GSList
-		* purple_const_GList_to_array
-		* purple_const_GSList_to_array
 		* purple_image_data_calculate_filename
-		* pidgin_retrieve_user_info, shows immediate feedback when getting
-		  information about a user.
 		* purple_timeout_add_seconds
 		    Callers should prefer this to purple_timeout_add for timers
 		    longer than 1 second away.  Be aware of the rounding, though.
@@ -35,11 +27,12 @@
 		    Callers should prefer this to purple_timeout_add for timers
 		    longer than 1 second away.  Be aware of the rounding, though.
 		* purple_xfer_get_remote_user
-		* gtk_imhtml_animation_new
-		    Can be used for inserting an animated image into an IMHTML.
+		* purple_pounces_get_all_for_ui
 
 		Changed:
-		* Mark some return types const:
+		* The documentation of the following functions now properly
+		  declares that the returned value must not be modified or
+		  freed, which was always the case:
 			* purple_accounts_get_all
 			* purple_connections_get_all
 			* purple_connections_get_connecting
@@ -49,26 +42,57 @@
 			* purple_get_conversations
 			* purple_get_ims
 			* purple_notify_user_info_get_entries
-
-		Deprecated:
-		* purple_dbusify_GList:  Use purple_dbusify_const_GList (and
-		  g_list_free if needed) if depending on 2.1.0 is okay.
-		* purple_dbusify_GSList:  Use purple_dbusify_const_GSList (and
-		  g_slist_free if needed) if depending on 2.1.0 is okay..
-		* purple_GList_to_array:  Use purple_const_GList_to_array (and
-		  g_list_free if needed) if depending on 2.1.0 is okay..
-		* purple_GSList_to_array:  Use purple_const_GSList_to_array (and
-		  g_slist_free if needed) if depending on 2.1.0 is okay..
+		* The following functions now return a GList* instead of a
+		  const GList*, as const is not very useful with GLists.  The
+		  returned value still must not be modified or freed:
+			* purple_account_get_status_types
+			* purple_mime_document_get_fields
+			* purple_mime_document_get_parts
+			* purple_mime_part_get_fields
+			* purple_request_fields_get_required
+			* purple_request_field_list_get_selected
+			* purple_request_field_list_get_items
+			* purple_status_type_get_attrs
+			* purple_presence_get_statuses
+		* purple_request_field_list_set_selected now takes a GList*
+		  instead of a const GList* for items, as const is not very
+		  useful with GLists.  The passed list is still not modified
+		  or freed.
+		* purple_presence_add_list now takes a GList* instead of a
+		  const GList* for source_list, as const is not very useful with
+		  GLists.  The passed list is still not modified or freed.
 
 	Pidgin:
+		Added:
+		* gtk_imhtml_setup_entry
+		* pidgin_create_window
+		* pidgin_retrieve_user_info, shows immediate feedback when getting
+		  information about a user.
+		* gtk_imhtml_animation_new
+		    Can be used for inserting an animated image into an IMHTML.
+		* pidgin_menu_position_func_helper
+		* pidgin_blist_get_name_markup, returns the buddy list markup
+		  text for a given buddy.
+
 		Changed:
 		* pidgin_append_menu_action returns the menuitem added to the menu.
 		* pidgin_separator returns the separator added to the menu.
+		* PidginConversation has struct members to handle the new info
+		  pane:
+		  	* infopane
+			* infopane_hbox
+			* infopane_model
+			* infopane_iter
 
 	Finch:
 		Added:
 		* finch_retrieve_user_info
 
+		Changed:
+		* gnt_tree_get_rows() now returns a GList* instead of a const
+		  GList*, as const is not very useful with GLists.  The
+		  returned value still must not be modified or freed.
+
 version 2.0.2 (6/14/2007):
 	Pidgin:
 		Deprecated:
--- a/configure.ac	Sat Jun 16 07:03:31 2007 +0000
+++ b/configure.ac	Tue Jun 19 17:28:41 2007 +0000
@@ -47,7 +47,7 @@
 m4_define([purple_major_version], [2])
 m4_define([purple_minor_version], [1])
 m4_define([purple_micro_version], [0])
-m4_define([purple_version_suffix], [])
+m4_define([purple_version_suffix], [devel])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
 m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix]))
@@ -56,7 +56,7 @@
 m4_define([gnt_major_version], [2])
 m4_define([gnt_minor_version], [0])
 m4_define([gnt_micro_version], [0])
-m4_define([gnt_version_suffix], [])
+m4_define([gnt_version_suffix], [devel])
 m4_define([gnt_version],
           [gnt_major_version.gnt_minor_version.gnt_micro_version])
 m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
--- a/doc/gtkrc-2.0	Sat Jun 16 07:03:31 2007 +0000
+++ b/doc/gtkrc-2.0	Tue Jun 19 17:28:41 2007 +0000
@@ -39,16 +39,17 @@
 }
 widget_class "*" style "my-style-name"
 
-# This style sets the expander size on a treeview to 0, which has the result
+# This sets the expander size on a treeview to 0, which has the result
 # of reducing the indent for items in the tree. This can be applied to the
-# Pidgin buddy list to reduce it's width.
-style "my-narrow-tree"
-{
-  GtkTreeView::expander_size = 0
-}
-
+# Pidgin buddy list to reduce the width of group and contact rows.
+# With the recent (~2.0.0) buddy list changes this isn't particularly
+# important anymore.
+#style "my-narrow-tree"
+#{
+#  GtkTreeView::expander_size = 0
+#}
 # And apply the style to the buddy list:
-widget "*pidgin_blist_treeview" style "my-narrow-tree"
+#widget "*pidgin_blist_treeview" style "my-narrow-tree"
 
 # In Pidgin, you can set custom keybindings in your theme.
 # Here is an example to follow:
--- a/finch/gntaccount.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/gntaccount.c	Tue Jun 19 17:28:41 2007 +0000
@@ -641,7 +641,7 @@
 
 void finch_accounts_show_all()
 {
-	const GList *iter;
+	GList *iter;
 	GntWidget *box, *button;
 
 	if (accounts.window)
@@ -734,7 +734,7 @@
 
 void finch_accounts_init()
 {
-	const GList *iter;
+	GList *iter;
 
 	purple_signal_connect(purple_accounts_get_handle(), "account-added",
 			finch_accounts_get_handle(), PURPLE_CALLBACK(account_added_callback),
@@ -831,7 +831,7 @@
 {
 	PurpleConnection *gc = purple_account_get_connection(data->account);
 
-	if (g_list_find((GList *)purple_connections_get_all(), gc))
+	if (g_list_find(purple_connections_get_all(), gc))
 	{
 		purple_blist_request_add_buddy(data->account, data->username,
 									 NULL, data->alias);
--- a/finch/gntft.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/gntft.c	Tue Jun 19 17:28:41 2007 +0000
@@ -86,7 +86,7 @@
 static void
 update_title_progress()
 {
-	const GList *list;
+	GList *list;
 	int num_active_xfers = 0;
 	guint64 total_bytes_xferred = 0;
 	guint64 total_file_size = 0;
@@ -172,7 +172,7 @@
 void
 finch_xfer_dialog_new(void)
 {
-	const GList *iter;
+	GList *iter;
 	GntWidget *window;
 	GntWidget *bbox;
 	GntWidget *button;
@@ -411,7 +411,7 @@
 
 	size_str      = purple_str_size_to_units(purple_xfer_get_size(xfer));
 	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));
-	kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
+	kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps);
 
 	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS,
 			g_ascii_dtostr(prog_str, sizeof(prog_str), purple_xfer_get_progress(xfer) * 100.));
--- a/finch/gntpounce.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/gntpounce.c	Tue Jun 19 17:28:41 2007 +0000
@@ -137,12 +137,12 @@
 static void
 populate_pounces_list(PouncesManager *dialog)
 {
-	const GList *pounces;
+	GList *pounces;
 
 	gnt_tree_remove_all(GNT_TREE(dialog->tree));
 
-	for (pounces = purple_pounces_get_all(); pounces != NULL;
-			pounces = g_list_next(pounces))
+	for (pounces = purple_pounces_get_all_for_ui(FINCH_UI); pounces != NULL;
+			pounces = g_list_delete_link(pounces, pounces))
 	{
 		add_pounce_to_treeview(GNT_TREE(dialog->tree), pounces->data);
 	}
@@ -288,7 +288,7 @@
 	GntWidget *hbox, *vbox;
 	GntWidget *button;
 	GntWidget *combo;
-	const GList *list;
+	GList *list;
 
 	g_return_if_fail((cur_pounce != NULL) ||
 	                 (account != NULL) ||
@@ -303,7 +303,7 @@
 		dialog->pounce  = NULL;
 		dialog->account = account;
 	} else {
-		const GList *connections = purple_connections_get_all();
+		GList *connections = purple_connections_get_all();
 		PurpleConnection *gc;
 
 		if (connections != NULL) {
--- a/finch/gntprefs.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/gntprefs.c	Tue Jun 19 17:28:41 2007 +0000
@@ -89,7 +89,7 @@
 get_status_titles()
 {
 	GList *list = NULL;
-	const GList *iter;
+	GList *iter;
 	for (iter = purple_savedstatuses_get_all(); iter; iter = iter->next) {
 		char *str;
 		if (purple_savedstatus_is_transient(iter->data))
--- a/finch/gntrequest.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/gntrequest.c	Tue Jun 19 17:28:41 2007 +0000
@@ -297,7 +297,7 @@
 				GList *list = NULL;
 				if (purple_request_field_list_get_multi_select(field))
 				{
-					const GList *iter;
+					GList *iter;
 					GntWidget *tree = field->ui_data;
 
 					iter = purple_request_field_list_get_items(field);
@@ -433,7 +433,7 @@
 			else if (type == PURPLE_REQUEST_FIELD_CHOICE)
 			{
 				int id;
-				const GList *list;
+				GList *list;
 				GntWidget *combo = gnt_combo_box_new();
 				gnt_box_add_widget(GNT_BOX(hbox), combo);
 				field->ui_data = combo;
@@ -449,7 +449,7 @@
 			}
 			else if (type == PURPLE_REQUEST_FIELD_LIST)
 			{
-				const GList *list;
+				GList *list;
 				gboolean multi = purple_request_field_list_get_multi_select(field);
 				if (multi)
 				{
@@ -490,7 +490,7 @@
 			{
 				gboolean all;
 				PurpleAccount *def;
-				const GList *list;
+				GList *list;
 				GntWidget *combo = gnt_combo_box_new();
 				gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
 				gnt_box_add_widget(GNT_BOX(hbox), combo);
--- a/finch/gntstatus.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/gntstatus.c	Tue Jun 19 17:28:41 2007 +0000
@@ -83,7 +83,7 @@
 static void
 populate_statuses(GntTree *tree)
 {
-	const GList *list;
+	GList *list;
 
 	for (list = purple_savedstatuses_get_all(); list; list = list->next)
 	{
@@ -244,7 +244,7 @@
 static void
 set_substatuses(EditStatus *edit)
 {
-	const GList *iter;
+	GList *iter;
 	for (iter = gnt_tree_get_rows(GNT_TREE(edit->tree)); iter; iter = iter->next) {
 		RowInfo *key = iter->data;
 		if (gnt_tree_get_choice(GNT_TREE(edit->tree), key)) {
@@ -410,7 +410,7 @@
 		EditSubStatus *sub;
 		GntWidget *window, *combo, *entry, *box, *button, *l;
 		PurpleSavedStatusSub *substatus = NULL;
-		const GList *iter;
+		GList *iter;
 		char *name;
 		RowInfo *selected = gnt_tree_get_selection_data(tree);
 		PurpleAccount *account = selected->account;
@@ -497,7 +497,7 @@
 	GntWidget *window, *box, *button, *entry, *combo, *label, *tree;
 	PurpleStatusPrimitive prims[] = {PURPLE_STATUS_AVAILABLE, PURPLE_STATUS_AWAY,
 		PURPLE_STATUS_INVISIBLE, PURPLE_STATUS_OFFLINE, PURPLE_STATUS_UNSET}, current;
-	const GList *iter;
+	GList *iter;
 	int i;
 
 	if (saved)
--- a/finch/libgnt/gnttree.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/libgnt/gnttree.c	Tue Jun 19 17:28:41 2007 +0000
@@ -303,7 +303,7 @@
 
 		notfirst = TRUE;
 
-		if (len > width - 2) {
+		if (len > width) {
 			len = width - 1;
 			cut = TRUE;
 		}
@@ -1017,7 +1017,7 @@
 	return ret;
 }
 
-const GList *gnt_tree_get_rows(GntTree *tree)
+GList *gnt_tree_get_rows(GntTree *tree)
 {
 	return tree->list;
 }
--- a/finch/libgnt/gnttree.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/libgnt/gnttree.h	Tue Jun 19 17:28:41 2007 +0000
@@ -190,7 +190,13 @@
  */
 GList * gnt_tree_get_selection_text_list(GntTree *tree);
 
-const GList *gnt_tree_get_rows(GntTree *tree);
+/**
+ *
+ * @param tree
+ *
+ * @constreturn
+ */
+GList *gnt_tree_get_rows(GntTree *tree);
 
 /**
  * 
--- a/finch/libgnt/gntwm.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/libgnt/gntwm.h	Tue Jun 19 17:28:41 2007 +0000
@@ -163,7 +163,7 @@
 	/* List of windows. Although the WM can keep a list of its own for the windows,
 	 * it'd be better if there was a way to share between the 'core' and the WM.
 	 */
-	/*const GList *(*window_list)();*/
+	/*GList *(*window_list)();*/
 
 	void (*res1)(void);
 	void (*res2)(void);
--- a/finch/libgnt/wms/irssi.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/libgnt/wms/irssi.c	Tue Jun 19 17:28:41 2007 +0000
@@ -177,7 +177,8 @@
 {
 	char title[256];
 	snprintf(title, sizeof(title), "%d: %s",
-			(int)g_object_get_data(G_OBJECT(node->me), "irssi-index") + 1, GNT_BOX(node->me)->title);
+			GPOINTER_TO_INT(g_object_get_data(G_OBJECT(node->me), "irssi-index")) + 1,
+			GNT_BOX(node->me)->title);
 	wbkgdset(node->window, '\0' | COLOR_PAIR(gnt_widget_has_focus(node->me) ? GNT_COLOR_TITLE : GNT_COLOR_TITLE_D));
 	mvwaddstr(node->window, 0, 0, title);
 	update_panels();
@@ -226,7 +227,7 @@
 
 	find_window_position(irssi, win, &hor, &vert);
 
-	switch ((int)list->data) {
+	switch (GPOINTER_TO_INT(list->data)) {
 		case 'k':
 			vert = MAX(0, vert - 1);
 			break;
--- a/finch/libgnt/wms/s.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/libgnt/wms/s.c	Tue Jun 19 17:28:41 2007 +0000
@@ -121,7 +121,7 @@
 static GntWidget *
 find_widget(GntWM *wm, const char *wname)
 {
-	const GList *iter = wm->cws->list;
+	GList *iter = wm->cws->list;
 	for (; iter; iter = iter->next) {
 		GntWidget *widget = iter->data;
 		const char *name = gnt_widget_get_name(widget);
--- a/finch/plugins/Makefile.am	Sat Jun 16 07:03:31 2007 +0000
+++ b/finch/plugins/Makefile.am	Tue Jun 19 17:28:41 2007 +0000
@@ -28,7 +28,7 @@
 
 endif # PLUGINS
 
-EXTRA_DIST = 
+EXTRA_DIST = pietray.py
 
 AM_CPPFLAGS = \
 	-DDATADIR=\"$(datadir)\" \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/pietray.py	Tue Jun 19 17:28:41 2007 +0000
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+
+# This is a dbus script to show a docklet for Finch. This should work
+# for any 'compatible' purple client.
+#
+# By 'compatible', I mean any client that sets and updates the
+# "unseen-count" data on the conversations.
+#
+# It allows doing the following things:
+#    - It allows changing status.
+#    - It shows the current status and info about unread messages in
+#      the tooltip.
+#    - It can blink on unread IM/Chat messages, and it allows canging
+#      the preference for that.
+# 
+# It requires GTK+ 2.10 or above, since it uses GtkStatusIcon.
+# 
+# Sadrul <sadrul@pidgin.im>
+
+import pygtk
+pygtk.require("2.0")
+import gtk
+import dbus, gobject, dbus.glib
+import os # to get the pkg-config output
+
+bus = dbus.SessionBus()
+obj = bus.get_object(
+    "im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
+purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
+
+def pack_image_label(menu, image, label):
+	item = gtk.ImageMenuItem(label)
+	if image:
+		img = gtk.Image()
+		img.set_from_stock(image, 1)
+		item.set_image(img)
+	menu.append(item)
+	return item
+
+def activate_primitive_status(item, status):
+	saved = purple.PurpleSavedstatusFindTransientByTypeAndMessage(status, "")
+	if not saved:
+		saved = purple.PurpleSavedstatusNew("", status)
+	purple.PurpleSavedstatusActivate(saved)
+
+def activate_popular_status(item, time):
+	saved = purple.PurpleSavedstatusFindByCreationTime(time)
+	if saved:
+		purple.PurpleSavedstatusActivate(saved)
+
+def generate_status_menu(menu):
+	item = gtk.MenuItem("Available")
+	item.connect("activate", activate_primitive_status, 2)
+	menu.append(item)
+
+	item = gtk.MenuItem("Away")
+	item.connect("activate", activate_primitive_status, 5)
+	menu.append(item)
+
+	item = gtk.MenuItem("Invisible")
+	item.connect("activate", activate_primitive_status, 4)
+	menu.append(item)
+
+	item = gtk.MenuItem("Offline")
+	item.connect("activate", activate_primitive_status, 1)
+	menu.append(item)
+
+	menu.append(gtk.MenuItem())
+
+	popular = purple.PurpleSavedstatusesGetPopular(10)
+	for pop in popular:
+		title = purple.PurpleSavedstatusGetTitle(pop).replace('_', '__')
+		item = gtk.MenuItem(title)
+		item.set_data("timestamp", purple.PurpleSavedstatusGetCreationTime(pop))
+		item.connect("activate", activate_popular_status, purple.PurpleSavedstatusGetCreationTime(pop))
+		menu.append(item)
+
+def toggle_pref(item, pref):
+	purple.PurplePrefsSetBool(pref, item.get_active())
+
+def popup_menu(icon, button, tm, none):
+	menu = gtk.Menu()
+
+	item = gtk.CheckMenuItem("Blink for unread IM")
+	item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im"))
+	item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/im")
+	menu.append(item)
+
+	item = gtk.CheckMenuItem("Blink for unread Chats")
+	item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat"))
+	item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/chat")
+	menu.append(item)
+
+	menu.append(gtk.MenuItem())
+
+	#item = pack_image_label(menu, None, "Change Status...")
+	item = gtk.MenuItem("Change Status...")
+	menu.append(item)
+	submenu = gtk.Menu()
+	item.set_submenu(submenu)
+	generate_status_menu(submenu)
+
+	menu.show_all()
+	menu.popup(None, None, None, button, tm)
+
+def get_status_message():
+	status = purple.PurpleSavedstatusGetCurrent()
+	msg = purple.PurpleSavedstatusGetMessage(status)
+	if msg and len(msg) > 0:
+		text = msg + " "
+	else:
+		text = ""
+	text = text + "(" + {
+		2: "Available",
+		5: "Away",
+		4: "Invisible",
+		1: "Offline"
+	}[purple.PurpleSavedstatusGetType(status)] + ")"
+	return text
+
+def detect_unread_conversations():
+	im = purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im")
+	chat = purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat")
+	tooltip = ""
+	blink = False
+	if im and chat:
+		convs = purple.PurpleGetConversations()
+	elif im:
+		convs = purple.PurpleGetIms()
+	elif chat:
+		convs = purple.PurpleGetChats()
+	else:
+		convs = None
+	for conv in convs:
+		count = purple.PurpleConversationGetData(conv, "unseen-count")
+		if count and count > 0:
+			blink = True
+			tooltip = tooltip + "\n" + purple.PurpleConversationGetName(conv) + " (" + str(count) + ")"
+	t.set_from_file(path + "/share/pixmaps/pidgin.png")
+	if blink:
+		# I hate this icon
+		# t.set_from_file(path + "/share/pixmaps/pidgin/tray/22/tray-message.png")
+		tooltip = "\nUnread Messages:" + tooltip
+	# There's going to be some way to expose the client's display name in 2.1.0.
+	# Use that instead of hardcoding Finch here.
+	t.set_tooltip("Finch: " + get_status_message() + tooltip)
+	t.set_blinking(blink)
+
+def conversation_updated(conv, type):
+	detect_unread_conversations()
+
+def savedstatus_changed(new, old):
+	# Change the icon for status perhaps?
+	detect_unread_conversations()
+
+def init_prefs():
+	if not purple.PurplePrefsExists("/plugins/dbus/docklet/blink"):
+		purple.PurplePrefsAddNone("/plugins")
+		purple.PurplePrefsAddNone("/plugins/dbus")
+		purple.PurplePrefsAddNone("/plugins/dbus/docklet")
+		purple.PurplePrefsAddNone("/plugins/dbus/docklet/blink")
+		purple.PurplePrefsAddBool("/plugins/dbus/docklet/blink/im", True)
+		purple.PurplePrefsAddBool("/plugins/dbus/docklet/blink/chat", True)
+
+pkg = os.popen("pkg-config --variable=prefix pidgin")
+path = pkg.readline().rstrip()
+
+bus.add_signal_receiver(conversation_updated,
+  dbus_interface="im.pidgin.purple.PurpleInterface",
+  signal_name="ConversationUpdated")
+
+bus.add_signal_receiver(savedstatus_changed,
+  dbus_interface="im.pidgin.purple.PurpleInterface",
+  signal_name="SavedstatusChanged")
+
+t = gtk.StatusIcon()
+t.connect("popup-menu", popup_menu, None)
+
+init_prefs()
+detect_unread_conversations()
+
+gtk.main ()
+
--- a/libpurple/account.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/account.c	Tue Jun 19 17:28:41 2007 +0000
@@ -205,7 +205,7 @@
 {
 	PurpleStatusType *type = purple_status_get_type(status);
 	xmlnode *node, *child;
-	const GList *attrs, *attr;
+	GList *attrs, *attr;
 
 	node = xmlnode_new("attributes");
 
@@ -241,7 +241,7 @@
 statuses_to_xmlnode(const PurplePresence *presence)
 {
 	xmlnode *node, *child;
-	const GList *statuses, *status;
+	GList *statuses, *status;
 
 	node = xmlnode_new("statuses");
 
@@ -371,7 +371,7 @@
 accounts_to_xmlnode(void)
 {
 	xmlnode *node, *child;
-	const GList *cur;
+	GList *cur;
 
 	node = xmlnode_new("account");
 	xmlnode_set_attrib(node, "version", "1.0");
@@ -877,7 +877,7 @@
 void
 purple_account_destroy(PurpleAccount *account)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(account != NULL);
 
@@ -1805,7 +1805,7 @@
 PurpleStatusType *
 purple_account_get_status_type(const PurpleAccount *account, const char *id)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(account != NULL, NULL);
 	g_return_val_if_fail(id      != NULL, NULL);
@@ -1824,7 +1824,7 @@
 PurpleStatusType *
 purple_account_get_status_type_with_primitive(const PurpleAccount *account, PurpleStatusPrimitive primitive)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(account != NULL, NULL);
 
@@ -1857,7 +1857,7 @@
 	return purple_presence_is_status_active(account->presence, status_id);
 }
 
-const GList *
+GList *
 purple_account_get_status_types(const PurpleAccount *account)
 {
 	g_return_val_if_fail(account != NULL, NULL);
@@ -2272,7 +2272,7 @@
 	schedule_accounts_save();
 }
 
-const GList *
+GList *
 purple_accounts_get_all(void)
 {
 	return accounts;
@@ -2282,7 +2282,7 @@
 purple_accounts_get_all_active(void)
 {
 	GList *list = NULL;
-	const GList *all = purple_accounts_get_all();
+	GList *all = purple_accounts_get_all();
 
 	while (all != NULL) {
 		PurpleAccount *account = all->data;
@@ -2300,7 +2300,7 @@
 purple_accounts_find(const char *name, const char *protocol_id)
 {
 	PurpleAccount *account = NULL;
-	const GList *l;
+	GList *l;
 	char *who;
 
 	g_return_val_if_fail(name != NULL, NULL);
@@ -2327,7 +2327,7 @@
 void
 purple_accounts_restore_current_statuses()
 {
-	const GList *l;
+	GList *l;
 	PurpleAccount *account;
 
 	/* If we're not connected to the Internet right now, we bail on this */
--- a/libpurple/account.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/account.h	Tue Jun 19 17:28:41 2007 +0000
@@ -369,7 +369,7 @@
  *                  as a NULL-terminated list of id/value pairs.
  */
 void purple_account_set_status(PurpleAccount *account, const char *status_id,
-							 gboolean active, ...);
+							 gboolean active, ...) G_GNUC_NULL_TERMINATED;
 
 
 /**
@@ -672,9 +672,9 @@
  *
  * @param account The account.
  *
- * @return The account's status types.
+ * @constreturn The account's status types.
  */
-const GList *purple_account_get_status_types(const PurpleAccount *account);
+GList *purple_account_get_status_types(const PurpleAccount *account);
 
 /**
  * Returns a protocol-specific integer setting for an account.
@@ -884,9 +884,9 @@
 /**
  * Returns a list of all accounts.
  *
- * @return A list of all accounts.
+ * @constreturn A list of all accounts.
  */
-const GList *purple_accounts_get_all(void);
+GList *purple_accounts_get_all(void);
 
 /**
  * Returns a list of all enabled accounts
--- a/libpurple/accountopt.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/accountopt.c	Tue Jun 19 17:28:41 2007 +0000
@@ -282,7 +282,7 @@
 	return option->masked;
 }
 
-const GList *
+GList *
 purple_account_option_get_list(const PurpleAccountOption *option)
 {
 	g_return_val_if_fail(option != NULL, NULL);
--- a/libpurple/accountopt.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/accountopt.h	Tue Jun 19 17:28:41 2007 +0000
@@ -296,9 +296,9 @@
  *
  * @param option The account option.
  *
- * @return The list values.
+ * @constreturn The list values.
  */
-const GList *purple_account_option_get_list(const PurpleAccountOption *option);
+GList *purple_account_option_get_list(const PurpleAccountOption *option);
 
 /*@}*/
 
--- a/libpurple/blist.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/blist.c	Tue Jun 19 17:28:41 2007 +0000
@@ -35,8 +35,6 @@
 #include "value.h"
 #include "xmlnode.h"
 
-#define PATHSIZE 1024
-
 static PurpleBlistUiOps *blist_ui_ops = NULL;
 
 static PurpleBuddyList *purplebuddylist = NULL;
@@ -304,7 +302,7 @@
 {
 	xmlnode *node, *child, *grandchild;
 	PurpleBlistNode *gnode;
-	const GList *cur;
+	GList *cur;
 
 	node = xmlnode_new("purple");
 	xmlnode_set_attrib(node, "version", "1.0");
@@ -1895,7 +1893,7 @@
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleBlistNode *node;
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(group != NULL);
 
--- a/libpurple/buddyicon.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/buddyicon.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1021,7 +1021,7 @@
 _purple_buddy_icons_account_loaded_cb()
 {
 	const char *dirname = purple_buddy_icons_get_cache_dir();
-	const GList *cur;
+	GList *cur;
 
 	for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next)
 	{
--- a/libpurple/connection.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/connection.c	Tue Jun 19 17:28:41 2007 +0000
@@ -456,7 +456,7 @@
 void
 purple_connections_disconnect_all(void)
 {
-	const GList *l;
+	GList *l;
 	PurpleConnection *gc;
 
 	while ((l = purple_connections_get_all()) != NULL) {
@@ -466,13 +466,13 @@
 	}
 }
 
-const GList *
+GList *
 purple_connections_get_all(void)
 {
 	return connections;
 }
 
-const GList *
+GList *
 purple_connections_get_connecting(void)
 {
 	return connections_connecting;
--- a/libpurple/connection.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/connection.h	Tue Jun 19 17:28:41 2007 +0000
@@ -259,16 +259,16 @@
  * Returns a list of all active connections.  This does not
  * include connections that are in the process of connecting.
  *
- * @return A list of all active connections.
+ * @constreturn A list of all active connections.
  */
-const GList *purple_connections_get_all(void);
+GList *purple_connections_get_all(void);
 
 /**
  * Returns a list of all connections in the process of connecting.
  *
- * @return A list of connecting connections.
+ * @constreturn A list of connecting connections.
  */
-const GList *purple_connections_get_connecting(void);
+GList *purple_connections_get_connecting(void);
 
 /**
  * Checks if gc is still a valid pointer to a gc.
@@ -279,7 +279,7 @@
  * TODO: Eventually this bad boy will be removed, because it is
  *       a gross fix for a crashy problem.
  */
-#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find((GList *)purple_connections_get_all(), (gc)) != NULL)
+#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find(purple_connections_get_all(), (gc)) != NULL)
 
 /*@}*/
 
--- a/libpurple/conversation.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/conversation.c	Tue Jun 19 17:28:41 2007 +0000
@@ -631,7 +631,7 @@
 purple_conversation_foreach(void (*func)(PurpleConversation *conv))
 {
 	PurpleConversation *conv;
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(func != NULL);
 
@@ -732,19 +732,19 @@
 	return g_hash_table_lookup(conv->data, key);
 }
 
-const GList *
+GList *
 purple_get_conversations(void)
 {
 	return conversations;
 }
 
-const GList *
+GList *
 purple_get_ims(void)
 {
 	return ims;
 }
 
-const GList *
+GList *
 purple_get_chats(void)
 {
 	return chats;
@@ -759,7 +759,7 @@
 	PurpleConversation *c = NULL;
 	gchar *name1;
 	const gchar *name2;
-	const GList *cnv;
+	GList *cnv;
 
 	g_return_val_if_fail(name != NULL, NULL);
 
@@ -819,7 +819,7 @@
 		return;
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM &&
-		!g_list_find((GList *)purple_get_conversations(), conv))
+		!g_list_find(purple_get_conversations(), conv))
 		return;
 
 	displayed = g_strdup(message);
@@ -1250,7 +1250,7 @@
 	return users;
 }
 
-const GList *
+GList *
 purple_conv_chat_get_users(const PurpleConvChat *chat)
 {
 	g_return_val_if_fail(chat != NULL, NULL);
@@ -1284,7 +1284,7 @@
 	if (!purple_conv_chat_is_user_ignored(chat, name))
 		return;
 
-	item = g_list_find((GList *)purple_conv_chat_get_ignored(chat),
+	item = g_list_find(purple_conv_chat_get_ignored(chat),
 					   purple_conv_chat_get_ignored_user(chat, name));
 
 	purple_conv_chat_set_ignored(chat,
@@ -1304,7 +1304,7 @@
 	return ignored;
 }
 
-const GList *
+GList *
 purple_conv_chat_get_ignored(const PurpleConvChat *chat)
 {
 	g_return_val_if_fail(chat != NULL, NULL);
@@ -1315,7 +1315,7 @@
 const char *
 purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, const char *user)
 {
-	const GList *ignored;
+	GList *ignored;
 
 	g_return_val_if_fail(chat != NULL, NULL);
 	g_return_val_if_fail(user != NULL, NULL);
@@ -1810,7 +1810,7 @@
 	PurpleConversation *conv;
 	PurpleConversationUiOps *ops;
 	GList *users;
-	const GList *l;
+	GList *l;
 	GList *names = NULL;
 
 	g_return_if_fail(chat != NULL);
@@ -1919,7 +1919,7 @@
 PurpleConversation *
 purple_find_chat(const PurpleConnection *gc, int id)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 
 	for (l = purple_get_chats(); l != NULL; l = l->next) {
@@ -1968,7 +1968,7 @@
 PurpleConvChatBuddy *
 purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name)
 {
-	const GList *l;
+	GList *l;
 	PurpleConvChatBuddy *cb = NULL;
 
 	g_return_val_if_fail(chat != NULL, NULL);
--- a/libpurple/conversation.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/conversation.h	Tue Jun 19 17:28:41 2007 +0000
@@ -502,23 +502,23 @@
  *
  * This list includes both IMs and chats.
  *
- * @return A GList of all conversations.
+ * @constreturn A GList of all conversations.
  */
-const GList *purple_get_conversations(void);
+GList *purple_get_conversations(void);
 
 /**
  * Returns a list of all IMs.
  *
- * @return A GList of all IMs.
+ * @constreturn A GList of all IMs.
  */
-const GList *purple_get_ims(void);
+GList *purple_get_ims(void);
 
 /**
  * Returns a list of all chats.
  *
- * @return A GList of all chats.
+ * @constreturn A GList of all chats.
  */
-const GList *purple_get_chats(void);
+GList *purple_get_chats(void);
 
 /**
  * Finds a conversation with the specified type, name, and Purple account.
@@ -875,9 +875,9 @@
  *
  * @param chat The chat.
  *
- * @return The list of users.
+ * @constreturn The list of users.
  */
-const GList *purple_conv_chat_get_users(const PurpleConvChat *chat);
+GList *purple_conv_chat_get_users(const PurpleConvChat *chat);
 
 /**
  * Ignores a user in a chat room.
@@ -912,7 +912,7 @@
  *
  * @return The list of ignored users.
  */
-const GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat);
+GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat);
 
 /**
  * Returns the actual name of the specified ignored user, if it exists in
--- a/libpurple/core.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/core.c	Tue Jun 19 17:28:41 2007 +0000
@@ -489,13 +489,33 @@
 			/* We're only going to duplicate a logs symlink. */
 			if (!strcmp(entry, "logs"))
 			{
+				char *link;
+#if GLIB_CHECK_VERSION(2,4,0)
+				GError *err = NULL;
+
+				if ((link = g_file_read_link(name, &err)) == NULL)
+				{
+					char *name_utf8 = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
+					purple_debug_error("core", "Error reading symlink %s: %s. Please report this at http://developer.pidgin.im\n",
+					                   name_utf8 ? name_utf8 : name, err->message);
+					g_free(name_utf8);
+					g_error_free(err);
+					g_free(name);
+					g_dir_close(dir);
+					g_free(status_file);
+					g_free(old_user_dir);
+					return FALSE;
+				}
+#else
 				char buf[MAXPATHLEN];
 				size_t linklen;
 
 				if ((linklen = readlink(name, buf, sizeof(buf) - 1) == -1))
 				{
+					char *name_utf8 = g_filename_to_utf8(name);
 					purple_debug_error("core", "Error reading symlink %s: %s. Please report this at http://developer.pidgin.im\n",
-					                   name, strerror(errno));
+					                   name_utf8, strerror(errno));
+					g_free(name_utf8);
 					g_free(name);
 					g_dir_close(dir);
 					g_free(status_file);
@@ -504,13 +524,18 @@
 				}
 				buf[linklen] = '\0';
 
-				logs_dir = g_strconcat(user_dir, G_DIR_SEPARATOR_S "logs", NULL);
+				/* This way we don't have to GLIB_VERSION_CHECK every g_free(link) below. */
+				link = g_strdup(buf);
+#endif
 
-				if (!strcmp(buf, "../.purple/logs") || !strcmp(buf, logs_dir))
+				logs_dir = g_build_filename(user_dir, "logs", NULL);
+
+				if (!strcmp(link, "../.purple/logs") || !strcmp(link, logs_dir))
 				{
 					/* If the symlink points to the new directory, we're
 					 * likely just trying again after a failed migration,
 					 * so there's no need to fail here. */
+					g_free(link);
 					g_free(logs_dir);
 					continue;
 				}
@@ -522,12 +547,13 @@
 				g_unlink(logs_dir);
 
 				/* Relative links will most likely still be
-				 * valid from ~/.purple, though not it's not
+				 * valid from ~/.purple, though it's not
 				 * guaranteed.  Oh well. */
-				if (symlink(buf, logs_dir))
+				if (symlink(link, logs_dir))
 				{
 					purple_debug_error("core", "Error symlinking %s to %s: %s. Please report this at http://developer.pidgin.im\n",
-					                   logs_dir, buf, strerror(errno));
+					                   logs_dir, link, strerror(errno));
+					g_free(link);
 					g_free(name);
 					g_free(logs_dir);
 					g_dir_close(dir);
@@ -536,6 +562,7 @@
 					return FALSE;
 				}
 
+				g_free(link);
 				g_free(logs_dir);
 				continue;
 			}
--- a/libpurple/dbus-analyze-functions.py	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/dbus-analyze-functions.py	Tue Jun 19 17:28:41 2007 +0000
@@ -3,7 +3,7 @@
 import sys
 
 # types translated into "int"
-simpletypes = ["int", "gint", "guint", "gboolean"]
+simpletypes = ["int", "gint", "guint", "gboolean", "gpointer", "size_t", "gssize", "time_t"]
 
 # List "excluded" contains functions that shouldn't be exported via
 # DBus.  If you remove a function from this list, please make sure
@@ -32,8 +32,8 @@
     "purple_log_read",
     ]
 
-# This is a list of functions that return a GList* whose elements are
-# string, not pointers to objects.
+# This is a list of functions that return a GList* or GSList * whose elements
+# are strings, not pointers to objects.
 stringlists = [
     "purple_prefs_get_path_list",
     "purple_prefs_get_string_list",
@@ -41,6 +41,32 @@
     "purple_uri_list_extract_uris",
 ]
 
+# This is a list of functions that return a GList* or GSList* that should
+# not be freed.  Ideally, this information should be obtained from the Doxygen
+# documentation at some point.
+constlists = [
+    "purple_account_get_status_types",
+    "purple_accounts_get_all",
+    "purple_account_option_get_list",
+    "purple_connections_get_all",
+    "purple_connections_get_connecting",
+    "purple_get_conversations",
+    "purple_get_ims",
+    "purple_get_chats",
+    "purple_conv_chat_get_users",
+    "purple_conv_chat_get_ignored",
+    "purple_mime_document_get_fields",
+    "purple_mime_document_get_parts",
+    "purple_mime_part_get_fields",
+    "purple_notify_user_info_get_entries",
+    "purple_request_fields_get_required",
+    "purple_request_field_list_get_selected",
+    "purple_request_field_list_get_items",
+    "purple_savedstatuses_get_all",
+    "purple_status_type_get_attrs",
+    "purple_presence_get_statuses",
+]
+
 pointer = "#pointer#"
 myexception = "My Exception"
 
@@ -93,21 +119,26 @@
 
     def processinput(self, type, name):
         const = False
+        unsigned = False
         if type[0] == "const":
             type = type[1:]
             const = True
 
+        if type[0] == "unsigned":
+            type = type[1:]
+            unsigned = True
+
         if len(type) == 1:
             # simple types (int, gboolean, etc.) and enums
             if (type[0] in simpletypes) or ((type[0].startswith("Purple") and not type[0].endswith("Callback"))):
-                return self.inputsimple(type, name)
+                return self.inputsimple(type, name, unsigned)
 
         # pointers ... 
         if (len(type) == 2) and (type[1] == pointer):
             # strings
             if type[0] in ["char", "gchar"]:
                 if const:
-                    return self.inputstring(type, name)
+                    return self.inputstring(type, name, unsigned)
                 else:
                     raise myexception
 
@@ -152,7 +183,7 @@
                 return self.outputpurplestructure(type, name)
 
             if type[0] in ["GList", "GSList"]:
-                return self.outputlist(type, name, const)
+                return self.outputlist(type, name)
 
         raise myexception
     
@@ -206,12 +237,18 @@
             print "typedef struct _%s %s;" % (type[0], type[0])
             self.knowntypes.append(type[0])
 
-    def inputsimple(self, type, name):
+    def inputsimple(self, type, name, us):
         self.paramshdr.append("%s %s" % (type[0], name))
-        self.inputparams.append(("G_TYPE_INT", name))
+        if us:
+            self.inputparams.append(("G_TYPE_UINT", name))
+        else:
+            self.inputparams.append(("G_TYPE_INT", name))
 
-    def inputstring(self, type, name):
-        self.paramshdr.append("const char *%s" % name)
+    def inputstring(self, type, name, us):
+        if us:
+            self.paramshdr.append("const unsigned char *%s" % name)
+        else:
+            self.paramshdr.append("const char *%s" % name)
         self.inputparams.append(("G_TYPE_STRING", name))
         
     def inputpurplestructure(self, type, name):
@@ -254,7 +291,7 @@
         self.returncode.append("return (%s*) GINT_TO_POINTER(%s);" % (type[0], name));
         self.definepurplestructure(type)
 
-    def outputlist(self, type, name, const):
+    def outputlist(self, type, name):
         self.functiontype = "%s*" % type[0]
         self.decls.append("GArray *%s;" % name)
         self.outputparams.append(('dbus_g_type_get_collection("GArray", G_TYPE_INT)', name))
@@ -298,7 +335,7 @@
         print "\tdbus_message_append_args(reply_DBUS,",
         for param in self.cparamsout:
             if type(param) is str:
-                print "%s," % param
+                print "%s," % param,
             else:
                 print "DBUS_TYPE_%s, &%s," % param,
         print "DBUS_TYPE_INVALID);"
@@ -322,15 +359,23 @@
 
     # input parameters
 
-    def inputsimple(self, type, name):
-        self.cdecls.append("\tdbus_int32_t %s;" % name)
-        self.cparams.append(("INT32", name))
-        self.addintype("i", name)
+    def inputsimple(self, type, name, us):
+        if us:
+            self.cdecls.append("\tdbus_int32_t %s;" % name)
+            self.cparams.append(("INT32", name))
+            self.addintype("i", name)
+        else:
+            self.cdecls.append("\tdbus_uint32_t %s;" % name)
+            self.cparams.append(("UINT32", name))
+            self.addintype("u", name)
 
-    def inputstring(self, type, name):
-        self.cdecls.append("\tconst char *%s;" % name)
+    def inputstring(self, type, name, us):
+        if us:
+            self.cdecls.append("\tconst unsigned char *%s;" % name)
+        else:
+            self.cdecls.append("\tconst char *%s;" % name)
         self.cparams.append(("STRING", name))
-        self.ccode  .append("\tNULLIFY(%s);" % name)
+        self.ccode.append("\t%s = (%s && %s[0]) ? %s : NULL;" % (name,name,name,name))
         self.addintype("s", name)
 
     def inputhash(self, type, name):
@@ -390,28 +435,20 @@
 
     # GList*, GSList*, assume that list is a list of objects
     # unless the function is in stringlists
-    def outputlist(self, type, name, const):
+    def outputlist(self, type, name):
         self.cdecls.append("\tdbus_int32_t %s_LEN;" % name)
         self.ccodeout.append("\tg_free(%s);" % name)
 
-        if const:
-            const_prefix = "const_"
-        else:
-            const_prefix = ""
-
-        if (const):
-            self.cdecls.append("\tconst %s *list;" % type[0]);
-        else:
-            self.cdecls.append("\t%s *list;" % type[0]);
+        self.cdecls.append("\t%s *list;" % type[0]);
 
         if self.function.name in stringlists:
             self.cdecls.append("\tchar **%s;" % name)
             self.ccode.append("\tlist = %s;" % self.call)
-            self.ccode.append("\t%s = (char **)purple_const_%s_to_array(list, &%s_LEN);" % \
+            self.ccode.append("\t%s = (char **)purple_%s_to_array(list, FALSE, &%s_LEN);" % \
                          (name, type[0], name))
-            self.cparamsout.append("\tDBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \
+            self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \
                           % (name, name))
-            if (not const):
+            if (not (self.function.name in constlists)):
                 type_name = type[0].lower()[1:]
                 self.ccodeout.append("\tg_%s_foreach(list, (GFunc)g_free, NULL);" % type_name)
                 self.ccodeout.append("\tg_%s_free(list);" % type_name)
@@ -419,11 +456,11 @@
         else:
             self.cdecls.append("\tdbus_int32_t *%s;" % name)
             self.ccode.append("\tlist = %s;" % self.call)
-            self.ccode.append("\t%s = purple_dbusify_const_%s(list, &%s_LEN);" % \
+            self.ccode.append("\t%s = purple_dbusify_%s(list, FALSE, &%s_LEN);" % \
                          (name, type[0], name))
-            if (not const):
+            if (not (self.function.name in constlists)):
                 self.ccode.append("\tg_%s_free(list);" % type[0].lower()[1:])
-            self.cparamsout.append("\tDBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \
+            self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \
                               % (name, name))
             self.addouttype("ai", name)
 
--- a/libpurple/dbus-bindings.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/dbus-bindings.h	Tue Jun 19 17:28:41 2007 +0000
@@ -83,52 +83,14 @@
 					int              first_arg_type,
 					va_list          var_args);
 
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_dbusify_const_GList().
- */
 dbus_int32_t* purple_dbusify_GList(GList *list, gboolean free_memory, 
 				 dbus_int32_t *len);
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_dbusify_const_GSList().
- */
 dbus_int32_t* purple_dbusify_GSList(GSList *list, gboolean free_memory,
 				  dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-dbus_int32_t* purple_dbusify_const_GList(const GList *list, dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-dbus_int32_t* purple_dbusify_const_GSList(const GSList *list, dbus_int32_t *len);
-
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_const_GList_to_array().
- */
 gpointer* purple_GList_to_array(GList *list, gboolean free_memory,
 			      dbus_int32_t *len);
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_const_GSList_to_array().
- */
 gpointer* purple_GSList_to_array(GSList *list, gboolean free_memory,
 			      dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-gpointer* purple_const_GList_to_array(const GList *list, dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-gpointer* purple_const_GSList_to_array(const GSList *list, dbus_int32_t *len);
-
 GHashTable *purple_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error);
 
 const char* empty_to_null(const char *str);
--- a/libpurple/dbus-server.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/dbus-server.c	Tue Jun 19 17:28:41 2007 +0000
@@ -120,7 +120,7 @@
 	if ((id == 0) && (node != NULL))
 	{
 		purple_debug_warning("dbus",
-				"Need to register an object with the dbus subsystem.\n");
+				"Need to register an object with the dbus subsystem. (If you are not a developer, please ignore this message.)\n");
 		return 0;
 	}
 	return id;
@@ -290,45 +290,19 @@
 }
 
 dbus_int32_t *
-purple_dbusify_const_GList(const GList *list, dbus_int32_t *len)
+purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len)
 {
 	dbus_int32_t *array;
 	int i;
-	const GList *elem;
+	GList *elem;
 
-	/* g_list_length() should really take a const GList */
-	*len = g_list_length((GList *)list);
+	*len = g_list_length(list);
 	array = g_new0(dbus_int32_t, *len);
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = purple_dbus_pointer_to_id(elem->data);
 
-	return array;
-}
-
-dbus_int32_t *
-purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len)
-{
-	dbus_int32_t *array = purple_dbusify_const_GList(list, len);
-
-	if (!free_memory)
-		return array;
-
-	g_list_free(list);
-	return array;
-}
-
-dbus_int32_t *
-purple_dbusify_const_GSList(const GSList *list, dbus_int32_t *len)
-{
-	dbus_int32_t *array;
-	int i;
-	const GSList *elem;
-
-	/* g_slist_length should really take a const GSList */
-	*len = g_slist_length((GSList *)list);
-	array = g_new0(dbus_int32_t, *len);
-	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
-		array[i] = purple_dbus_pointer_to_id(elem->data);
+	if (free_memory)
+		g_list_free(list);
 
 	return array;
 }
@@ -336,26 +310,17 @@
 dbus_int32_t *
 purple_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len)
 {
-	dbus_int32_t *array = purple_dbusify_const_GSList(list, len);
-
-	if (!free_memory)
-		return array;
-
-	g_slist_free(list);
-	return array;
-}
+	dbus_int32_t *array;
+	int i;
+	GSList *elem;
 
-gpointer *
-purple_const_GList_to_array(const GList *list, dbus_int32_t *len)
-{
-	gpointer *array;
-	int i;
-	const GList *elem;
+	*len = g_slist_length(list);
+	array = g_new0(dbus_int32_t, *len);
+	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
+		array[i] = purple_dbus_pointer_to_id(elem->data);
 
-	*len = g_list_length((GList *)list);
-	array = g_new0(gpointer, *len);
-	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
-		array[i] = elem->data;
+	if (free_memory)
+		g_slist_free(list);
 
 	return array;
 }
@@ -363,39 +328,36 @@
 gpointer *
 purple_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len)
 {
-	gpointer *array = purple_const_GList_to_array(list, len);
-
-	if (!free_memory)
-		return array;
-
-	g_list_free(list);
-	return array;
-}
-
-gpointer *
-purple_const_GSList_to_array(const GSList *list, dbus_int32_t *len)
-{
 	gpointer *array;
 	int i;
-	const GSList *elem;
+	GList *elem;
 
-	*len = g_slist_length((GSList *)list);
+	*len = g_list_length(list);
 	array = g_new0(gpointer, *len);
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = elem->data;
 
+	if (free_memory)
+		g_list_free(list);
+
 	return array;
 }
 
 gpointer *
 purple_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len)
 {
-	gpointer *array = purple_const_GSList_to_array(list, len);
+	gpointer *array;
+	int i;
+	GSList *elem;
 
-	if (!free_memory)
-		return array;
+	*len = g_slist_length(list);
+	array = g_new0(gpointer, *len);
+	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
+		array[i] = elem->data;
 
-	g_slist_free(list);
+	if (free_memory)
+		g_slist_free(list);
+
 	return array;
 }
 
@@ -798,7 +760,7 @@
 	dbus_message_iter_init_append(signal, &iter);
 
 	if (purple_dbus_message_append_purple_values(&iter, num_values, values, vargs))
-		purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error.\n", name);
+		purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error. (If you are not a developer, please ignore this message.)\n", name);
 
 	dbus_connection_send(purple_dbus_connection, signal, NULL);
 
@@ -835,8 +797,18 @@
 void
 purple_dbus_uninit(void)
 {
-	/* Surely we must do SOME kind of uninitialization? */
+	DBusError error;
+	if (!purple_dbus_connection)
+		return;
 
+	dbus_error_init(&error);
+	dbus_connection_unregister_object_path(purple_dbus_connection, DBUS_PATH_PURPLE);
+	dbus_bus_release_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, &error);
+	dbus_error_free(&error);
+	dbus_connection_unref(purple_dbus_connection);
+	purple_dbus_connection = NULL;
+	purple_signals_disconnect_by_handle(purple_dbus_get_handle());
 	g_free(init_error);
 	init_error = NULL;
 }
+
--- a/libpurple/dbus-useful.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/dbus-useful.c	Tue Jun 19 17:28:41 2007 +0000
@@ -11,7 +11,7 @@
 		       gboolean (*account_test)(const PurpleAccount *account))
 {
 	PurpleAccount *result = NULL;
-	const GList *l;
+	GList *l;
 	char *who;
 
 	if (name)
--- a/libpurple/idle.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/idle.c	Tue Jun 19 17:28:41 2007 +0000
@@ -199,7 +199,7 @@
 	/* Idle reporting stuff */
 	if (report_idle && (time_idle >= IDLEMARK))
 	{
-		const GList *l;
+		GList *l;
 		for (l = purple_connections_get_all(); l != NULL; l = l->next)
 		{
 			PurpleConnection *gc = l->data;
--- a/libpurple/internal.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/internal.h	Tue Jun 19 17:28:41 2007 +0000
@@ -112,16 +112,10 @@
 # include <unistd.h>
 #endif
 
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
 #ifndef HOST_NAME_MAX
 # define HOST_NAME_MAX 255
 #endif
 
-#define PATHSIZE 1024
-
 #include <glib.h>
 #if !GLIB_CHECK_VERSION(2,4,0)
 #	define G_MAXUINT32 ((guint32) 0xffffffff)
--- a/libpurple/log.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/log.c	Tue Jun 19 17:28:41 2007 +0000
@@ -985,7 +985,7 @@
 		GDir *protocol_dir;
 		const gchar *username;
 		gchar *protocol_unescaped;
-		const GList *account_iter;
+		GList *account_iter;
 		GList *accounts = NULL;
 
 		if ((protocol_dir = g_dir_open(protocol_path, 0, NULL)) == NULL) {
--- a/libpurple/mime.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/mime.c	Tue Jun 19 17:28:41 2007 +0000
@@ -277,7 +277,7 @@
 }
 
 
-const GList *
+GList *
 purple_mime_part_get_fields(PurpleMimePart *part)
 {
 	g_return_val_if_fail(part != NULL, NULL);
@@ -513,7 +513,7 @@
 }
 
 
-const GList *
+GList *
 purple_mime_document_get_fields(PurpleMimeDocument *doc)
 {
 	g_return_val_if_fail(doc != NULL, NULL);
@@ -537,7 +537,7 @@
 }
 
 
-const GList *
+GList *
 purple_mime_document_get_parts(PurpleMimeDocument *doc)
 {
 	g_return_val_if_fail(doc != NULL, NULL);
--- a/libpurple/mime.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/mime.h	Tue Jun 19 17:28:41 2007 +0000
@@ -90,10 +90,10 @@
  *
  * @param doc The MIME document.
  *
- * @returns   A list of strings indicating the fields (but not the values of
- *            the fields) in the header of doc.
+ * @constreturn A list of strings indicating the fields (but not the values
+ *              of the fields) in the header of doc.
  */
-const GList *purple_mime_document_get_fields(PurpleMimeDocument *doc);
+GList *purple_mime_document_get_fields(PurpleMimeDocument *doc);
 
 /**
  * Get the value of a specific field in the header of a document.
@@ -125,9 +125,9 @@
  *
  * @param doc The MIME document.
  *
- * @returns   List of PurpleMimePart contained within doc.
+ * @constreturn   List of PurpleMimePart contained within doc.
  */
-const GList *purple_mime_document_get_parts(PurpleMimeDocument *doc);
+GList *purple_mime_document_get_parts(PurpleMimeDocument *doc);
 
 /**
  * Create and insert a new part into a MIME document.
@@ -142,10 +142,10 @@
  *
  * @param part The MIME document part.
  *
- * @returns    List of strings indicating the fields (but not the values
- *             of the fields) in the header of part.
+ * @constreturn List of strings indicating the fields (but not the values
+ *              of the fields) in the header of part.
  */
-const GList *purple_mime_part_get_fields(PurpleMimePart *part);
+GList *purple_mime_part_get_fields(PurpleMimePart *part);
 
 
 /**
--- a/libpurple/notify.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/notify.c	Tue Jun 19 17:28:41 2007 +0000
@@ -530,7 +530,7 @@
 	g_free(user_info);
 }
 
-const GList *
+GList *
 purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info)
 {
 	g_return_val_if_fail(user_info != NULL, NULL);
--- a/libpurple/notify.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/notify.h	Tue Jun 19 17:28:41 2007 +0000
@@ -456,9 +456,9 @@
  *
  * @param user_info          The PurpleNotifyUserInfo
  *
- * @result                   A GList of PurpleNotifyUserInfoEntry objects
+ * @constreturn              A GList of PurpleNotifyUserInfoEntry objects
  */
-const GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info);
+GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info);
 
 /**
  * Create a textual representation of a PurpleNotifyUserInfo, separating entries with newline
--- a/libpurple/plugins/joinpart.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/joinpart.c	Tue Jun 19 17:28:41 2007 +0000
@@ -86,7 +86,7 @@
 	/* If the room is small, don't bother. */
 	chat = PURPLE_CONV_CHAT(conv);
 	threshold = purple_prefs_get_int(THRESHOLD_PREF);
-	if (g_list_length((GList *)purple_conv_chat_get_users(chat)) < threshold)
+	if (g_list_length(purple_conv_chat_get_users(chat)) < threshold)
 		return FALSE;
 
 	/* We always care about our buddies! */
--- a/libpurple/plugins/perl/common/Account.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/Account.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -184,7 +184,7 @@
 purple_account_get_status_types(account)
     Purple::Account account
 PREINIT:
-    const GList *l;
+    GList *l;
 PPCODE:
     for (l = purple_account_get_status_types(account); l != NULL; l = l->next) {
         XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::StatusType")));
@@ -290,7 +290,7 @@
 void
 purple_accounts_get_all()
 PREINIT:
-    const GList *l;
+    GList *l;
 PPCODE:
     for (l = purple_accounts_get_all(); l != NULL; l = l->next) {
         XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account")));
--- a/libpurple/plugins/perl/common/AccountOpts.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/AccountOpts.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -88,7 +88,7 @@
 purple_account_option_get_list(option)
 	Purple::Account::Option option
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_account_option_get_list(option); l != NULL; l = l->next) {
 		/* XXX These are actually PurpleKeyValuePairs but we don't have a
--- a/libpurple/plugins/perl/common/Connection.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/Connection.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -72,7 +72,7 @@
 void
 purple_connections_get_all()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_connections_get_all(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
@@ -81,7 +81,7 @@
 void
 purple_connections_get_connecting()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_connections_get_connecting(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
--- a/libpurple/plugins/perl/common/Conversation.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/Conversation.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -93,7 +93,7 @@
 void
 purple_get_ims()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_get_ims(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
@@ -102,7 +102,7 @@
 void
 purple_get_conversations()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
@@ -111,7 +111,7 @@
 void
 purple_get_chats()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_get_chats(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
@@ -354,7 +354,7 @@
 purple_conv_chat_get_users(chat)
 	Purple::Conversation::Chat chat
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_conv_chat_get_users(chat); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
@@ -394,7 +394,7 @@
 purple_conv_chat_get_ignored(chat)
 	Purple::Conversation::Chat chat
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_conv_chat_get_ignored(chat); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
--- a/libpurple/plugins/perl/common/Notify.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/Notify.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -140,7 +140,7 @@
 purple_notify_user_info_get_entries(user_info)
 	Purple::NotifyUserInfo user_info
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	l = purple_notify_user_info_get_entries(user_info);
 	for (; l != NULL; l = l->next) {
--- a/libpurple/plugins/perl/common/Request.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/Request.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -396,7 +396,7 @@
 purple_request_field_list_get_items(field)
 	Purple::Request::Field field
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_request_field_list_get_items(field); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
@@ -410,7 +410,7 @@
 purple_request_field_list_get_selected(field)
 	Purple::Request::Field field
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_request_field_list_get_selected(field); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
@@ -625,7 +625,7 @@
 purple_request_fields_get_required(fields)
 	Purple::Request::Fields fields
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_request_fields_get_required(fields); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Request::Field")));
--- a/libpurple/plugins/perl/common/SavedStatuses.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/SavedStatuses.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -130,7 +130,7 @@
 void
 purple_savedstatuses_get_all()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_savedstatuses_get_all(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::SavedStatus")));
@@ -140,7 +140,7 @@
 purple_savedstatuses_get_popular(how_many)
 	unsigned int how_many
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_savedstatuses_get_popular(how_many); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::SavedStatus")));
--- a/libpurple/plugins/perl/common/Status.xs	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/perl/common/Status.xs	Tue Jun 19 17:28:41 2007 +0000
@@ -142,7 +142,7 @@
 purple_presence_get_statuses(presence)
 	Purple::Presence presence
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status")));
@@ -392,7 +392,7 @@
 purple_status_type_get_attrs(status_type)
 	Purple::StatusType status_type
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_status_type_get_attrs(status_type); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::StatusAttr")));
--- a/libpurple/plugins/startup.py	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/startup.py	Tue Jun 19 17:28:41 2007 +0000
@@ -25,6 +25,13 @@
 import dbus
 import os
 
+if len(sys.argv) == 1:
+	print "Usage:", sys.argv[0], """<purple-client> [arguments]
+
+Example:
+	""", sys.argv[0], "pidgin -d -c /my/home"
+	sys.exit(1)
+
 home = os.path.expanduser('~/.purple/')
 for arg in range(1, len(sys.argv[1:])):
 	if sys.argv[arg] == "-c":
--- a/libpurple/plugins/tcl/tcl_cmds.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/plugins/tcl/tcl_cmds.c	Tue Jun 19 17:28:41 2007 +0000
@@ -43,7 +43,7 @@
 static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp)
 {
 	PurpleAccount *account;
-	const GList *cur;
+	GList *cur;
 
 	account = purple_tcl_ref_get(interp, obj, PurpleTclRefAccount);
 
@@ -62,7 +62,7 @@
 static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp)
 {
 	PurpleConversation *convo;
-	const GList *cur;
+	GList *cur;
 
 	convo = purple_tcl_ref_get(interp, obj, PurpleTclRefConversation);
 
@@ -81,7 +81,7 @@
 static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp)
 {
 	PurpleConnection *gc;
-	const GList *cur;
+	GList *cur;
 
 	gc = purple_tcl_ref_get(interp, obj, PurpleTclRefConnection);
 
@@ -113,7 +113,7 @@
 	const char *listopts[] = { "-all", "-online", NULL };
 	enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
 	const char *alias;
-	const GList *cur;
+	GList *cur;
 	PurpleAccount *account;
 	PurpleStatus *status;
 	PurpleStatusType *status_type;
@@ -612,7 +612,7 @@
 	const char *cmds[] = { "account", "displayname", "handle", "list", NULL };
 	enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE, CMD_CONN_LIST } cmd;
 	int error;
-	const GList *cur;
+	GList *cur;
 	PurpleConnection *gc;
 
 	if (objc < 2) {
@@ -680,7 +680,7 @@
 	PurpleConversation *convo;
 	PurpleAccount *account;
 	PurpleConversationType type;
-	const GList *cur;
+	GList *cur;
 	char *opt, *from, *what;
 	int error, argsused, flags = 0;
 
@@ -1082,7 +1082,7 @@
 	Tcl_Obj *result = Tcl_GetObjResult(interp);
 	Tcl_Obj *list, *elem;
 	PurplePresence *presence;
-	const GList *cur;
+	GList *cur;
 	int error, idle, idle_time, login_time;
 
 	if (objc < 2) {
@@ -1524,7 +1524,7 @@
 	Tcl_Obj *result = Tcl_GetObjResult(interp);
 	PurpleStatusType *status_type;
 	Tcl_Obj *list, *elem;
-	const GList *cur;
+	GList *cur;
 	int error;
 
 	if (objc < 2) {
--- a/libpurple/pounce.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/pounce.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1014,6 +1014,20 @@
 	return pounces;
 }
 
+GList *purple_pounces_get_all_for_ui(const char *ui)
+{
+	GList *list = NULL, *iter;
+	g_return_val_if_fail(ui != NULL, NULL);
+
+	for (iter = pounces; iter; iter = iter->next) {
+		PurplePounce *pounce = iter->data;
+		if (pounce->ui_type && strcmp(pounce->ui_type, ui) == 0)
+			list = g_list_prepend(list, pounce);
+	}
+	list = g_list_reverse(list);
+	return list;
+}
+
 static void
 free_pounce_handler(gpointer user_data)
 {
--- a/libpurple/pounce.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/pounce.h	Tue Jun 19 17:28:41 2007 +0000
@@ -343,6 +343,17 @@
 GList *purple_pounces_get_all(void);
 
 /**
+ * Returns a list of registered buddy pounces for the ui-type.
+ *
+ * @param ui  The ID of the UI using the core.
+ *
+ * @return The list of buddy pounces. The list should be freed by
+ *         the caller when it's no longer used.
+ * @since  2.1.0
+ */
+GList *purple_pounces_get_all_for_ui(const char *ui);
+
+/**
  * Returns the buddy pounce subsystem handle.
  *
  * @return The subsystem handle.
--- a/libpurple/prefs.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/prefs.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1355,7 +1355,6 @@
 	purple_prefs_remove("/plugins/core/autorecon/hide_reconnecting_dialog");
 	purple_prefs_remove("/plugins/core/autorecon/restore_state");
 	purple_prefs_remove("/plugins/core/autorecon");
-	purple_prefs_remove("/purple/debug/timestamps");
 
 	/* Convert old sounds while_away pref to new 3-way pref. */
 	if (purple_prefs_exists("/purple/sound/while_away") &&
--- a/libpurple/protocols/gg/gg.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/gg/gg.c	Tue Jun 19 17:28:41 2007 +0000
@@ -823,7 +823,7 @@
 {
 	GGPInfo *info = gc->proto_data;
 	PurpleRequestField *field;
-	const GList *sel;
+	GList *sel;
 
 	field = purple_request_fields_get_field(fields, "name");
 	sel = purple_request_field_list_get_selected(field);
--- a/libpurple/protocols/irc/irc.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/irc/irc.c	Tue Jun 19 17:28:41 2007 +0000
@@ -592,7 +592,7 @@
 	struct irc_conn *irc = gc->proto_data;
 	int len;
 
-	if(!g_list_find((GList *)purple_connections_get_all(), gc)) {
+	if(!g_list_find(purple_connections_get_all(), gc)) {
 		purple_ssl_close(gsc);
 		return;
 	}
--- a/libpurple/protocols/jabber/buddy.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Tue Jun 19 17:28:41 2007 +0000
@@ -385,6 +385,11 @@
 	xmlnode *vc_node;
 	struct tag_attr *tag_attr;
 
+	/* if we have't grabbed the remote vcard yet, we can't
+	 * assume that what we have here is correct */
+	if(!js->vcard_fetched)
+		return;
+
 	g_free(js->avatar_hash);
 	js->avatar_hash = NULL;
 
@@ -443,14 +448,9 @@
 
 void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
-	PurplePresence *gpresence;
-	PurpleStatus *status;
-
 	jabber_set_info(gc, purple_account_get_user_info(gc->account));
 
-	gpresence = purple_account_get_presence(gc->account);
-	status = purple_presence_get_active_status(gpresence);
-	jabber_presence_send(gc->account, status);
+	jabber_presence_send(gc->account, NULL);
 }
 
 /*
@@ -739,6 +739,40 @@
 	}
 }
 
+static void jabber_vcard_save_mine(JabberStream *js, xmlnode *packet, gpointer data)
+{
+	xmlnode *vcard;
+	char *txt;
+	PurpleStoredImage *img;
+
+	if((vcard = xmlnode_get_child(packet, "vCard")) ||
+			(vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp")))
+	{
+		txt = xmlnode_to_str(vcard, NULL);
+		purple_account_set_user_info(purple_connection_get_account(js->gc), txt);
+
+		g_free(txt);
+	} else {
+		/* if we have no vCard, then lets not overwrite what we might have locally */
+	}
+
+	js->vcard_fetched = TRUE;
+
+	if(NULL != (img = purple_buddy_icons_find_account_icon(js->gc->account))) {
+		jabber_set_buddy_icon(js->gc, img);
+		purple_imgstore_unref(img);
+	}
+}
+
+void jabber_vcard_fetch_mine(JabberStream *js)
+{
+	JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "vcard-temp");
+
+	jabber_iq_set_callback(iq, jabber_vcard_save_mine, NULL);
+
+	jabber_iq_send(iq);
+}
+
 static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data)
 {
 	const char *id, *from;
--- a/libpurple/protocols/jabber/buddy.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/buddy.h	Tue Jun 19 17:28:41 2007 +0000
@@ -103,4 +103,6 @@
 
 void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js);
 
+void jabber_vcard_fetch_mine(JabberStream *js);
+
 #endif /* _PURPLE_JABBER_BUDDY_H_ */
--- a/libpurple/protocols/jabber/disco.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/disco.c	Tue Jun 19 17:28:41 2007 +0000
@@ -218,18 +218,15 @@
 static void
 jabber_disco_finish_server_info_result_cb(JabberStream *js)
 {
-	PurplePresence *gpresence;
-	PurpleStatus *status;
+
+	jabber_vcard_fetch_mine(js);
 
 	if (!(js->server_caps & JABBER_CAP_GOOGLE_ROSTER)) {
 		/* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
 		jabber_roster_request(js);
 	}
 
-	/* Send initial presence; this will trigger receipt of presence for contacts on the roster */
-	gpresence = purple_account_get_presence(js->gc->account);
-	status = purple_presence_get_active_status(gpresence);
-	jabber_presence_send(js->gc->account, status);
+	/* when we get the roster back, we'll send our initial presence */
 }
 
 static void
--- a/libpurple/protocols/jabber/google.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/google.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1,4 +1,3 @@
-
 /**
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -30,7 +29,7 @@
 #include "presence.h"
 #include "iq.h"
 
-static void 
+static void
 jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul)
 {
 	const char *type = xmlnode_get_attrib(packet, "type");
@@ -40,57 +39,57 @@
 	const char *in_str;
 	char *to_name;
 	int i, count = 1, returned_count;
-	
+
 	const char **tos, **froms, **subjects, **urls;
-	
+
 	if (strcmp(type, "result"))
 		return;
-	
+
 	child = xmlnode_get_child(packet, "mailbox");
 	if (!child)
 		return;
 
 	in_str = xmlnode_get_attrib(child, "total-matched");
-	if (in_str && *in_str) 
+	if (in_str && *in_str)
 		count = atoi(in_str);
- 
-	if (count == 0) 
+
+	if (count == 0)
 		return;
 
 	message = xmlnode_get_child(child, "mail-thread-info");
-	
+
 	/* Loop once to see how many messages were returned so we can allocate arrays
 	 * accordingly */
-	if (!message) 
+	if (!message)
 		return;
 	for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message));
-	
+
 	froms    = g_new0(const char* , returned_count);
 	tos      = g_new0(const char* , returned_count);
 	subjects = g_new0(const char* , returned_count);
 	urls     = g_new0(const char* , returned_count);
-	
+
 	to = xmlnode_get_attrib(packet, "to");
 	to_name = jabber_get_bare_jid(to);
 	url = xmlnode_get_attrib(child, "url");
 	if (!url || !*url)
 		url = "http://www.gmail.com";
-	
+
 	message= xmlnode_get_child(child, "mail-thread-info");
 	for (i=0; message; message = xmlnode_get_next_twin(message), i++) {
 		subject_node = xmlnode_get_child(message, "subject");
 		sender_node  = xmlnode_get_child(message, "senders");
 		sender_node  = xmlnode_get_child(sender_node, "sender");
 
-		while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") || 
+		while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") ||
 		       !strcmp(xmlnode_get_attrib(sender_node, "unread"),"0")))
 			sender_node = xmlnode_get_next_twin(sender_node);
-		
+
 		if (!sender_node) {
 			i--;
 			continue;
 		}
-			
+
 		from = xmlnode_get_attrib(sender_node, "name");
 		if (!from || !*from)
 			from = xmlnode_get_attrib(sender_node, "address");
@@ -102,18 +101,18 @@
 		froms[i] = (from != NULL ?  from : "");
 		subjects[i] = (subject != NULL ? subject : "");
 		urls[i] = (url != NULL ? url : "");
-		
+
 		tid = xmlnode_get_attrib(message, "tid");
-		if (tid && 
+		if (tid &&
 		    (js->gmail_last_tid == NULL || strcmp(tid, js->gmail_last_tid) > 0)) {
 			g_free(js->gmail_last_tid);
 			js->gmail_last_tid = g_strdup(tid);
 		}
 	}
 
-	if (i>0) 
-		purple_notify_emails(js->gc, count, count == returned_count, subjects, froms, tos, 
-				   	   urls, NULL, NULL);
+	if (i>0)
+		purple_notify_emails(js->gc, count, count == returned_count, subjects, froms, tos,
+				urls, NULL, NULL);
 
 	g_free(to_name);
 	g_free(tos);
@@ -128,19 +127,19 @@
 	}
 }
 
-void 
-jabber_gmail_poke(JabberStream *js, xmlnode *packet) 
+void
+jabber_gmail_poke(JabberStream *js, xmlnode *packet)
 {
 	const char *type;
 	xmlnode *query;
 	JabberIq *iq;
-	
+
 	/* bail if the user isn't interested */
 	if (!purple_account_get_check_mail(js->gc->account))
 		return;
 
 	type = xmlnode_get_attrib(packet, "type");
-	
+
 
 	/* Is this an initial incoming mail notification? If so, send a request for more info */
 	if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail"))
@@ -165,7 +164,7 @@
 void jabber_gmail_init(JabberStream *js) {
 	JabberIq *iq;
 
-	if (!purple_account_get_check_mail(js->gc->account)) 
+	if (!purple_account_get_check_mail(js->gc->account))
 		return;
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "google:mail:notify");
@@ -180,7 +179,7 @@
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
 	query = xmlnode_get_child(iq->node, "query");
-	
+
 	xmlnode_set_attrib(query, "xmlns:gr", "google:roster");
 	xmlnode_set_attrib(query, "gr:ext", "2");
 
@@ -218,14 +217,14 @@
 
 	const char *grt = xmlnode_get_attrib_with_namespace(item, "t", "google:roster");
 	const char *subscription = xmlnode_get_attrib(item, "subscription");
-	
+
 	if (!subscription || !strcmp(subscription, "none")) {
 		/* The Google Talk servers will automatically add people from your Gmail address book
 		 * with subscription=none. If we see someone with subscription=none, ignore them.
 		 */
 		return FALSE;
 	}
-	
+
 	while (list) {
 		if (!strcmp(jid_norm, (char*)list->data)) {
 			on_block_list = TRUE;
@@ -233,13 +232,13 @@
 		}
 		list = list->next;
 	}
-	
+
 	if (grt && (*grt == 'H' || *grt == 'h')) {
 		PurpleBuddy *buddy = purple_find_buddy(account, jid_norm);
 		purple_blist_remove_buddy(buddy);
 		return FALSE;
 	}
-	
+
 	if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) {
 		purple_debug_info("jabber", "Blocking %s\n", jid_norm);
 		purple_privacy_deny_add(account, jid_norm, TRUE);
@@ -250,7 +249,7 @@
 	return TRUE;
 }
 
-void jabber_google_roster_add_deny(PurpleConnection *gc, const char *who) 
+void jabber_google_roster_add_deny(PurpleConnection *gc, const char *who)
 {
 	JabberStream *js;
 	GSList *buddies;
@@ -262,7 +261,7 @@
 	JabberBuddy *jb;
 
 	js = (JabberStream*)(gc->proto_data);
-	
+
 	if (!js || !js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
 		return;
 
@@ -271,11 +270,11 @@
 	buddies = purple_find_buddies(js->gc->account, who);
 	if(!buddies)
 		return;
-	
+
 	b = buddies->data;
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-	
+
 	query = xmlnode_get_child(iq->node, "query");
 	item = xmlnode_new_child(query, "item");
 
@@ -287,7 +286,7 @@
 
 		group = xmlnode_new_child(item, "group");
 		xmlnode_insert_data(group, g->name, -1);
-		
+
 		buddies = buddies->next;
 	}
 
@@ -333,20 +332,20 @@
 
 	g_return_if_fail(gc != NULL);
 	g_return_if_fail(who != NULL);
-	
+
 	js = (JabberStream*)(gc->proto_data);
-	
+
 	if (!js || !js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
 		return;
-	
+
 	buddies = purple_find_buddies(js->gc->account, who);
 	if(!buddies)
 		return;
-	
+
 	b = buddies->data;
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-	
+
 	query = xmlnode_get_child(iq->node, "query");
 	item = xmlnode_new_child(query, "item");
 
@@ -358,7 +357,7 @@
 
 		group = xmlnode_new_child(item, "group");
 		xmlnode_insert_data(group, g->name, -1);
-		
+
 		buddies = buddies->next;
 	}
 
@@ -440,15 +439,15 @@
 
 	for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
 		gunichar c = g_utf8_get_char(p);
- 
+
 		if (bold_count < 2 && italic_count < 2 && !in_bold && !in_italic) {
 			g_string_append(str, p);
 			return g_string_free(str, FALSE);
 		}
 
-		
+
 		if (c == '*' && !in_tag) {
-			if (in_bold && 
+			if (in_bold &&
 			    (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { /* This is safe in UTF-8 */
 				str = g_string_append(str, "</b>");
 				in_bold = FALSE;
@@ -490,6 +489,6 @@
 		} else {
 			str = g_string_append_unichar(str, c);
 		}
-	}	
+	}
 	return g_string_free(str, FALSE);
 }
--- a/libpurple/protocols/jabber/iq.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/iq.c	Tue Jun 19 17:28:41 2007 +0000
@@ -208,14 +208,18 @@
 
 static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet)
 {
-	const char *type, *from, *id;
+	const char *type, *id, *from;
 	JabberIq *iq;
-	xmlnode *query;
+
+	type = xmlnode_get_attrib(packet, "type");
+	from = xmlnode_get_attrib(packet, "from");
+	id = xmlnode_get_attrib(packet, "id");
 
 	if(type && !strcmp(type, "get")) {
 		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping");
 
 		jabber_iq_set_id(iq, id);
+		xmlnode_set_attrib(iq->node, "to", from);
 
 		jabber_iq_send(iq);
 	} else {
--- a/libpurple/protocols/jabber/jabber.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1038,8 +1038,6 @@
 
 void jabber_stream_set_state(JabberStream *js, JabberStreamState state)
 {
-	PurpleStoredImage *img;
-
 	js->state = state;
 	switch(state) {
 		case JABBER_STREAM_OFFLINE:
@@ -1071,14 +1069,6 @@
 
 			break;
 		case JABBER_STREAM_CONNECTED:
-			/* lets make sure our buddy icon is up to date
-			 * before we go letting people know we're here */
-			img = purple_buddy_icons_find_account_icon(js->gc->account);
-			if(NULL != img) {
-				jabber_set_buddy_icon(js->gc, img);
-				purple_imgstore_unref(img);
-			}
-
 			/* now we can alert the core that we're ready to send status */
 			purple_connection_set_state(js->gc, PURPLE_CONNECTED);
 			jabber_disco_items_server(js);
--- a/libpurple/protocols/jabber/jabber.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Tue Jun 19 17:28:41 2007 +0000
@@ -142,11 +142,17 @@
 #ifdef HAVE_CYRUS_SASL
 	sasl_conn_t *sasl;
 	sasl_callback_t *sasl_cb;
+#else /* keep the struct the same size */
+	void *sasl;
+	void *sasl_cb;
+#endif
+
 	int sasl_state;
 	int sasl_maxbuf;
 	GString *sasl_mechs;
 	char *serverFQDN;
-#endif
+
+	gboolean vcard_fetched;
 
 } JabberStream;
 
--- a/libpurple/protocols/jabber/jutil.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/jutil.c	Tue Jun 19 17:28:41 2007 +0000
@@ -221,7 +221,7 @@
 jabber_find_unnormalized_conv(const char *name, PurpleAccount *account)
 {
 	PurpleConversation *c = NULL;
-	const GList *cnv;
+	GList *cnv;
 
 	g_return_val_if_fail(name != NULL, NULL);
 
--- a/libpurple/protocols/jabber/presence.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/presence.c	Tue Jun 19 17:28:41 2007 +0000
@@ -102,6 +102,11 @@
 	JabberBuddyState state;
 	int priority;
 
+	if(NULL == status) {
+		PurplePresence *gpresence = purple_account_get_presence(account);
+		status = purple_presence_get_active_status(gpresence);
+	}
+
 	if(!purple_status_is_active(status))
 		return;
 
@@ -115,6 +120,12 @@
 	gc = purple_account_get_connection(account);
 	js = gc->proto_data;
 
+	/* we don't want to send presence before we've gotten our roster */
+	if(!js->roster_parsed) {
+		purple_debug_info("jabber", "attempt to send presence before roster retrieved\n");
+		return;
+	}
+
 	purple_status_to_jabber(status, &state, &stripped, &priority);
 
 
--- a/libpurple/protocols/jabber/roster.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/roster.c	Tue Jun 19 17:28:41 2007 +0000
@@ -153,8 +153,6 @@
 	if(!query)
 		return;
 
-	js->roster_parsed = TRUE;
-
 	for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item))
 	{
 		const char *jid, *name, *subscription, *ask;
@@ -232,6 +230,14 @@
 			add_purple_buddies_to_groups(js, jid, name, groups);
 		}
 	}
+
+	/* if we're just now parsing the roster for the first time,
+	 * then now would be the time to send our initial presence */
+	if(!js->roster_parsed) {
+		js->roster_parsed = TRUE;
+
+		jabber_presence_send(js->gc->account, NULL);
+	}
 }
 
 static void jabber_roster_update(JabberStream *js, const char *name,
--- a/libpurple/protocols/jabber/xdata.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/jabber/xdata.c	Tue Jun 19 17:28:41 2007 +0000
@@ -93,7 +93,7 @@
 				case JABBER_X_DATA_LIST_SINGLE:
 				case JABBER_X_DATA_LIST_MULTI:
 					{
-					const GList *selected = purple_request_field_list_get_selected(field);
+					GList *selected = purple_request_field_list_get_selected(field);
 					char *value;
 					fieldnode = xmlnode_new_child(result, "field");
 					xmlnode_set_attrib(fieldnode, "var", id);
--- a/libpurple/protocols/msn/msn.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1598,7 +1598,7 @@
 	purple_debug_info("msn", "In msn_got_info,url_text:{%s}\n",url_text);
 
 	/* Make sure the connection is still valid */
-	if (g_list_find((GList *)purple_connections_get_all(), info_data->gc) == NULL)
+	if (g_list_find(purple_connections_get_all(), info_data->gc) == NULL)
 	{
 		purple_debug_warning("msn", "invalid connection. ignoring buddy info.\n");
 		g_free(info_data->name);
@@ -2019,7 +2019,7 @@
 
 	/* Make sure the connection is still valid if we got here by fetching a photo url */
 	if (url_text && (error_message != NULL ||
-					 g_list_find((GList *)purple_connections_get_all(), info_data->gc) == NULL))
+					 g_list_find(purple_connections_get_all(), info_data->gc) == NULL))
 	{
 		purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n");
 		g_free(stripped);
@@ -2118,7 +2118,7 @@
 		if (acct && !purple_account_is_connected(acct))
 			acct = NULL;
 	} else { /* Otherwise find an active account for the protocol */
-		const GList *l = purple_accounts_get_all();
+		GList *l = purple_accounts_get_all();
 		while (l) {
 			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
 					&& purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/oscar/oscar.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue Jun 19 17:28:41 2007 +0000
@@ -2827,6 +2827,7 @@
 	va_list ap;
 	guint16 reason;
 	char *destn;
+	PurpleNotifyUserInfo *user_info;
 
 	va_start(ap, fr);
 	reason = (guint16) va_arg(ap, unsigned int);
@@ -2836,12 +2837,12 @@
 	if (destn == NULL)
 		return 1;
 
+	user_info = purple_notify_user_info_new();
 	buf = g_strdup_printf(_("User information not available: %s"), (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason."));
-	if (!purple_conv_present_error(destn, purple_connection_get_account((PurpleConnection*)od->gc), buf)) {
-		g_free(buf);
-		buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
-		purple_notify_error(od->gc, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason."));
-	}
+	purple_notify_user_info_add_pair(user_info, NULL, buf);
+	purple_notify_userinfo(od->gc, destn, user_info, NULL, NULL);
+	purple_notify_user_info_destroy(user_info);
+	purple_conv_present_error(destn, purple_connection_get_account(od->gc), buf);
 	g_free(buf);
 
 	return 1;
@@ -6558,7 +6559,7 @@
 		if (acct && !purple_account_is_connected(acct))
 			acct = NULL;
 	} else { /* Otherwise find an active account for the protocol */
-		const GList *l = purple_accounts_get_all();
+		GList *l = purple_accounts_get_all();
 		while (l) {
 			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
 					&& purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/qq/group_im.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/qq/group_im.c	Tue Jun 19 17:28:41 2007 +0000
@@ -341,7 +341,7 @@
 	read_packet_dw(data, cursor, data_len, &(im_group->member_uid));
 	read_packet_w(data, cursor, data_len, &unknown);	/* 0x0001? */
 	read_packet_w(data, cursor, data_len, &(im_group->msg_seq));
-	read_packet_dw(data, cursor, data_len, (guint32 *) & (im_group->send_time));
+	read_packet_time(data, cursor, data_len, &im_group->send_time);
 	read_packet_dw(data, cursor, data_len, &unknown4);	/* versionID */
 	/*
 	 * length includes font_attr
--- a/libpurple/protocols/qq/login_logout.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/qq/login_logout.c	Tue Jun 19 17:28:41 2007 +0000
@@ -181,7 +181,7 @@
 	/* 031-032: server listening port */
 	bytes += read_packet_w(data, &cursor, len, &lrop.server_port);
 	/* 033-036: login time for current session */
-	bytes += read_packet_dw(data, &cursor, len, (guint32 *) &lrop.login_time);
+	bytes += read_packet_time(data, &cursor, len, &lrop.login_time);
 	/* 037-062: 26 bytes, unknown */
 	bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown1, 26);
 	/* 063-066: unknown server1 ip address */
@@ -203,7 +203,7 @@
 	/* 123-126: login IP of last session */
 	bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.last_client_ip, 4);
 	/* 127-130: login time of last session */
-	bytes += read_packet_dw(data, &cursor, len, (guint32 *) &lrop.last_login_time);
+	bytes += read_packet_time(data, &cursor, len, &lrop.last_login_time);
 	/* 131-138: 8 bytes unknown */
 	bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown6, 8);
 
--- a/libpurple/protocols/qq/packet_parse.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/qq/packet_parse.c	Tue Jun 19 17:28:41 2007 +0000
@@ -65,6 +65,19 @@
 	}
 }
 
+/* read four bytes as "time_t" from buf,
+ * return the number of bytes read if succeeds, otherwise return -1
+ * This function is a wrapper around read_packet_dw() to avoid casting. */
+gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t)
+{
+	guint32 time;
+	gint ret = read_packet_dw(buf, cursor, buflen, &time);
+	if (ret != -1 ) {
+		*t = time;
+	}
+	return ret;
+}
+
 /* read datalen bytes from buf, 
  * return the number of bytes read if succeeds, otherwise return -1 */
 gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen) {
--- a/libpurple/protocols/qq/packet_parse.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/qq/packet_parse.h	Tue Jun 19 17:28:41 2007 +0000
@@ -26,6 +26,7 @@
 #define _QQ_PACKED_PARSE_H_
 
 #include <glib.h>
+#include <time.h>
 
 /* According to "UNIX Network Programming", all TCP/IP implementations
  * must support a minimum IP datagram size of 576 bytes, regardless of the MTU.
@@ -39,6 +40,7 @@
 gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b);
 gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w);
 gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw);
+gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t);
 gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen);
 gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b);
 gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w);
--- a/libpurple/protocols/sametime/sametime.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Tue Jun 19 17:28:41 2007 +0000
@@ -2660,7 +2660,7 @@
   GString *str;
 
   PurpleMimeDocument *doc;
-  const GList *parts;
+  GList *parts;
 
   img_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
   images = NULL;
@@ -3401,7 +3401,7 @@
 static void conf_select_prompt_invite(PurpleBuddy *buddy,
 				      PurpleRequestFields *fields) {
   PurpleRequestField *f;
-  const GList *l;
+  GList *l;
   const char *msg;
   
   f = purple_request_fields_get_field(fields, CHAT_KEY_INVITE);
@@ -5268,7 +5268,7 @@
 				       PurpleRequestFields *fields) {
   
   PurpleRequestField *f;
-  const GList *l;
+  GList *l;
 
   f = purple_request_fields_get_field(fields, "group");
   l = purple_request_field_list_get_items(f);
@@ -5334,7 +5334,7 @@
 static void remote_group_multi_cb(struct mwPurplePluginData *pd,
 				  PurpleRequestFields *fields) {
   PurpleRequestField *f;
-  const GList *l;
+  GList *l;
 
   f = purple_request_fields_get_field(fields, "group");
   l = purple_request_field_list_get_selected(f);
--- a/libpurple/protocols/silc/buddy.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/silc/buddy.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1117,7 +1117,7 @@
 silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
 {
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcClientEntry client_entry;
 	SilcDList clients;
 
--- a/libpurple/protocols/silc/chat.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/silc/chat.c	Tue Jun 19 17:28:41 2007 +0000
@@ -291,7 +291,7 @@
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcPublicKey public_key;
 	SilcBuffer chpks, pk, chidp;
 	SilcUInt16 c = 0, ct;
--- a/libpurple/protocols/silc10/buddy.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/silc10/buddy.c	Tue Jun 19 17:28:41 2007 +0000
@@ -1118,7 +1118,7 @@
 silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
 {
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcClientEntry client_entry;
 
 	f = purple_request_fields_get_field(fields, "list");
--- a/libpurple/protocols/silc10/chat.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/silc10/chat.c	Tue Jun 19 17:28:41 2007 +0000
@@ -278,7 +278,7 @@
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcPublicKey public_key;
 	SilcBuffer chpks, pk, chidp;
 	SilcUInt16 c = 0, ct;
--- a/libpurple/protocols/yahoo/yahoo.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Tue Jun 19 17:28:41 2007 +0000
@@ -3861,7 +3861,7 @@
 		if (acct && !purple_account_is_connected(acct))
 			acct = NULL;
 	} else { /* Otherwise find an active account for the protocol */
-		const GList *l = purple_accounts_get_all();
+		GList *l = purple_accounts_get_all();
 		while (l) {
 			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
 					&& purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo_doodle.c	Tue Jun 19 17:28:41 2007 +0000
@@ -491,7 +491,8 @@
 
 	/* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
 
-	yahoo_doodle_command_send_shutdown(gc, wb->who);
+	if (gc)
+		yahoo_doodle_command_send_shutdown(gc, wb->who);
 
 	g_free(wb->proto_data);
 }
--- a/libpurple/protocols/yahoo/yahoochat.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Tue Jun 19 17:28:41 2007 +0000
@@ -633,10 +633,10 @@
  * I think conference names are always ascii.
  */
 
-void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, const GList *who)
+void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who)
 {
 	struct yahoo_packet *pkt;
-	const GList *w;
+	GList *w;
 
 	purple_debug_misc("yahoo", "leaving conference %s\n", room);
 	
@@ -653,11 +653,11 @@
 }
 
 static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
-							const GList *members, const char *what)
+							GList *members, const char *what)
 {
 	struct yahoo_data *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
-	const GList *who;
+	GList *who;
 	char *msg, *msg2;
 	int utf8 = 1;
 
@@ -714,7 +714,7 @@
 {
 	struct yahoo_data *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
-	const GList *members;
+	GList *members;
 	char *msg2 = NULL;
 
 	if (msg)
--- a/libpurple/protocols/yahoo/yahoochat.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.h	Tue Jun 19 17:28:41 2007 +0000
@@ -50,7 +50,7 @@
 char *yahoo_get_chat_name(GHashTable *data);
 void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
 
-void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, const GList *who);
+void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who);
 
 void yahoo_chat_goto(PurpleConnection *gc, const char *name);
 
--- a/libpurple/protocols/zephyr/ZLocations.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/protocols/zephyr/ZLocations.c	Tue Jun 19 17:28:41 2007 +0000
@@ -36,7 +36,8 @@
     return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, ZAUTH, ""));
 }
 
-static char host[MAXHOSTNAMELEN], mytty[MAXPATHLEN];
+static char host[MAXHOSTNAMELEN];
+static char *mytty = NULL;
 static int reenter = 0;
 
 Code_t Z_SendLocation(class, opcode, auth, format)
@@ -87,21 +88,20 @@
 	    }
 #ifndef X_DISPLAY_MISSING
 	    if ((display = getenv("DISPLAY")) && *display) {
-		    (void) strncpy(mytty, display, sizeof(mytty));
+		    mytty = g_strdup(display);
 	    } else {
 #endif
 #ifdef WIN32
-              	    strncpy(mytty, "WinPurple", sizeof(mytty));
+		    mytty = g_strdup("WinPurple");
 #else
 		    ttyp = ttyname(0);
 		    if (ttyp && *ttyp) {
 			p = strchr(ttyp + 1, '/');
-			strcpy(mytty, (p) ? p + 1 : ttyp);
+			mytty = g_strdup((p) ? p + 1 : ttyp);
 		    } else {
-			strncpy(mytty, "unknown", sizeof(mytty));
+			mytty = g_strdup("unknown");
 		    }
 #endif
-		    mytty[sizeof(mytty)-1] = '\0';
 #ifndef X_DISPLAY_MISSING
 	    }
 #endif
@@ -114,7 +114,6 @@
     bptr[1][strlen(bptr[1])-1] = '\0';
     bptr[2] = mytty;
 
-	
     if ((retval = ZSendList(&notice, bptr, 3, auth)) != ZERR_NONE)
 	return (retval);
 
--- a/libpurple/prpl.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/prpl.c	Tue Jun 19 17:28:41 2007 +0000
@@ -265,7 +265,7 @@
 purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence)
 {
 	GList *statuses = NULL;
-	const GList *l;
+	GList *l;
 	PurpleStatus *status;
 
 	g_return_val_if_fail(account  != NULL, NULL);
--- a/libpurple/prpl.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/prpl.h	Tue Jun 19 17:28:41 2007 +0000
@@ -378,7 +378,7 @@
  *                  beginning with the value for @a attr_id.
  */
 void purple_prpl_got_account_status(PurpleAccount *account,
-								  const char *status_id, ...);
+								  const char *status_id, ...) G_GNUC_NULL_TERMINATED;
 /**
  * Notifies Purple that a user's idle state and time have changed.
  *
@@ -418,7 +418,7 @@
  *                  beginning with the value for @a attr_id.
  */
 void purple_prpl_got_user_status(PurpleAccount *account, const char *name,
-							   const char *status_id, ...);
+							   const char *status_id, ...) G_GNUC_NULL_TERMINATED;
 
 /**
  * Notifies libpurple that a user's status has been deactivated
--- a/libpurple/request.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/request.c	Tue Jun 19 17:28:41 2007 +0000
@@ -111,7 +111,7 @@
 	return (g_hash_table_lookup(fields->fields, id) != NULL);
 }
 
-const GList *
+GList *
 purple_request_fields_get_required(const PurpleRequestFields *fields)
 {
 	g_return_val_if_fail(fields != NULL, NULL);
@@ -872,9 +872,9 @@
 }
 
 void
-purple_request_field_list_set_selected(PurpleRequestField *field, const GList *items)
+purple_request_field_list_set_selected(PurpleRequestField *field, GList *items)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(field != NULL);
 	g_return_if_fail(items != NULL);
@@ -883,7 +883,7 @@
 	purple_request_field_list_clear_selected(field);
 
 	if (!purple_request_field_list_get_multi_select(field) &&
-		g_list_length((GList*)items) > 1)
+		g_list_length(items) > 1)
 	{
 		purple_debug_warning("request",
 						   "More than one item added to non-multi-select "
@@ -913,7 +913,7 @@
 										item, NULL, NULL);
 }
 
-const GList *
+GList *
 purple_request_field_list_get_selected(const PurpleRequestField *field)
 {
 	g_return_val_if_fail(field != NULL, NULL);
@@ -922,7 +922,7 @@
 	return field->u.list.selected;
 }
 
-const GList *
+GList *
 purple_request_field_list_get_items(const PurpleRequestField *field)
 {
 	g_return_val_if_fail(field != NULL, NULL);
--- a/libpurple/request.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/request.h	Tue Jun 19 17:28:41 2007 +0000
@@ -285,9 +285,9 @@
  *
  * @param fields The fields list.
  *
- * @return The list of required fields.
+ * @constreturn The list of required fields.
  */
-const GList *purple_request_fields_get_required(const PurpleRequestFields *fields);
+GList *purple_request_fields_get_required(const PurpleRequestFields *fields);
 
 /**
  * Returns whether or not a field with the specified ID is required.
@@ -917,10 +917,10 @@
  * Sets a list of selected items in a list field.
  *
  * @param field The field.
- * @param items The list of selected items.
+ * @param items The list of selected items, which is not modified or freed.
  */
 void purple_request_field_list_set_selected(PurpleRequestField *field,
-										  const GList *items);
+										  GList *items);
 
 /**
  * Returns whether or not a particular item is selected in a list field.
@@ -941,9 +941,9 @@
  *
  * @param field The field.
  *
- * @return The list of selected items.
+ * @constreturn The list of selected items.
  */
-const GList *purple_request_field_list_get_selected(
+GList *purple_request_field_list_get_selected(
 	const PurpleRequestField *field);
 
 /**
@@ -951,9 +951,9 @@
  *
  * @param field The field.
  *
- * @return The list of items.
+ * @constreturn The list of items.
  */
-const GList *purple_request_field_list_get_items(const PurpleRequestField *field);
+GList *purple_request_field_list_get_items(const PurpleRequestField *field);
 
 /*@}*/
 
@@ -1228,7 +1228,7 @@
 						  const char *ok_text, GCallback ok_cb,
 						  const char *cancel_text, GCallback cancel_cb,
 						  PurpleAccount *account, const char *who, PurpleConversation *conv,
-						  void *user_data, ...);
+						  void *user_data, ...) G_GNUC_NULL_TERMINATED;
 
 /**
  * Prompts the user for multiple-choice input.
--- a/libpurple/savedstatuses.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/savedstatuses.c	Tue Jun 19 17:28:41 2007 +0000
@@ -569,6 +569,9 @@
 
 	schedule_save();
 
+	purple_signal_emit(purple_savedstatuses_get_handle(), "savedstatus-added",
+		status);
+
 	return status;
 }
 
@@ -584,6 +587,9 @@
 	status->title = g_strdup(title);
 
 	schedule_save();
+
+	purple_signal_emit(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", status);
 }
 
 void
@@ -594,6 +600,8 @@
 	status->type = type;
 
 	schedule_save();
+	purple_signal_emit(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", status);
 }
 
 void
@@ -608,6 +616,9 @@
 		status->message = g_strdup(message);
 
 	schedule_save();
+
+	purple_signal_emit(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", status);
 }
 
 void
@@ -637,6 +648,8 @@
 	substatus->message = g_strdup(message);
 
 	schedule_save();
+	purple_signal_emit(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", saved_status);
 }
 
 void
@@ -660,6 +673,9 @@
 			return;
 		}
 	}
+
+	purple_signal_emit(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", saved_status);
 }
 
 /*
@@ -683,16 +699,12 @@
 	}
 }
 
-gboolean
-purple_savedstatus_delete(const char *title)
+void
+purple_savedstatus_delete_by_status(PurpleSavedStatus *status)
 {
-	PurpleSavedStatus *status;
 	time_t creation_time, current, idleaway;
 
-	status = purple_savedstatus_find(title);
-
-	if (status == NULL)
-		return FALSE;
+	g_return_if_fail(status != NULL);
 
 	saved_statuses = g_list_remove(saved_statuses, status);
 	creation_time = purple_savedstatus_get_creation_time(status);
@@ -713,10 +725,29 @@
 	if (idleaway == creation_time)
 		purple_prefs_set_int("/purple/savedstatus/idleaway", 0);
 
+	purple_signal_emit(purple_savedstatuses_get_handle(),
+			"savedstatus-deleted", status);
+}
+
+gboolean
+purple_savedstatus_delete(const char *title)
+{
+	PurpleSavedStatus *status;
+
+	status = purple_savedstatus_find(title);
+
+	if (status == NULL)
+		return FALSE;
+
+	if (purple_savedstatus_get_current() == status)
+		return FALSE;
+
+	purple_savedstatus_delete_by_status(status);
+
 	return TRUE;
 }
 
-const GList *
+GList *
 purple_savedstatuses_get_all(void)
 {
 	return saved_statuses;
@@ -1171,6 +1202,21 @@
 					 purple_value_new(PURPLE_TYPE_SUBTYPE,
 									PURPLE_SUBTYPE_SAVEDSTATUS));
 
+	purple_signal_register(handle, "savedstatus-added",
+		purple_marshal_VOID__POINTER, NULL, 1,
+		purple_value_new(PURPLE_TYPE_SUBTYPE,
+			PURPLE_SUBTYPE_SAVEDSTATUS));
+
+	purple_signal_register(handle, "savedstatus-deleted",
+		purple_marshal_VOID__POINTER, NULL, 1,
+		purple_value_new(PURPLE_TYPE_SUBTYPE,
+			PURPLE_SUBTYPE_SAVEDSTATUS));
+
+	purple_signal_register(handle, "savedstatus-modified",
+		purple_marshal_VOID__POINTER, NULL, 1,
+		purple_value_new(PURPLE_TYPE_SUBTYPE,
+			PURPLE_SUBTYPE_SAVEDSTATUS));
+
 	purple_signal_connect(purple_accounts_get_handle(), "account-removed",
 			handle,
 			PURPLE_CALLBACK(purple_savedstatus_unset_all_substatuses),
--- a/libpurple/savedstatuses.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/savedstatuses.h	Tue Jun 19 17:28:41 2007 +0000
@@ -149,11 +149,21 @@
 gboolean purple_savedstatus_delete(const char *title);
 
 /**
+ * Delete a saved status.  This removes the saved status from the list
+ * of saved statuses, and writes the revised list to status.xml.
+ *
+ * @param saved_status the status to delete, the pointer is invalid after
+ *        the call
+ *
+ */
+void purple_savedstatus_delete_by_status(PurpleSavedStatus *saved_status);
+
+/**
  * Returns all saved statuses.
  *
- * @return A list of saved statuses.
+ * @constreturn A list of saved statuses.
  */
-const GList *purple_savedstatuses_get_all(void);
+GList *purple_savedstatuses_get_all(void);
 
 /**
  * Returns the n most popular saved statuses.  "Popularity" is
--- a/libpurple/status.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/status.c	Tue Jun 19 17:28:41 2007 +0000
@@ -451,7 +451,7 @@
 	return NULL;
 }
 
-const GList *
+GList *
 purple_status_type_get_attrs(const PurpleStatusType *status_type)
 {
 	g_return_val_if_fail(status_type != NULL, NULL);
@@ -548,7 +548,7 @@
 purple_status_new(PurpleStatusType *status_type, PurplePresence *presence)
 {
 	PurpleStatus *status;
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(status_type != NULL, NULL);
 	g_return_val_if_fail(presence    != NULL, NULL);
@@ -719,10 +719,10 @@
 
 void
 purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
-									   const GList *attrs)
+									   GList *attrs)
 {
 	gboolean changed = FALSE;
-	const GList *l;
+	GList *l;
 	GList *specified_attr_ids = NULL;
 	PurpleStatusType *status_type;
 
@@ -1168,9 +1168,9 @@
 }
 
 void
-purple_presence_add_list(PurplePresence *presence, const GList *source_list)
+purple_presence_add_list(PurplePresence *presence, GList *source_list)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(presence    != NULL);
 	g_return_if_fail(source_list != NULL);
@@ -1396,7 +1396,7 @@
 	return presence->u.buddy.buddy;
 }
 
-const GList *
+GList *
 purple_presence_get_statuses(const PurplePresence *presence)
 {
 	g_return_val_if_fail(presence != NULL, NULL);
@@ -1408,7 +1408,7 @@
 purple_presence_get_status(const PurplePresence *presence, const char *status_id)
 {
 	PurpleStatus *status;
-	const GList *l = NULL;
+	GList *l = NULL;
 
 	g_return_val_if_fail(presence  != NULL, NULL);
 	g_return_val_if_fail(status_id != NULL, NULL);
@@ -1487,7 +1487,7 @@
 purple_presence_is_status_primitive_active(const PurplePresence *presence,
 		PurpleStatusPrimitive primitive)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(presence  != NULL,              FALSE);
 	g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, FALSE);
@@ -1535,7 +1535,7 @@
 	gboolean idle1, idle2;
 	time_t idle_time_1, idle_time_2;
 	int score1 = 0, score2 = 0;
-	const GList *l;
+	GList *l;
 
 	if (presence1 == presence2)
 		return 0;
--- a/libpurple/status.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/status.h	Tue Jun 19 17:28:41 2007 +0000
@@ -227,7 +227,7 @@
 												gboolean independent,
 												const char *attr_id,
 												const char *attr_name,
-												PurpleValue *attr_value, ...);
+												PurpleValue *attr_value, ...) G_GNUC_NULL_TERMINATED;
 
 /**
  * Destroys a status type.
@@ -270,7 +270,7 @@
  * @param ...         Additional attribute information.
  */
 void purple_status_type_add_attrs(PurpleStatusType *status_type, const char *id,
-								const char *name, PurpleValue *value, ...);
+								const char *name, PurpleValue *value, ...) G_GNUC_NULL_TERMINATED;
 
 /**
  * Adds multiple attributes to a status type using a va_list.
@@ -387,9 +387,9 @@
  *
  * @param status_type The status type.
  *
- * @return The list of attributes.
+ * @constreturn The list of attributes.
  */
-const GList *purple_status_type_get_attrs(const PurpleStatusType *status_type);
+GList *purple_status_type_get_attrs(const PurpleStatusType *status_type);
 
 /**
  * Find the PurpleStatusType with the given id.
@@ -515,10 +515,11 @@
  * @param active The active state.
  * @param attrs  A list of attributes to set on the status.  This list is
  *               composed of key/value pairs, where each key is a valid
- *               attribute name for this PurpleStatusType.
+ *               attribute name for this PurpleStatusType.  The list is
+ *               not modified or freed by this function.
  */
 void purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
-											const GList *attrs);
+											GList *attrs);
 
 /**
  * Sets the boolean value of an attribute in a status with the specified ID.
@@ -768,9 +769,10 @@
  * Adds a list of statuses to the presence.
  *
  * @param presence    The presence.
- * @param source_list The source list of statuses to add.
+ * @param source_list The source list of statuses to add, which is not
+ *                    modified or freed by this function.
  */
-void purple_presence_add_list(PurplePresence *presence, const GList *source_list);
+void purple_presence_add_list(PurplePresence *presence, GList *source_list);
 
 /**
  * Sets the active state of a status in a presence.
@@ -869,9 +871,9 @@
  *
  * @param presence The presence.
  *
- * @return The statuses.
+ * @constreturn The statuses.
  */
-const GList *purple_presence_get_statuses(const PurplePresence *presence);
+GList *purple_presence_get_statuses(const PurplePresence *presence);
 
 /**
  * Returns the status with the specified ID from a presence.
--- a/libpurple/util.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/libpurple/util.c	Tue Jun 19 17:28:41 2007 +0000
@@ -66,8 +66,8 @@
 	unsigned long data_len;
 };
 
-static char custom_home_dir[MAXPATHLEN];
-static char home_dir[MAXPATHLEN] = "";
+static char *custom_user_dir = NULL;
+static char *home_dir = NULL;
 
 PurpleMenuAction *
 purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data,
@@ -2396,27 +2396,22 @@
 const char *
 purple_user_dir(void)
 {
-	if (custom_home_dir != NULL && *custom_home_dir) {
-		strcpy ((char*) &home_dir, (char*) &custom_home_dir);
-	} else if (!*home_dir) {
-		const gchar *hd = purple_home_dir();
-
-		if (hd) {
-			g_strlcpy((char*) &home_dir, hd, sizeof(home_dir));
-			g_strlcat((char*) &home_dir, G_DIR_SEPARATOR_S ".purple",
-					sizeof(home_dir));
-		}
-	}
+	if (custom_user_dir != NULL)
+		return custom_user_dir;
+	else if (!home_dir)
+		home_dir = g_build_filename(purple_home_dir(), ".purple", NULL);
 
 	return home_dir;
 }
 
 void purple_util_set_user_dir(const char *dir)
 {
-	if (dir != NULL && strlen(dir) > 0) {
-		g_strlcpy((char*) &custom_home_dir, dir,
-				sizeof(custom_home_dir));
-	}
+	g_free(custom_user_dir);
+
+	if (dir != NULL && *dir)
+		custom_user_dir = g_strdup(dir);
+	else
+		custom_user_dir = NULL;
 }
 
 int purple_build_dir (const char *path, int mode)
@@ -3135,7 +3130,7 @@
 char *
 purple_str_size_to_units(size_t size)
 {
-	static const char *size_str[4] = { "bytes", "KB", "MB", "GB" };
+	static const char *size_str[4] = { "bytes", "KiB", "MiB", "GiB" };
 	float size_mag;
 	int size_index = 0;
 
--- a/pidgin/gtkaccount.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkaccount.c	Tue Jun 19 17:28:41 2007 +0000
@@ -697,7 +697,7 @@
 	PurpleAccountOption *option;
 	PurpleAccount *account;
 	GtkWidget *frame, *vbox, *check, *entry, *combo, *menu, *item;
-	const GList *list, *node;
+	GList *list, *node;
 	gint i, idx, int_value;
 	GtkListStore *model;
 	GtkTreeIter iter;
@@ -1586,7 +1586,7 @@
 
 	account = purple_connection_get_account(gc);
 	model = GTK_TREE_MODEL(accounts_window->model);
-	index = g_list_index((GList *)purple_accounts_get_all(), account);
+	index = g_list_index(purple_accounts_get_all(), account);
 
 	if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index))
 	{
@@ -1789,13 +1789,13 @@
 				case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
 					move_account_after(dialog->model, &dialog->drag_iter,
 									   &iter);
-					dest_index = g_list_index((GList *)purple_accounts_get_all(),
+					dest_index = g_list_index(purple_accounts_get_all(),
 											  account) + 1;
 					break;
 
 				case GTK_TREE_VIEW_DROP_BEFORE:
 				case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
-					dest_index = g_list_index((GList *)purple_accounts_get_all(),
+					dest_index = g_list_index(purple_accounts_get_all(),
 											  account);
 
 					move_account_before(dialog->model, &dialog->drag_iter,
@@ -2094,7 +2094,7 @@
 static gboolean
 populate_accounts_list(AccountsWindow *dialog)
 {
-	const GList *l;
+	GList *l;
 	gboolean ret = FALSE;
 	GdkPixbuf *global_buddyicon = NULL;
 	const char *path;
@@ -2298,7 +2298,7 @@
 global_buddyicon_changed(const char *name, PurplePrefType type,
 			gconstpointer value, gpointer window)
 {
-	const GList *list;
+	GList *list;
 	for (list = purple_accounts_get_all(); list; list = list->next) {
 		account_modified_cb(list->data, window);
 	}
@@ -2429,7 +2429,7 @@
 {
 	PurpleConnection *gc = purple_account_get_connection(data->account);
 
-	if (g_list_find((GList *)purple_connections_get_all(), gc))
+	if (g_list_find(purple_connections_get_all(), gc))
 	{
 		purple_blist_request_add_buddy(data->account, data->username,
 									 NULL, data->alias);
@@ -2686,3 +2686,4 @@
 	purple_signals_unregister_by_instance(pidgin_account_get_handle());
 }
 
+
--- a/pidgin/gtkblist.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkblist.c	Tue Jun 19 17:28:41 2007 +0000
@@ -696,7 +696,7 @@
 gboolean
 pidgin_blist_joinchat_is_showable()
 {
-	const GList *c;
+	GList *c;
 	PurpleConnection *gc;
 
 	for (c = purple_connections_get_all(); c != NULL; c = c->next) {
@@ -1551,7 +1551,7 @@
 add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list,
 					   const char *alias)
 {
-	const GList *l;
+	GList *l;
 	PurpleAccount *account = NULL;
 	PurpleConnection *gc;
 
@@ -2860,7 +2860,6 @@
 	{ N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD },
 	{ N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD },
 	{ "/Buddies/sep3", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Buddies/_About Pidgin"), NULL, pidgin_dialogs_about, 0,  "<Item>", NULL },
 	{ N_("/Buddies/_Quit"), "<CTL>Q", purple_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
 
 	/* Accounts menu */
@@ -2877,7 +2876,6 @@
 	{ N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL },
 	{ N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
 	{ N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL },
-	{ N_("/Tools/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
 	{ "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
 	/* Help */
@@ -2909,7 +2907,7 @@
 		prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-		if (g_list_length((GList *)purple_connections_get_all()) > 1)
+		if (g_list_length(purple_connections_get_all()) > 1)
 		{
 			tmp = g_markup_escape_text(chat->account->username, -1);
 			g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp);
@@ -2974,7 +2972,7 @@
 		user_info = purple_notify_user_info_new();
 
 		/* Account */
-		if (full && g_list_length((GList *)purple_connections_get_all()) > 1)
+		if (full && g_list_length(purple_connections_get_all()) > 1)
 		{
 			tmp = g_markup_escape_text(purple_account_get_username(
 									   purple_buddy_get_account(b)), -1);
@@ -3284,7 +3282,7 @@
 	return ret;
 }
 
-static gchar *pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected)
+gchar *pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected)
 {
 	const char *name;
 	char *esc, *text = NULL;
@@ -4234,7 +4232,7 @@
 				{"application/x-im-contact", 0, DRAG_BUDDY},
 				{"text/x-vcard", 0, DRAG_VCARD }};
 	if (gtkblist && gtkblist->window) {
-		purple_blist_set_visible(TRUE);
+		purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible"));
 		return;
 	}
 
@@ -5030,6 +5028,7 @@
 	PurpleContact *contact;
 	PurpleBuddy *buddy;
 	struct _pidgin_blist_node *gtknode;
+
 	if (editing_blist)
 		return;
 
@@ -5128,6 +5127,7 @@
 	PurpleChat *chat;
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
 	if (editing_blist)
 		return;
 
@@ -5731,7 +5731,7 @@
 {
 	PidginAddChatData *data;
 	PidginBuddyList *gtkblist;
-	const GList *l;
+	GList *l;
 	PurpleConnection *gc;
 	GtkWidget *label;
 	GtkWidget *rowbox;
@@ -6498,8 +6498,7 @@
 {
 	GtkWidget *menuitem = NULL, *submenu = NULL;
 	GtkAccelGroup *accel_group = NULL;
-	GList *l = NULL;
-	const GList *accounts;
+	GList *l = NULL, *accounts = NULL;
 	gboolean disabled_accounts = FALSE;
 
 	if (accountmenu == NULL)
@@ -6736,3 +6735,4 @@
 	if (activeitem)
 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE);
 }
+
--- a/pidgin/gtkblist.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkblist.h	Tue Jun 19 17:28:41 2007 +0000
@@ -360,4 +360,13 @@
 void pidgin_blist_set_headline(const char *text, GdkPixbuf *pixbuf, GCallback callback, gpointer user_data,
 		GDestroyNotify destroy);
 
+/**
+ * Returns a buddy's Pango markup appropriate for setting in a GtkCellRenderer.
+ *
+ * @param buddy The buddy to return markup from
+ * @param selected  Whether this buddy is selected. If TRUE, the markup will not change the color.
+ * @return The markup for this buddy
+ */
+gchar *pidgin_blist_get_name_markup(PurpleBuddy *buddy, gboolean selected);
+
 #endif /* _PIDGINBLIST_H_ */
--- a/pidgin/gtkconv.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkconv.c	Tue Jun 19 17:28:41 2007 +0000
@@ -82,6 +82,12 @@
 	PIDGIN_CONV_COLORIZE_TITLE		= 1 << 6
 }PidginConvFields;
 
+enum {
+	ICON_COLUMN,
+	TEXT_COLUMN,
+	NUM_COLUMNS
+} PidginInfopaneColumns;
+
 #define	PIDGIN_CONV_ALL	((1 << 7) - 1)
 
 #define SEND_COLOR "#204a87"
@@ -2350,6 +2356,9 @@
 	gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status);
 	gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status);
 
+	gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter),
+			ICON_COLUMN, status, -1);
+
 	if (status != NULL)
 		g_object_unref(status);
 
@@ -2409,11 +2418,7 @@
 			PURPLE_ICON_SCALE_DISPLAY, &scale_width, &scale_height);
 
 	/* this code is ugly, and scares me */
-	scale = gdk_pixbuf_scale_simple(buf,
-		MAX(gdk_pixbuf_get_width(buf) * scale_width /
-		    gdk_pixbuf_animation_get_width(gtkconv->u.im->anim), 1),
-		MAX(gdk_pixbuf_get_height(buf) * scale_height /
-		    gdk_pixbuf_animation_get_height(gtkconv->u.im->anim), 1),
+	scale = gdk_pixbuf_scale_simple(buf, 32, 32,
 		GDK_INTERP_BILINEAR);
 
 	gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->u.im->icon), scale);
@@ -2690,7 +2695,7 @@
 										gboolean hidden_only,
 										guint max_count)
 {
-	const GList *l;
+	GList *l;
 	GList *r = NULL;
 	guint c = 0;
 
@@ -3850,7 +3855,7 @@
 		g_list_free(list);
 	} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
-		const GList *l = purple_conv_chat_get_users(chat);
+		GList *l = purple_conv_chat_get_users(chat);
 		GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list));
 		GtkTreeIter iter;
 		int f;
@@ -4378,6 +4383,8 @@
 setup_common_pane(PidginConversation *gtkconv)
 {
 	GtkWidget *paned, *vbox, *frame, *imhtml_sw;
+	GtkCellRenderer *rend;
+	GtkTreePath *path;
 	PurpleConversation *conv = gtkconv->active_conv;
 	gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT);
 	GtkPolicyType imhtml_sw_hscroll;
@@ -4390,6 +4397,35 @@
 	gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
 	gtk_widget_show(vbox);
 
+	/* Setup the info pane */
+	gtkconv->infopane_hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), gtkconv->infopane_hbox, FALSE, FALSE, 0);
+	gtk_widget_show(gtkconv->infopane_hbox);
+
+	gtkconv->infopane = gtk_cell_view_new();
+	gtkconv->infopane_model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+	gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane), gtkconv->infopane_model);
+	gtk_list_store_append(gtkconv->infopane_model, &(gtkconv->infopane_iter));
+	gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), gtkconv->infopane, TRUE, TRUE, 0);
+        path = gtk_tree_path_new_from_string("0");
+        gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(gtkconv->infopane), path);
+	gtk_widget_set_size_request(gtkconv->infopane, -1, 32);
+	gtk_widget_show(gtkconv->infopane);
+
+	rend = gtk_cell_renderer_pixbuf_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", ICON_COLUMN, NULL);
+        g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL);
+
+	rend = gtk_cell_renderer_text_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, TRUE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "markup", TEXT_COLUMN, NULL);
+        g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL);
+
+#if GTK_CHECK_VERSION(2, 6, 0)
+	g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+#endif
+
 	/* Setup the gtkimhtml widget */
 	frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
 	if (chat) {
@@ -5446,7 +5482,7 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	gtkchat = gtkconv->u.chat;
 
-	num_users = g_list_length((GList *)purple_conv_chat_get_users(chat));
+	num_users = g_list_length(purple_conv_chat_get_users(chat));
 
 	g_snprintf(tmp, sizeof(tmp),
 			   ngettext("%d person in room", "%d people in room",
@@ -5540,7 +5576,7 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	gtkchat = gtkconv->u.chat;
 
-	num_users = g_list_length((GList *)purple_conv_chat_get_users(chat));
+	num_users = g_list_length(purple_conv_chat_get_users(chat));
 
 	for (l = users; l != NULL; l = l->next) {
 		model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
@@ -5981,8 +6017,10 @@
 			buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE;
 		}
 
-		if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) ||
-				conv->features & PURPLE_CONNECTION_NO_IMAGES)
+		if (!(prpl_info->options & OPT_PROTO_IM_IMAGE))
+			conv->features |= PURPLE_CONNECTION_NO_IMAGES;
+
+		if(conv->features & PURPLE_CONNECTION_NO_IMAGES)
 			buttons &= ~GTK_IMHTML_IMAGE;
 
 		gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons);
@@ -5995,7 +6033,7 @@
 		gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
 		gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
 		gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML));
-		gtk_widget_set_sensitive(win->menu.insert_image, (prpl_info->options & OPT_PROTO_IM_IMAGE) && !(conv->features & PURPLE_CONNECTION_NO_IMAGES));
+		gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 		{
@@ -6120,6 +6158,8 @@
 		char *title;
 		PurpleConvIm *im = NULL;
 		PurpleAccount *account = purple_conversation_get_account(conv);
+		PurpleBuddy *buddy; 
+		char *markup;
 		AtkObject *accessibility_obj;
 		/* I think this is a little longer than it needs to be but I'm lazy. */
 		char style[51];
@@ -6135,6 +6175,17 @@
 		else
 			title = g_strdup(purple_conversation_get_title(conv));
 
+		buddy = purple_find_buddy(account, conv->name);
+		if (buddy)
+			markup = pidgin_blist_get_name_markup(buddy, FALSE);
+		else
+			markup = title;
+		gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter),
+				TEXT_COLUMN, markup, -1);
+	
+		if (title != markup)
+			g_free(markup);
+
 		*style = '\0';
 
 		if (!GTK_WIDGET_REALIZED(gtkconv->tab_label))
@@ -6294,7 +6345,6 @@
 	GdkPixbuf *buf;
 
 	GtkWidget *event;
-	GtkWidget *frame;
 	GdkPixbuf *scale;
 	int scale_width, scale_height;
 
@@ -6403,24 +6453,13 @@
 			start_anim(NULL, gtkconv);
 	}
 
-	pidgin_buddy_icon_get_scale_size(buf, &prpl_info->icon_spec,
-			PURPLE_ICON_SCALE_DISPLAY, &scale_width, &scale_height);
-	scale = gdk_pixbuf_scale_simple(buf,
-				MAX(gdk_pixbuf_get_width(buf) * scale_width /
-				    gdk_pixbuf_animation_get_width(gtkconv->u.im->anim), 1),
-				MAX(gdk_pixbuf_get_height(buf) * scale_height /
-				    gdk_pixbuf_animation_get_height(gtkconv->u.im->anim), 1),
+	scale = gdk_pixbuf_scale_simple(buf, 32, 32,
 				GDK_INTERP_BILINEAR);
 
 	gtkconv->u.im->icon_container = gtk_vbox_new(FALSE, 0);
 
-	frame = gtk_frame_new(NULL);
-	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
-	gtk_box_pack_start(GTK_BOX(gtkconv->u.im->icon_container), frame,
-					   FALSE, FALSE, 0);
-
 	event = gtk_event_box_new();
-	gtk_container_add(GTK_CONTAINER(frame), event);
+	gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event);
 	g_signal_connect(G_OBJECT(event), "button-press-event",
 					 G_CALLBACK(icon_menu), gtkconv);
 	gtk_widget_show(event);
@@ -6428,19 +6467,16 @@
 	gtkconv->u.im->icon = gtk_image_new_from_pixbuf(scale);
 	gtkconv->auto_resize = TRUE;
 	/* Reset the size request to allow the buddy icon to resize */
-	gtk_widget_set_size_request(gtkconv->lower_hbox, -1, -1);
 	g_idle_add(reset_auto_resize_cb, gtkconv);
-	gtk_widget_set_size_request(gtkconv->u.im->icon, scale_width, scale_height);
 	gtk_container_add(GTK_CONTAINER(event), gtkconv->u.im->icon);
 	gtk_widget_show(gtkconv->u.im->icon);
 
 	g_object_unref(G_OBJECT(scale));
 
-	gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox),
+	gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox),
 			   gtkconv->u.im->icon_container, FALSE, FALSE, 0);
 
 	gtk_widget_show(gtkconv->u.im->icon_container);
-	gtk_widget_show(frame);
 
 	/* The buddy icon code needs badly to be fixed. */
 	if(pidgin_conv_window_is_active_conversation(conv))
@@ -6537,7 +6573,7 @@
 close_on_tabs_pref_cb(const char *name, PurplePrefType type,
 					  gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 
@@ -6561,7 +6597,7 @@
 				   gconstpointer value, gpointer data)
 {
 #ifdef USE_GTKSPELL
-	const GList *cl;
+	GList *cl;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	GtkSpell *spell;
@@ -6608,7 +6644,7 @@
 show_timestamps_pref_cb(const char *name, PurplePrefType type,
 						gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	PidginWindow *win;
@@ -6636,7 +6672,7 @@
 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
 								gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	PidginWindow *win;
@@ -6666,7 +6702,7 @@
 animate_buddy_icons_pref_cb(const char *name, PurplePrefType type,
 							gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	PidginWindow *win;
@@ -6693,7 +6729,7 @@
 show_buddy_icons_pref_cb(const char *name, PurplePrefType type,
 						 gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		PurpleConversation *conv = l->data;
@@ -6819,7 +6855,7 @@
 static void
 account_signed_off_cb(PurpleConnection *gc, gpointer event)
 {
-	const GList *iter;
+	GList *iter;
 
 	for (iter = purple_get_conversations(); iter; iter = iter->next)
 	{
@@ -8413,7 +8449,7 @@
 	gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, !tabs_side && !angle, TRUE, GTK_PACK_START);
 
 	/* show the widgets */
-	gtk_widget_show(gtkconv->icon);
+/* XXX	gtk_widget_show(gtkconv->icon); */
 	gtk_widget_show(gtkconv->tab_label);
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs"))
 		gtk_widget_show(gtkconv->close);
--- a/pidgin/gtkconv.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkconv.h	Tue Jun 19 17:28:41 2007 +0000
@@ -158,6 +158,10 @@
 	} u;
 
 	time_t newday;
+	GtkWidget *infopane_hbox;
+	GtkWidget *infopane;
+	GtkTreeModel *infopane_model;
+	GtkTreeIter infopane_iter;
 };
 
 /*@}*/
--- a/pidgin/gtkdocklet.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkdocklet.c	Tue Jun 19 17:28:41 2007 +0000
@@ -109,8 +109,7 @@
 static gboolean
 docklet_update_status()
 {
-	GList *convs;
-	const GList *l;
+	GList *convs, *l;
 	int count;
 	PurpleSavedStatus *saved_status;
 	PurpleStatusPrimitive newstatus = PURPLE_STATUS_OFFLINE;
@@ -214,7 +213,8 @@
 static gboolean
 online_account_supports_chat()
 {
-	const GList *c = purple_connections_get_all();
+	GList *c = NULL;
+	c = purple_connections_get_all();
 
 	while(c != NULL) {
 		PurpleConnection *gc = c->data;
--- a/pidgin/gtkft.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkft.c	Tue Jun 19 17:28:41 2007 +0000
@@ -130,7 +130,7 @@
 	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);
 
 	if (kbsec != NULL) {
-		*kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
+		*kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps);
 	}
 
 	if (time_elapsed != NULL)
--- a/pidgin/gtkimhtml.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkimhtml.c	Tue Jun 19 17:28:41 2007 +0000
@@ -5036,10 +5036,24 @@
 
 void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags)
 {
+	GtkIMHtmlButtons buttons;
+
 	if (flags & PURPLE_CONNECTION_HTML) {
 		char color[8];
 		GdkColor fg_color, bg_color;
 
+		buttons = GTK_IMHTML_ALL;
+
+		if (flags & PURPLE_CONNECTION_NO_BGCOLOR)
+			buttons &= ~GTK_IMHTML_BACKCOLOR;
+		if (flags & PURPLE_CONNECTION_NO_FONTSIZE)
+		{
+			buttons &= ~GTK_IMHTML_GROW;
+			buttons &= ~GTK_IMHTML_SHRINK;
+		}
+		if (flags & PURPLE_CONNECTION_NO_URLDESC)
+			buttons &= ~GTK_IMHTML_LINKDESC;
+
 		gtk_imhtml_set_format_functions(imhtml, GTK_IMHTML_ALL);
 		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != imhtml->edit.bold)
 			gtk_imhtml_toggle_bold(imhtml);
@@ -5094,9 +5108,14 @@
 		else
 			gtk_imhtml_set_whole_buffer_formatting_only(imhtml, FALSE);
 	} else {
+		buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE;
 		imhtml_clear_formatting(imhtml);
-		gtk_imhtml_set_format_functions(imhtml, 0);
 	}
+
+	if (flags & PURPLE_CONNECTION_NO_IMAGES)
+		buttons &= ~GTK_IMHTML_IMAGE;
+
+	gtk_imhtml_set_format_functions(imhtml, buttons);
 }
 
 
--- a/pidgin/gtkimhtmltoolbar.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Tue Jun 19 17:28:41 2007 +0000
@@ -865,41 +865,21 @@
                     gboolean          *push_in,
                     gpointer          data)
 {
+	GtkWidget *widget = GTK_WIDGET(data);
 	GtkRequisition menu_req;
-	GtkTextDirection direction;
-	GdkRectangle monitor;
-	gint monitor_num;
-	GdkScreen *screen;
-	GtkWidget *widget = GTK_WIDGET(data);
-
-	gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
-
-	direction = gtk_widget_get_direction (widget);
-
-	screen = gtk_widget_get_screen (GTK_WIDGET (menu));
-	monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
-	if (monitor_num < 0)
-		monitor_num = 0;
-	gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+	gint ythickness = widget->style->ythickness;
+	int savy;
 
-	gdk_window_get_origin (widget->window, x, y);
+	gtk_widget_size_request(GTK_WIDGET (menu), &menu_req);
+	gdk_window_get_origin(widget->window, x, y);
 	*x += widget->allocation.x;
-	*y += widget->allocation.y;
-
-	if (direction == GTK_TEXT_DIR_LTR)
-		*x += MAX (widget->allocation.width - menu_req.width, 0);
-	else if (menu_req.width > widget->allocation.width)
-		*x -= menu_req.width - widget->allocation.width;
+	*y += widget->allocation.y + widget->allocation.height;
+	savy = *y;
 
-	if ((*y + widget->allocation.height + menu_req.height) <= monitor.y + monitor.height)
-		*y += widget->allocation.height;
-	else if ((*y - menu_req.height) >= monitor.y)
-		*y -= menu_req.height;
-	else if (monitor.y + monitor.height - (*y + widget->allocation.height) > *y)
-		*y += widget->allocation.height;
-	else
-		*y -= menu_req.height;
-	*push_in = FALSE;
+	pidgin_menu_position_func_helper(menu, x, y, push_in, data);
+
+	if (savy > *y + ythickness + 1)
+		*y -= widget->allocation.height;
 }
 
 static void pidgin_menu_clicked(GtkWidget *button, GtkMenu *menu)
@@ -1055,6 +1035,7 @@
 	GtkWidget *font_button;
 	GtkWidget *font_menu;
 	GtkWidget *insert_menu;
+	GtkWidget *menuitem;
 	GtkWidget *button;
 	GtkWidget *sep;
 	int i;
@@ -1108,7 +1089,7 @@
 	
 	for (i = 0; buttons[i].label; i++) {
 		GtkWidget *old = *buttons[i].button;
-		GtkWidget *menuitem = gtk_check_menu_item_new_with_mnemonic(buttons[i].label);
+		menuitem = gtk_check_menu_item_new_with_mnemonic(buttons[i].label);
 		g_signal_connect_swapped(G_OBJECT(menuitem), "activate",
 				G_CALLBACK(gtk_button_clicked), old);
 		g_signal_connect_after(G_OBJECT(old), "toggled",
@@ -1160,17 +1141,23 @@
 
 	insert_menu = gtk_menu_new();
 
-	button = gtk_menu_item_new_with_mnemonic(_("_Smiley"));
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->smiley);
-	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), button);
+	menuitem = gtk_menu_item_new_with_mnemonic(_("_Smiley"));
+	g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->smiley);
+	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem);
+	g_signal_connect(G_OBJECT(toolbar->smiley), "notify::sensitive",
+			G_CALLBACK(button_sensitiveness_changed), menuitem);
 
-	button = gtk_menu_item_new_with_mnemonic(_("_Image"));
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->image);
-	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), button);
+	menuitem = gtk_menu_item_new_with_mnemonic(_("_Image"));
+	g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->image);
+	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem);
+	g_signal_connect(G_OBJECT(toolbar->image), "notify::sensitive",
+			G_CALLBACK(button_sensitiveness_changed), menuitem);
 
-	button = gtk_menu_item_new_with_mnemonic(_("_Link"));
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gtk_button_clicked), toolbar->link);
-	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), button);
+	menuitem = gtk_menu_item_new_with_mnemonic(_("_Link"));
+	g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->link);
+	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem);
+	g_signal_connect(G_OBJECT(toolbar->link), "notify::sensitive",
+			G_CALLBACK(button_sensitiveness_changed), menuitem);
 
 	g_signal_connect(G_OBJECT(insert_button), "clicked", G_CALLBACK(pidgin_menu_clicked), insert_menu);
 	g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button);
--- a/pidgin/gtklog.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtklog.c	Tue Jun 19 17:28:41 2007 +0000
@@ -757,7 +757,7 @@
 
 void pidgin_syslog_show()
 {
-	const GList *accounts;
+	GList *accounts = NULL;
 	GList *logs = NULL;
 
 	if (syslog_viewer != NULL) {
--- a/pidgin/gtkmain.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkmain.c	Tue Jun 19 17:28:41 2007 +0000
@@ -125,7 +125,7 @@
 		}
 		g_strfreev(names);
 	} else { /* no name given, use the first account */
-		const GList *accounts;
+		GList *accounts;
 
 		accounts = purple_accounts_get_all();
 		if (accounts != NULL)
@@ -372,6 +372,7 @@
 		       "  -c, --config=DIR    use DIR for config files\n"
 		       "  -d, --debug         print debugging messages to stdout\n"
 		       "  -h, --help          display this help and exit\n"
+		       "  -m, --multiple      do not ensure single instance\n"
 		       "  -n, --nologin       don't automatically login\n"
 		       "  -l, --login[=NAME]  automatically login (optional argument NAME specifies\n"
 		       "                      account(s) to use, separated by commas)\n"
@@ -431,11 +432,12 @@
 	gboolean opt_login = FALSE;
 	gboolean opt_nologin = FALSE;
 	gboolean opt_version = FALSE;
+	gboolean opt_si = TRUE;     /* Check for single instance? */
 	char *opt_config_dir_arg = NULL;
 	char *opt_login_arg = NULL;
 	char *opt_session_arg = NULL;
 	char *search_path;
-	const GList *accounts;
+	GList *accounts;
 #ifdef HAVE_SIGNAL_H
 	int sig_indx;	/* for setting up signal catching */
 	sigset_t sigset;
@@ -457,6 +459,7 @@
 		{"debug",    no_argument,       NULL, 'd'},
 		{"help",     no_argument,       NULL, 'h'},
 		{"login",    optional_argument, NULL, 'l'},
+		{"multiple", no_argument,       NULL, 'm'},
 		{"nologin",  no_argument,       NULL, 'n'},
 		{"session",  required_argument, NULL, 's'},
 		{"version",  no_argument,       NULL, 'v'},
@@ -471,7 +474,7 @@
 
 	/* This is the first Glib function call. Make sure to initialize GThread bfeore then */
 	g_thread_init(NULL);
-	
+
 #ifdef ENABLE_NLS
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	bind_textdomain_codeset(PACKAGE, "UTF-8");
@@ -570,7 +573,7 @@
 	opterr = 1;
 	while ((opt = getopt_long(argc, argv,
 #ifndef _WIN32
-				  "c:dhnl::s:v",
+				  "c:dhmnl::s:v",
 #else
 				  "c:dhnl::v",
 #endif
@@ -602,6 +605,9 @@
 		case 'v':	/* version */
 			opt_version = TRUE;
 			break;
+		case 'm':   /* do not ensure single instance. */
+			opt_si = FALSE;
+			break;
 		case '?':	/* show terse help */
 		default:
 			show_usage(argv[0], TRUE);
@@ -728,7 +734,7 @@
 		abort();
 	}
 
-	if (!purple_core_ensure_single_instance()) {
+	if (opt_si && !purple_core_ensure_single_instance()) {
 		purple_core_quit();
 #ifdef HAVE_SIGNAL_H
 		g_free(segfault_message);
@@ -849,6 +855,7 @@
 	winpidgin_post_init();
 #endif
 
+	g_set_application_name(_("Pidgin"));
 	gtk_main();
 
 #ifdef HAVE_SIGNAL_H
--- a/pidgin/gtkpounce.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkpounce.c	Tue Jun 19 17:28:41 2007 +0000
@@ -211,12 +211,12 @@
 static void
 populate_pounces_list(PouncesManager *dialog)
 {
-	const GList *pounces;
+	GList *pounces;
 
 	gtk_list_store_clear(dialog->model);
 
-	for (pounces = purple_pounces_get_all(); pounces != NULL;
-			pounces = g_list_next(pounces))
+	for (pounces = purple_pounces_get_all_for_ui(PIDGIN_UI); pounces != NULL;
+			pounces = g_list_delete_link(pounces, pounces))
 	{
 		add_pounce_to_treeview(dialog->model, pounces->data);
 	}
@@ -496,7 +496,7 @@
 	}
 	else
 	{
-		const GList *connections = purple_connections_get_all();
+		GList *connections = purple_connections_get_all();
 		PurpleConnection *gc;
 
 		if (connections != NULL)
--- a/pidgin/gtkrequest.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkrequest.c	Tue Jun 19 17:28:41 2007 +0000
@@ -974,7 +974,7 @@
 	GtkTreeSelection *sel;
 	GtkTreeViewColumn *column;
 	GtkTreeIter iter;
-	const GList *l;
+	GList *l;
 
 	/* Create the scrolled window */
 	sw = gtk_scrolled_window_new(NULL, NULL);
--- a/pidgin/gtkroomlist.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkroomlist.c	Tue Jun 19 17:28:41 2007 +0000
@@ -343,7 +343,7 @@
 gboolean
 pidgin_roomlist_is_showable()
 {
-	const GList *c;
+	GList *c;
 	PurpleConnection *gc;
 
 	for (c = purple_connections_get_all(); c != NULL; c = c->next) {
--- a/pidgin/gtksavedstatuses.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Tue Jun 19 17:28:41 2007 +0000
@@ -285,9 +285,11 @@
 
 	for (l = sel_titles; l != NULL; l = l->next) {
 		title = l->data;
-		if (status_window_find_savedstatus(&iter, title))
-			gtk_list_store_remove(status_window->model, &iter);
-		purple_savedstatus_delete(title);
+		if (purple_savedstatus_find(title) != purple_savedstatus_get_current()) {
+			if (status_window_find_savedstatus(&iter, title))
+				gtk_list_store_remove(status_window->model, &iter);
+			purple_savedstatus_delete(title);
+		}
 		g_free(title);
 	}
 	g_list_free(sel_titles);
@@ -349,17 +351,39 @@
 status_selected_cb(GtkTreeSelection *sel, gpointer user_data)
 {
 	StatusWindow *dialog = user_data;
-	int num_selected = 0;
+	GList *sel_paths, *tmp;
+	gboolean can_use = TRUE, can_delete = TRUE;
+	int num_selected;
+	GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
 
 #if GTK_CHECK_VERSION(2,2,0)
-	num_selected = gtk_tree_selection_count_selected_rows(sel);
+	sel_paths = gtk_tree_selection_get_selected_rows(sel, NULL);
 #else
-	gtk_tree_selection_selected_foreach(sel, count_selected_helper, &num_selected);
+	gtk_tree_selection_selected_foreach(sel, list_selected_helper, &sel_paths);
 #endif
 
-	gtk_widget_set_sensitive(dialog->use_button, (num_selected == 1));
+	for (tmp = sel_paths, num_selected = 0; tmp; tmp = sel_paths->next, num_selected++) {
+		GtkTreeIter iter;
+		char *title;
+
+		if (gtk_tree_model_get_iter(model, &iter, tmp->data)) {
+			gtk_tree_model_get(model, &iter,
+					STATUS_WINDOW_COLUMN_TITLE, &title, -1);
+			if (purple_savedstatus_find(title) == purple_savedstatus_get_current()) {
+				can_use = can_delete = FALSE;
+			}
+
+			g_free(title);
+		}
+
+		gtk_tree_path_free(tmp->data);
+	}
+
+	gtk_widget_set_sensitive(dialog->use_button, (num_selected == 1) && can_use);
 	gtk_widget_set_sensitive(dialog->modify_button, (num_selected > 0));
-	gtk_widget_set_sensitive(dialog->delete_button, (num_selected > 0));
+	gtk_widget_set_sensitive(dialog->delete_button, can_delete);
+
+    g_list_free(sel_paths);
 }
 
 static void
@@ -389,7 +413,7 @@
 static void
 populate_saved_status_list(StatusWindow *dialog)
 {
-	const GList *saved_statuses;
+	GList *saved_statuses;
 
 	gtk_list_store_clear(dialog->model);
 
@@ -421,6 +445,12 @@
 	status_window_modify_cb(NULL, dialog);
 }
 
+static void
+saved_status_updated_cb(PurpleSavedStatus *status, StatusWindow *sw)
+{
+	populate_saved_status_list(sw);
+}
+
 static GtkWidget *
 create_saved_status_list(StatusWindow *dialog)
 {
@@ -529,6 +559,13 @@
 	return FALSE;
 }
 
+static void
+current_status_changed(PurpleSavedStatus *old, PurpleSavedStatus *new_status,
+		StatusWindow *dialog)
+{
+	status_selected_cb(gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)), dialog);
+}
+
 void
 pidgin_status_window_show(void)
 {
@@ -615,6 +652,20 @@
 	g_signal_connect(G_OBJECT(button), "clicked",
 					 G_CALLBACK(status_window_close_cb), dialog);
 
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-changed", dialog,
+			PURPLE_CALLBACK(current_status_changed), dialog);
+
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-added", dialog,
+			PURPLE_CALLBACK(saved_status_updated_cb), dialog);
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-deleted", dialog,
+			PURPLE_CALLBACK(saved_status_updated_cb), dialog);
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", dialog,
+			PURPLE_CALLBACK(saved_status_updated_cb), dialog);
+
 	gtk_widget_show_all(win);
 }
 
@@ -804,8 +855,10 @@
 	gtk_widget_destroy(dialog->window);
 	g_free(dialog->original_title);
 
+/*
 	if (status_window != NULL)
 	  add_status_to_saved_status_list(status_window->model, saved_status);
+*/
 
 	/* If they clicked on "Save & Use" or "Use," then activate the status */
 	if (button != dialog->save_button)
@@ -1012,7 +1065,7 @@
 static void
 status_editor_populate_list(StatusEditor *dialog, PurpleSavedStatus *saved_status)
 {
-	const GList *iter;
+	GList *iter;
 	PurpleSavedStatusSub *substatus;
 
 	gtk_list_store_clear(dialog->model);
@@ -1393,7 +1446,7 @@
 	GtkTreeIter iter;
 	GtkCellRenderer *rend;
 	const char *status_id = NULL;
-	const GList *list;
+	GList *list;
 	gboolean select = FALSE;
 
 	g_return_if_fail(status_editor != NULL);
--- a/pidgin/gtkstatusbox.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Tue Jun 19 17:28:41 2007 +0000
@@ -47,6 +47,7 @@
 #include "internal.h"
 #include "imgstore.h"
 #include "network.h"
+#include "request.h"
 #include "savedstatuses.h"
 #include "status.h"
 #include "debug.h"
@@ -191,7 +192,7 @@
 static void
 update_to_reflect_account_status(PidginStatusBox *status_box, PurpleAccount *account, PurpleStatus *newstatus)
 {
-	const GList *l;
+	GList *l;
 	int status_no = -1;
 	const PurpleStatusType *statustype = NULL;
 	const char *message;
@@ -732,7 +733,7 @@
 static PurpleStatusType *
 find_status_type_by_index(const PurpleAccount *account, gint active)
 {
-	const GList *l = purple_account_get_status_types(account);
+	GList *l = purple_account_get_status_types(account);
 	gint i;
 
 	for (i = 0; l; l = l->next) {
@@ -941,7 +942,7 @@
 {
 	PurpleAccount *acct = NULL, *acct2;
 	GList *tmp, *tmp2, *active_accts = purple_accounts_get_all_active();
-	const GList *s, *s1, *s2;
+	GList *s, *s1, *s2;
 
 	for (tmp = active_accts; tmp; tmp = tmp->next) {
 		acct = tmp->data;
@@ -989,7 +990,7 @@
 add_account_statuses(PidginStatusBox *status_box, PurpleAccount *account)
 {
 	/* Per-account */
-	const GList *l;
+	GList *l;
 	GdkPixbuf *pixbuf;
 
 	for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
@@ -1223,6 +1224,12 @@
 }
 
 static void
+saved_status_updated_cb(PurpleSavedStatus *status, PidginStatusBox *status_box)
+{
+	pidgin_status_box_regenerate(status_box);
+}
+
+static void
 spellcheck_prefs_cb(const char *name, PurplePrefType type,
 					gconstpointer value, gpointer data)
 {
@@ -1434,7 +1441,7 @@
 			}
 		}
 	} else {
-		const GList *accounts;
+		GList *accounts;
 		for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
 			PurpleAccount *account = accounts->data;
 			PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(account));
@@ -1514,6 +1521,56 @@
 	pidgin_status_box_changed(status_box);
 }
 
+static void tree_view_delete_current_selection_cb(gpointer data)
+{
+	PurpleSavedStatus *saved;
+
+	saved = purple_savedstatus_find_by_creation_time(GPOINTER_TO_INT(data));
+	g_return_if_fail(saved != NULL);
+
+	if (purple_savedstatus_get_current() != saved)
+		purple_savedstatus_delete_by_status(saved);
+}
+
+static void
+tree_view_delete_current_selection(PidginStatusBox *status_box, GtkTreePath *path)
+{
+	GtkTreeIter iter;
+	gpointer data;
+	PurpleSavedStatus *saved;
+	gchar *msg;
+
+	if (status_box->active_row) {
+		/* don't delete active status */
+		if (gtk_tree_path_compare(path, gtk_tree_row_reference_get_path(status_box->active_row)) == 0)
+			return;
+	}
+
+	if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(status_box->dropdown_store), &iter, path))
+		return;
+
+	gtk_tree_model_get(GTK_TREE_MODEL(status_box->dropdown_store), &iter,
+			   DATA_COLUMN, &data,
+			   -1);
+
+	saved = purple_savedstatus_find_by_creation_time(GPOINTER_TO_INT(data));
+	g_return_if_fail(saved != NULL);
+	if (saved == purple_savedstatus_get_current())
+		return;
+
+	msg = g_strdup_printf(_("Are you sure you want to delete %s?"), purple_savedstatus_get_title(saved));
+
+	purple_request_action(pidgin_status_get_handle(), NULL, msg, NULL, 0,
+		NULL, NULL, NULL,
+		data, 2,
+		_("Delete"), tree_view_delete_current_selection_cb,
+		_("Cancel"), NULL);
+
+	g_free(msg);
+
+	pidgin_status_box_popdown(status_box);
+}
+
 static gboolean
 treeview_button_release_cb(GtkWidget *widget, GdkEventButton *event, PidginStatusBox *status_box)
 {
@@ -1561,18 +1618,23 @@
 		if (event->keyval == GDK_Escape) {
 			pidgin_status_box_popdown(box);
 			return TRUE;
-		} else if (event->keyval == GDK_Return) {
+		} else {
 			GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(box->tree_view));
 			GtkTreeIter iter;
 			GtkTreePath *path;
 
 			if (gtk_tree_selection_get_selected(sel, NULL, &iter)) {
 				path = gtk_tree_model_get_path(GTK_TREE_MODEL(box->dropdown_store), &iter);
-				treeview_activate_current_selection(box, path);
+				if (event->keyval == GDK_Return) {
+					treeview_activate_current_selection(box, path);
+				} else if (event->keyval == GDK_Delete) {
+					tree_view_delete_current_selection(box, path);
+				}
+
 				gtk_tree_path_free (path);
 				return TRUE;
 			}
-		}
+		} 
 	}
 	return FALSE;
 }
@@ -1742,6 +1804,15 @@
 						status_box,
 						PURPLE_CALLBACK(current_savedstatus_changed_cb),
 						status_box);
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-added", status_box,
+			PURPLE_CALLBACK(saved_status_updated_cb), status_box);
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-deleted", status_box,
+			PURPLE_CALLBACK(saved_status_updated_cb), status_box);
+	purple_signal_connect(purple_savedstatuses_get_handle(),
+			"savedstatus-modified", status_box,
+			PURPLE_CALLBACK(saved_status_updated_cb), status_box);
 	purple_signal_connect(purple_accounts_get_handle(), "account-enabled", status_box,
 						PURPLE_CALLBACK(account_enabled_cb),
 						status_box);
@@ -2223,7 +2294,7 @@
 		{
 			/* Manually find the appropriate transient acct */
 			if (status_box->token_status_account) {
-				const GList *iter = purple_savedstatuses_get_all();
+				GList *iter = purple_savedstatuses_get_all();
 				GList *tmp, *active_accts = purple_accounts_get_all_active();
 
 				for (; iter != NULL; iter = iter->next) {
--- a/pidgin/gtkthemes.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkthemes.c	Tue Jun 19 17:28:41 2007 +0000
@@ -237,7 +237,7 @@
 	}
 
 	if (load) {
-		const GList *cnv;
+		GList *cnv;
 
 		if (current_smiley_theme)
 			pidgin_themes_destroy_smiley_theme(current_smiley_theme);
--- a/pidgin/gtkutils.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkutils.c	Tue Jun 19 17:28:41 2007 +0000
@@ -525,7 +525,7 @@
 {
 	PurplePluginProtocolInfo *prpl_info;
 	const char *protoname = NULL;
-	char buf[MAXPATHLEN];
+	char *tmp;
 	char *filename = NULL;
 	GdkPixbuf *pixbuf;
 
@@ -541,12 +541,14 @@
 	 * Status icons will be themeable too, and then it will look up
 	 * protoname from the theme
 	 */
-	g_snprintf(buf, sizeof(buf), "%s.png", protoname);
+	tmp = g_strconcat(protoname, ".png", NULL);
 
 	filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
 				    size == PIDGIN_PRPL_ICON_SMALL ? "16" :
 				    size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48",
-				    buf, NULL);
+				    tmp, NULL);
+	g_free(tmp);
+
 	pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
 	g_free(filename);
 
@@ -687,8 +689,8 @@
 	AopMenu *aop_menu = NULL;
 	PurpleAccount *account;
 	GdkPixbuf *pixbuf = NULL;
-	const GList *list;
-	const GList *p;
+	GList *list;
+	GList *p;
 	GtkSizeGroup *sg;
 	int i;
 	char buf[256];
@@ -995,9 +997,9 @@
 		/* Check for a compatible account. */
 		if (ret_account != NULL)
 		{
-			const GList *list;
+			GList *list;
 			PurpleAccount *account = NULL;
-			const GList *l;
+			GList *l;
 			const char *protoname;
 
 			if (all_accounts)
@@ -1139,14 +1141,14 @@
 	g_object_unref (relation);
 }
 
-#if GTK_CHECK_VERSION(2,2,0)
-static void
-pidgin_menu_position_func(GtkMenu *menu,
+void
+pidgin_menu_position_func_helper(GtkMenu *menu,
 							gint *x,
 							gint *y,
 							gboolean *push_in,
 							gpointer data)
 {
+#if GTK_CHECK_VERSION(2,2,0)
 	GtkWidget *widget;
 	GtkRequisition requisition;
 	GdkScreen *screen;
@@ -1287,9 +1289,9 @@
 	{
 		*y = monitor.y;
 	}
+#endif
 }
 
-#endif
 
 void
 pidgin_treeview_popup_menu_position_func(GtkMenu *menu,
@@ -1311,9 +1313,7 @@
 
 	*x += rect.x+rect.width;
 	*y += rect.y+rect.height+ythickness;
-#if GTK_CHECK_VERSION(2,2,0)
-	pidgin_menu_position_func (menu, x, y, push_in, data);
-#endif
+	pidgin_menu_position_func_helper(menu, x, y, push_in, data);
 }
 
 enum {
@@ -3090,3 +3090,4 @@
 	return path;
 }
 #endif
+
--- a/pidgin/gtkutils.h	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/gtkutils.h	Tue Jun 19 17:28:41 2007 +0000
@@ -359,6 +359,21 @@
 void pidgin_set_accessible_label(GtkWidget *w, GtkWidget *l);
 
 /**
+ * A helper function for GtkMenuPositionFuncs. This ensures the menu will
+ * be kept on screen if possible.
+ *
+ * @param menu The menu we are positioning.
+ * @param x Address of the gint representing the horizontal position
+ *        where the menu shall be drawn. This is an output parameter.
+ * @param y Address of the gint representing the vertical position
+ *        where the menu shall be drawn. This is an output parameter.
+ * @param push_in This is an output parameter?
+ * @param user_data Not used by this particular position function.
+ */
+void pidgin_menu_position_func_helper(GtkMenu *menu, gint *x, gint *y,
+										gboolean *push_in, gpointer data);
+
+/**
  * A valid GtkMenuPositionFunc.  This is used to determine where 
  * to draw context menu's when the menu is activated with the 
  * keyboard (shift+F10).  If the menu is activated with the mouse, 
--- a/pidgin/pidginstock.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/pidginstock.c	Tue Jun 19 17:28:41 2007 +0000
@@ -105,7 +105,7 @@
 	{ PIDGIN_STOCK_STATUS_AWAY, 	   "status", "away.png",	TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AWAY_I },
 	{ PIDGIN_STOCK_STATUS_BUSY, 	"status", "busy.png", 		TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_BUSY_I },
 	{ PIDGIN_STOCK_STATUS_CHAT, 	"status", "chat.png",		TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
-	{ PIDGIN_STOCK_STATUS_INVISIBLE,"status", "invisible.png",	TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
+	{ PIDGIN_STOCK_STATUS_INVISIBLE,"status", "invisible.png",	TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
 	{ PIDGIN_STOCK_STATUS_XA, 	"status", "extended-away.png",	TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, PIDGIN_STOCK_STATUS_XA_I },
 	{ PIDGIN_STOCK_STATUS_LOGIN, 	"status", "log-in.png",		TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
 	{ PIDGIN_STOCK_STATUS_LOGOUT, 	"status", "log-out.png",	TRUE, TRUE, TRUE, TRUE, FALSE, FALSE , NULL },
--- a/pidgin/plugins/gestures/gestures.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/gestures/gestures.c	Tue Jun 19 17:28:41 2007 +0000
@@ -176,7 +176,7 @@
 plugin_load(PurplePlugin *plugin)
 {
 	PurpleConversation *conv;
-	const GList *l;
+	GList *l;
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		conv = (PurpleConversation *)l->data;
@@ -199,7 +199,7 @@
 {
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
-	const GList *l;
+	GList *l;
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		conv = (PurpleConversation *)l->data;
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/gevolution/add_buddy_dialog.c	Tue Jun 19 17:28:41 2007 +0000
@@ -162,7 +162,7 @@
 		GList *list, const char *id)
 {
 	PurpleAccount *account = NULL;
-	const GList *l;
+	GList *l;
 	GtkTreeIter iter;
 	GdkPixbuf *pixbuf;
 
--- a/pidgin/plugins/gevolution/gevolution.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/gevolution/gevolution.c	Tue Jun 19 17:28:41 2007 +0000
@@ -69,8 +69,7 @@
 						const char *prpl_id, EContactField field)
 {
 	GList *ims = e_contact_get(contact, field);
-	const GList *l;
-	const GList *l2;
+	GList *l, *l2;
 
 	if (ims == NULL)
 		return;
@@ -119,9 +118,9 @@
 }
 
 static void
-contacts_changed_cb(EBookView *book_view, const GList *contacts)
+contacts_changed_cb(EBookView *book_view, GList *contacts)
 {
-	const GList *l;
+	GList *l;
 
 	if (purple_connections_get_all() == NULL)
 		return;
@@ -401,7 +400,7 @@
 	GtkCellRenderer *renderer;
 	GdkPixbuf *pixbuf;
 	GtkListStore *model;
-	const GList *l;
+	GList *l;
 
 	/* Outside container */
 	ret = gtk_vbox_new(FALSE, 18);
--- a/pidgin/plugins/notify.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/notify.c	Tue Jun 19 17:28:41 2007 +0000
@@ -624,7 +624,7 @@
 static void
 apply_method()
 {
-	const GList *convs;
+	GList *convs;
 	PidginWindow *purplewin = NULL;
 
 	for (convs = purple_get_conversations(); convs != NULL;
@@ -644,7 +644,7 @@
 static void
 apply_notify()
 {
-	const GList *convs = purple_get_conversations();
+	GList *convs = purple_get_conversations();
 
 	while (convs) {
 		PurpleConversation *conv = (PurpleConversation *)convs->data;
@@ -818,7 +818,7 @@
 static gboolean
 plugin_load(PurplePlugin *plugin)
 {
-	const GList *convs = purple_get_conversations();
+	GList *convs = purple_get_conversations();
 	void *conv_handle = purple_conversations_get_handle();
 	void *gtk_conv_handle = pidgin_conversations_get_handle();
 
@@ -860,7 +860,7 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
-	const GList *convs = purple_get_conversations();
+	GList *convs = purple_get_conversations();
 
 	while (convs) {
 		PurpleConversation *conv = (PurpleConversation *)convs->data;
--- a/pidgin/plugins/pidginrc.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/pidginrc.c	Tue Jun 19 17:28:41 2007 +0000
@@ -27,49 +27,49 @@
 
 static guint pref_callback;
 
-static const char *color_prefs[] = {
+static const gchar *color_prefs[] = {
 	"/plugins/gtk/purplerc/color/GtkWidget::cursor-color",
 	"/plugins/gtk/purplerc/color/GtkWidget::secondary-cursor-color",
 	"/plugins/gtk/purplerc/color/GtkIMHtml::hyperlink-color"
 };
-static const char *color_prefs_set[] = {
+static const gchar *color_prefs_set[] = {
 	"/plugins/gtk/purplerc/set/color/GtkWidget::cursor-color",
 	"/plugins/gtk/purplerc/set/color/GtkWidget::secondary-cursor-color",
 	"/plugins/gtk/purplerc/set/color/GtkIMHtml::hyperlink-color"
 };
-static const char *color_names[] = {
+static const gchar *color_names[] = {
 	N_("Cursor Color"),
 	N_("Secondary Cursor Color"),
 	N_("Hyperlink Color")
 };
 static GtkWidget *color_widgets[G_N_ELEMENTS(color_prefs)];
 
-static const char *widget_size_prefs[] = {
+static const gchar *widget_size_prefs[] = {
 	"/plugins/gtk/purplerc/size/GtkTreeView::horizontal_separator"
 };
-static const char *widget_size_prefs_set[] = {
+static const gchar *widget_size_prefs_set[] = {
 	"/plugins/gtk/purplerc/set/size/GtkTreeView::horizontal_separator"
 };
-static const char *widget_size_names[] = {
+static const gchar *widget_size_names[] = {
 	N_("GtkTreeView Horizontal Separation")
 };
 static GtkWidget *widget_size_widgets[G_N_ELEMENTS(widget_size_prefs)];
 
-static const char *font_prefs[] = {
+static const gchar *font_prefs[] = {
 	"/plugins/gtk/purplerc/font/*pidgin_conv_entry",
 	"/plugins/gtk/purplerc/font/*pidgin_conv_imhtml",
 	"/plugins/gtk/purplerc/font/*pidgin_log_imhtml",
 	"/plugins/gtk/purplerc/font/*pidgin_request_imhtml",
 	"/plugins/gtk/purplerc/font/*pidgin_notify_imhtml",
 };
-static const char *font_prefs_set[] = {
+static const gchar *font_prefs_set[] = {
 	"/plugins/gtk/purplerc/set/font/*pidgin_conv_entry",
 	"/plugins/gtk/purplerc/set/font/*pidgin_conv_imhtml",
 	"/plugins/gtk/purplerc/set/font/*pidgin_log_imhtml",
 	"/plugins/gtk/purplerc/set/font/*pidgin_request_imhtml",
 	"/plugins/gtk/purplerc/set/font/*pidgin_notify_imhtml",
 };
-static const char *font_names[] = {
+static const gchar *font_names[] = {
 	N_("Conversation Entry"),
 	N_("Conversation History"),
 	N_("Log Viewer"),
@@ -79,53 +79,56 @@
 static GtkWidget *font_widgets[G_N_ELEMENTS(font_prefs)];
 
 /*
-static const char *widget_bool_prefs[] = {
+static const gchar *widget_bool_prefs[] = {
 };
-static const char *widget_bool_prefs_set[] = {
+static const gchar *widget_bool_prefs_set[] = {
 };
-static const char *widget_bool_names[] = {
+static const gchar *widget_bool_names[] = {
 };
 static GtkWidget *widget_bool_widgets[G_N_ELEMENTS(widget_bool_prefs)];
 */
 
-static void
-purplerc_make_changes()
+static GString *
+make_gtkrc_string()
 {
-	int i;
-	char *prefbase = NULL;
-#if GTK_CHECK_VERSION(2,4,0)
-	GtkSettings *setting = NULL;
-#endif
+	gint i;
+	gchar *prefbase = NULL;
 	GString *style_string = g_string_new("");
 
 	if (purple_prefs_get_bool("/plugins/gtk/purplerc/set/gtk-font-name")) {
-		const char *pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-font-name");
+		const gchar *pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-font-name");
 
-		if (pref != NULL && strcmp(pref, ""))
-			g_string_append_printf(style_string, "gtk-font-name = \"%s\"\n", pref);
+		if (pref != NULL && strcmp(pref, "")) {
+			g_string_append_printf(style_string,
+			                       "gtk-font-name = \"%s\"\n",
+			                       pref);
+		}
 	}
 
 	if (purple_prefs_get_bool("/plugins/gtk/purplerc/set/gtk-key-theme-name")) {
-		const char *pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-key-theme-name");
+		const gchar *pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-key-theme-name");
 
-		if (pref != NULL && strcmp(pref, ""))
-			g_string_append_printf(style_string, "gtk-key-theme-name = \"%s\"\n", pref);
+		if (pref != NULL && strcmp(pref, "")) {
+			g_string_append_printf(style_string,
+			                       "gtk-key-theme-name = \"%s\"\n",
+			                       pref);
+		}
 	}
 
-	g_string_append(style_string, "style \"purplerc_style\" {\n");
+	g_string_append(style_string, "style \"purplerc_style\"\n{");
 
 	for (i = 0; i < G_N_ELEMENTS(color_prefs); i++) {
 		if (purple_prefs_get_bool(color_prefs_set[i])) {
-			const char *pref;
-
-			prefbase = g_path_get_basename(color_prefs[i]);
-			pref = purple_prefs_get_string(color_prefs[i]);
+			const gchar *pref;
 
-			if (pref != NULL && strcmp(pref, ""))
-			    g_string_append_printf(style_string,
-			                           "%s = \"%s\"\n",
-			                           prefbase, pref);
-			g_free(prefbase);
+			pref = purple_prefs_get_string(color_prefs[i]);
+			if (pref != NULL && strcmp(pref, "")) {
+				prefbase = g_path_get_basename(color_prefs[i]);
+				g_string_append_printf(style_string,
+				                       "\n\t%s = \"%s\"",
+				                       prefbase, pref);
+				g_free(prefbase);
+			}
 		}
 	}
 
@@ -133,7 +136,7 @@
 		if (purple_prefs_get_bool(widget_size_prefs_set[i])) {
 			prefbase = g_path_get_basename(widget_size_prefs[i]);
 			g_string_append_printf(style_string,
-			                       "%s = %d\n", prefbase,
+			                       "\n\t%s = %d", prefbase,
 			                       purple_prefs_get_int(widget_size_prefs[i]));
 			g_free(prefbase);
 		}
@@ -144,37 +147,47 @@
 		if (purple_prefs_get_bool(widget_bool_prefs_set[i])) {
 			prefbase = g_path_get_basename(widget_bool_prefs[i]);
 			g_string_append_printf(style_string,
-			                       "%s = %d\n", prefbase,
+			                       "\t%s = %d\n", prefbase,
 			                       purple_prefs_get_bool(widget_bool_prefs[i]));
 			g_free(prefbase);
 		}
 	}
 	*/
 
-	g_string_append(style_string, "}");
-	g_string_append(style_string, "widget_class \"*\" style \"purplerc_style\"\n");
+	g_string_append(style_string, "\n}\nwidget_class \"*\" style \"purplerc_style\"\n");
 
 	for (i = 0; i < G_N_ELEMENTS(font_prefs); i++) {
 		if (purple_prefs_get_bool(font_prefs_set[i])) {
-			const char *pref;
-
-			prefbase = g_path_get_basename(font_prefs[i]);
-			pref = purple_prefs_get_string(font_prefs[i]);
+			const gchar *pref;
 
-			if (pref != NULL && strcmp(pref, ""))
+			pref = purple_prefs_get_string(font_prefs[i]);
+			if (pref != NULL && strcmp(pref, "")) {
+				prefbase = g_path_get_basename(font_prefs[i]);
 				g_string_append_printf(style_string,
-				                       "style \"%s_style\"\n"
-				                       "{font_name = \"%s\"}\n"
-				                       "widget \"%s\" "
+				                       "style \"%s_style\"\n{\n"
+				                       "\tfont_name = \"%s\"\n}"
+				                       "\nwidget \"%s\" "
 				                       "style \"%s_style\"\n",
 				                       prefbase, pref,
 				                       prefbase, prefbase);
-			g_free(prefbase);
+				g_free(prefbase);
+			}
 		}
 	}
 
-	gtk_rc_parse_string(style_string->str);
-	g_string_free(style_string, TRUE);
+	return style_string;
+}
+
+static void
+purplerc_make_changes()
+{
+	GString *str = make_gtkrc_string();
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkSettings *setting = NULL;
+#endif
+
+	gtk_rc_parse_string(str->str);
+	g_string_free(str, TRUE);
 
 #if GTK_CHECK_VERSION(2,4,0)
 	setting = gtk_settings_get_default();
@@ -185,92 +198,10 @@
 static void
 purplerc_write(GtkWidget *widget, gpointer data)
 {
-	int i;
-	GString *style_string = g_string_new("");
-	char *prefbase = NULL;
-
-	if (purple_prefs_get_bool("/plugins/gtk/purplerc/set/gtk-font-name")) {
-		const char *pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-font-name");
-
-		if (pref != NULL && strcmp(pref, ""))
-			g_string_append_printf(style_string,
-			                       "gtk-font-name = \"%s\"\n",
-			                       pref);
-	}
-
-	if (purple_prefs_get_bool("/plugins/gtk/purplerc/set/gtk-key-theme-name")) {
-		const char *pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-key-theme-name");
-
-		if (pref != NULL && strcmp(pref, ""))
-			g_string_append_printf(style_string,
-			                       "gtk-key-theme-name = \"%s\"\n",
-			                       pref);
-	}
-
-	g_string_append(style_string, "style \"purplerc_style\" {\n");
-
-	for (i = 0; i < G_N_ELEMENTS(color_prefs); i++) {
-		if (purple_prefs_get_bool(color_prefs_set[i])) {
-			const char *pref;
-
-			prefbase = g_path_get_basename(color_prefs[i]);
-			pref = purple_prefs_get_string(color_prefs[i]);
-
-			if (pref != NULL && strcmp(pref, ""))
-			    g_string_append_printf(style_string,
-			                           "%s = \"%s\"\n",
-			                           prefbase, pref);
-			g_free(prefbase);
-		}
-	}
-
-	for (i = 0; i < G_N_ELEMENTS(widget_size_prefs); i++) {
-		if (purple_prefs_get_bool(widget_size_prefs_set[i])) {
-			prefbase = g_path_get_basename(widget_size_prefs[i]);
-			g_string_append_printf(style_string,
-			                       "%s = %d\n", prefbase,
-			                       purple_prefs_get_int(widget_size_prefs[i]));
-			g_free(prefbase);
-		}
-	}
-
-	/*
-	for (i = 0; i < G_N_ELEMENTS(widget_bool_prefs); i++) {
-		if (purple_prefs_get_bool(widget_bool_prefs_set[i])) {
-			prefbase = g_path_get_basename(widget_bool_prefs[i]);
-			g_string_append_printf(style_string,
-			                       "%s = %d\n", prefbase,
-			                       purple_prefs_get_bool(widget_bool_prefs[i]));
-			g_free(prefbase);
-		}
-	}
-	*/
-
-	g_string_append(style_string, "}");
-	g_string_append(style_string, "widget_class \"*\" style \"purplerc_style\"\n");
-
-	for (i = 0; i < G_N_ELEMENTS(font_prefs); i++) {
-		if (purple_prefs_get_bool(font_prefs_set[i])) {
-			const char *pref;
-
-			prefbase = g_path_get_basename(font_prefs[i]);
-			pref = purple_prefs_get_string(font_prefs[i]);
-
-			if (pref != NULL && strcmp(pref, ""))
-				g_string_append_printf(style_string,
-				                       "style \"%s_style\"\n"
-				                       "{font_name = \"%s\"}\n"
-				                       "widget \"%s\" "
-				                       "style \"%s_style\"\n",
-				                       prefbase, pref,
-				                       prefbase, prefbase);
-			g_free(prefbase);
-		}
-	}
-
-	purple_util_write_data_to_file("gtkrc-2.0", style_string->str, -1);
-
-	g_string_free(style_string, TRUE);
+	GString *str = make_gtkrc_string();
+	str = g_string_prepend(str, "# This file automatically written by the Pidgin GTK+ Theme Control plugin.\n# Any changes to this file will be overwritten by the plugin when told to\n# write the settings again.\n# The FAQ (http://developer.pidgin.im/wiki/FAQ) contains some further examples\n# of possible pidgin gtkrc settings.\n");
+	purple_util_write_data_to_file("gtkrc-2.0", str->str, -1);
+	g_string_free(str, TRUE);
 }
 
 static void
@@ -283,7 +214,7 @@
 
 static void
 purplerc_pref_changed_cb(const char *name, PurplePrefType type,
-                       gconstpointer value, gpointer data)
+                         gconstpointer value, gpointer data)
 {
 	purplerc_make_changes();
 }
@@ -291,12 +222,12 @@
 static void
 purplerc_color_response(GtkDialog *color_dialog, gint response, gpointer data)
 {
-	int subscript = GPOINTER_TO_INT(data);
+	gint subscript = GPOINTER_TO_INT(data);
 
 	if (response == GTK_RESPONSE_OK) {
+		GdkColor color;
+		gchar colorstr[8];
 		GtkWidget *colorsel = GTK_COLOR_SELECTION_DIALOG(color_dialog)->colorsel;
-		GdkColor color;
-		char colorstr[8];
 
 		gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(colorsel), &color);
 
@@ -311,11 +242,11 @@
 static void
 purplerc_set_color(GtkWidget *widget, gpointer data)
 {
+	GdkColor color;
+	gchar title[128];
+	const gchar *pref = NULL;
 	GtkWidget *color_dialog = NULL;
-	GdkColor color;
-	char title[128];
-	const char *pref = NULL;
-	int subscript = GPOINTER_TO_INT(data);
+	gint subscript = GPOINTER_TO_INT(data);
 
 	g_snprintf(title, sizeof(title), _("Select Color for %s"),
 	           _(color_names[GPOINTER_TO_INT(data)]));
@@ -337,14 +268,21 @@
 static void
 purplerc_font_response(GtkDialog *font_dialog, gint response, gpointer data)
 {
-	int subscript = GPOINTER_TO_INT(data);
+	const gchar *prefpath;
+	gint subscript = GPOINTER_TO_INT(data);
 
 	if (response == GTK_RESPONSE_OK) {
-		char *fontname = NULL;
+		gchar *fontname = NULL;
+
+		if (subscript == -1) {
+			prefpath = "/plugins/gtk/purplerc/gtk-font-name";
+		} else {
+			prefpath = font_prefs[subscript];
+		}
 
 		fontname = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog));
 
-		purple_prefs_set_string(font_prefs[subscript], fontname);
+		purple_prefs_set_string(prefpath, fontname);
 		g_free(fontname);
 	}
 	gtk_widget_destroy(GTK_WIDGET(font_dialog));
@@ -353,53 +291,25 @@
 static void
 purplerc_set_font(GtkWidget *widget, gpointer data)
 {
+	gchar title[128];
 	GtkWidget *font_dialog = NULL;
-	char title[128];
-	const char *pref = NULL;
-	int subscript = GPOINTER_TO_INT(data);
+	gint subscript = GPOINTER_TO_INT(data);
+	const gchar *pref = NULL, *prefpath = NULL;
 
-	g_snprintf(title, sizeof(title), _("Select Font for %s"),
-	           _(font_names[subscript]));
+	if (subscript == -1) {
+		g_snprintf(title, sizeof(title), _("Select Interface Font"));
+		prefpath = "/plugins/gtk/purplerc/gtk-font-name";
+	} else {
+		g_snprintf(title, sizeof(title), _("Select Font for %s"),
+		           _(font_names[subscript]));
+		prefpath = font_prefs[subscript];
+	}
+
 	font_dialog = gtk_font_selection_dialog_new(title);
 	g_signal_connect(G_OBJECT(font_dialog), "response",
 	                 G_CALLBACK(purplerc_font_response), data);
 
-	pref = purple_prefs_get_string(font_prefs[subscript]);
-
-	if (pref != NULL && strcmp(pref, "")) {
-		gtk_font_selection_set_font_name(GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(font_dialog)->fontsel), pref);
-	}
-
-	gtk_window_present(GTK_WINDOW(font_dialog));
-}
-
-static void
-purplerc_font_response_special(GtkDialog *font_dialog, gint response,
-                             gpointer data)
-{
-	if (response == GTK_RESPONSE_OK) {
-		char *fontname = NULL;
-
-		fontname = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog));
-
-		purple_prefs_set_string("/plugins/gtk/purplerc/gtk-font-name",
-		                      fontname);
-		g_free(fontname);
-	}
-	gtk_widget_destroy(GTK_WIDGET(font_dialog));
-}
-
-static void
-purplerc_set_font_special(GtkWidget *widget, gpointer data)
-{
-	GtkWidget *font_dialog = NULL;
-	const char *pref = NULL;
-
-	font_dialog = gtk_font_selection_dialog_new(_("Select Interface Font"));
-	g_signal_connect(G_OBJECT(font_dialog), "response",
-	                 G_CALLBACK(purplerc_font_response_special), NULL);
-
-	pref = purple_prefs_get_string("/plugins/gtk/purplerc/gtk-font-name");
+	pref = purple_prefs_get_string(prefpath);
 
 	if (pref != NULL && strcmp(pref, "")) {
 		gtk_font_selection_set_font_name(GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(font_dialog)->fontsel), pref);
@@ -413,8 +323,10 @@
 {
 	purplerc_make_changes();
 
-	pref_callback = purple_prefs_connect_callback(plugin, "/plugins/gtk/purplerc",
-	                                            purplerc_pref_changed_cb, NULL);
+	pref_callback = purple_prefs_connect_callback(plugin,
+	                                              "/plugins/gtk/purplerc",
+	                                              purplerc_pref_changed_cb,
+	                                              NULL);
 
 	return TRUE;
 }
@@ -433,17 +345,23 @@
 	/* Note: Intentionally not using the size group argument to the
 	 * pidgin_prefs_labeled_* functions they only add the text label to
 	 * the size group not the whole thing, which isn't what I want. */
-	int i;
-	char *tmp;
+	gint i;
+	gchar *tmp;
 	GtkWidget *check = NULL, *widget = NULL;
-	GtkSizeGroup *labelsg = NULL, *widgetsg = NULL;
-	GtkWidget *ret = NULL, *frame = NULL, *hbox = NULL, *vbox = NULL;
+	GtkWidget *ret = NULL, *hbox = NULL, *frame = NULL;
+	GtkSizeGroup *labelsg = NULL, *widgetsg = NULL, *buttonsg = NULL;
+#ifndef _WIN32
+	const gchar *homepath = "$HOME";
+#else
+	const gchar *homepath = "\%APPDATA\%";
+#endif
 
 	ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
 	gtk_container_set_border_width(GTK_CONTAINER(ret), PIDGIN_HIG_BORDER);
 
 	labelsg  = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 	widgetsg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+	buttonsg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
 	frame = pidgin_make_frame(ret, _("General"));
 	/* interface font */
@@ -451,12 +369,12 @@
 	gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
 	check = pidgin_prefs_checkbox(_("GTK+ Interface Font"),
-	                                "/plugins/gtk/purplerc/set/gtk-font-name",
-	                                hbox);
+	                              "/plugins/gtk/purplerc/set/gtk-font-name",
+	                              hbox);
 	gtk_size_group_add_widget(labelsg, check);
 
 	widget = pidgin_pixbuf_button_from_stock("", GTK_STOCK_SELECT_FONT,
-	                                       PIDGIN_BUTTON_HORIZONTAL);
+	                                         PIDGIN_BUTTON_HORIZONTAL);
 	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0);
 	gtk_size_group_add_widget(widgetsg, widget);
 	gtk_widget_set_sensitive(widget,
@@ -464,20 +382,20 @@
 	g_signal_connect(G_OBJECT(check), "toggled",
 	                 G_CALLBACK(pidgin_toggle_sensitive), widget);
 	g_signal_connect(G_OBJECT(widget), "clicked",
-	                 G_CALLBACK(purplerc_set_font_special), NULL);
+	                 G_CALLBACK(purplerc_set_font), GINT_TO_POINTER(-1));
 
 	/* key theme name */
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
 	gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
 	check = pidgin_prefs_checkbox(_("GTK+ Text Shortcut Theme"),
-	                                "/plugins/gtk/purplerc/set/gtk-key-theme-name",
-	                                hbox);
+	                              "/plugins/gtk/purplerc/set/gtk-key-theme-name",
+	                              hbox);
 	gtk_size_group_add_widget(labelsg, check);
 
 	widget = pidgin_prefs_labeled_entry(hbox, "",
-	                                      "/plugins/gtk/purplerc/gtk-key-theme-name",
-	                                      NULL);
+	                                    "/plugins/gtk/purplerc/gtk-key-theme-name",
+	                                    NULL);
 	/*
 	gtk_size_group_add_widget(widgetsg, widget);
 	*/
@@ -492,7 +410,7 @@
 		gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
 		check = pidgin_prefs_checkbox(_(widget_bool_names[i]),
-		                                widget_bool_prefs_set[i], hbox);
+		                              widget_bool_prefs_set[i], hbox);
 		gtk_size_group_add_widget(labelsg, check);
 
 		widget_bool_widgets[i] = pidgin_prefs_checkbox("", widget_bool_prefs[i], hbox);
@@ -514,7 +432,7 @@
 		gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
 		check = pidgin_prefs_checkbox(_(color_names[i]),
-		                                color_prefs_set[i], hbox);
+		                              color_prefs_set[i], hbox);
 		gtk_size_group_add_widget(labelsg, check);
 
 		color_widgets[i] = pidgin_pixbuf_button_from_stock("", GTK_STOCK_SELECT_COLOR, PIDGIN_BUTTON_HORIZONTAL);
@@ -538,7 +456,7 @@
 		gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
 		check = pidgin_prefs_checkbox(_(widget_size_names[i]),
-		                                widget_size_prefs_set[i], hbox);
+		                              widget_size_prefs_set[i], hbox);
 		gtk_size_group_add_widget(labelsg, check);
 
 		widget_size_widgets[i] = pidgin_prefs_labeled_spin_button(hbox, "", widget_size_prefs[i], 0, 50, NULL);
@@ -559,7 +477,7 @@
 		gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
 		check = pidgin_prefs_checkbox(_(font_names[i]),
-		                                font_prefs_set[i], hbox);
+		                              font_prefs_set[i], hbox);
 		gtk_size_group_add_widget(labelsg, check);
 
 		font_widgets[i] = pidgin_pixbuf_button_from_stock("", GTK_STOCK_SELECT_FONT, PIDGIN_BUTTON_HORIZONTAL);
@@ -572,27 +490,29 @@
 		                 G_CALLBACK(pidgin_toggle_sensitive),
 		                 font_widgets[i]);
 		g_signal_connect(G_OBJECT(font_widgets[i]), "clicked",
-		                 G_CALLBACK(purplerc_set_font), GINT_TO_POINTER(i));
+		                 G_CALLBACK(purplerc_set_font),
+		                 GINT_TO_POINTER(i));
 	}
 
-	frame = pidgin_make_frame(ret, _("Tools"));
+	frame = pidgin_make_frame(ret, _("Gtkrc File Tools"));
 
-	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
-	gtk_box_pack_start(GTK_BOX(frame), vbox, FALSE, FALSE, 0);
+	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
+	gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
 
-	tmp = g_strdup_printf(_("Write settings to %s%sgtkrc-2.0"), purple_user_dir(), G_DIR_SEPARATOR_S);
+	tmp = g_strdup_printf(_("Write settings to %s%sgtkrc-2.0"),
+	                      homepath, G_DIR_SEPARATOR_S);
 	check = gtk_button_new_with_label(tmp);
 	g_free(tmp);
-	gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(labelsg, check);
-	g_signal_connect(G_OBJECT(check), "clicked", G_CALLBACK(purplerc_write),
-	                 NULL);
+	gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, FALSE, 0);
+	gtk_size_group_add_widget(buttonsg, check);
+	g_signal_connect(G_OBJECT(check), "clicked",
+	                 G_CALLBACK(purplerc_write), NULL);
 
 	check = gtk_button_new_with_label(_("Re-read gtkrc files"));
-	gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(labelsg, check);
-	g_signal_connect(G_OBJECT(check), "clicked", G_CALLBACK(purplerc_reread),
-	                 NULL);
+	gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, FALSE, 0);
+	gtk_size_group_add_widget(buttonsg, check);
+	g_signal_connect(G_OBJECT(check), "clicked",
+	                 G_CALLBACK(purplerc_reread), NULL);
 
 	gtk_widget_show_all(ret);
 	return ret;
@@ -645,7 +565,7 @@
 static void
 purplerc_init(PurplePlugin *plugin)
 {
-	int i;
+	gint i;
 
 	purple_prefs_add_none("/plugins");
 	purple_prefs_add_none("/plugins/gtk");
--- a/pidgin/plugins/spellchk.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/spellchk.c	Tue Jun 19 17:28:41 2007 +0000
@@ -2118,7 +2118,7 @@
 plugin_load(PurplePlugin *plugin)
 {
 	void *conv_handle = purple_conversations_get_handle();
-	const GList *convs;
+	GList *convs;
 
 	load_conf();
 
@@ -2137,7 +2137,7 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
-	const GList *convs;
+	GList *convs;
 
 	/* Detach from existing conversations */
 	for (convs = purple_get_conversations(); convs != NULL; convs = convs->next)
--- a/pidgin/plugins/timestamp.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/timestamp.c	Tue Jun 19 17:28:41 2007 +0000
@@ -77,7 +77,7 @@
 	time_t now = time(NULL) / interval * interval;
 	time_t then;
 
-	if (!g_list_find((GList *)purple_get_conversations(), conv))
+	if (!g_list_find(purple_get_conversations(), conv))
 		return FALSE;
 
 	then = GPOINTER_TO_INT(purple_conversation_get_data(
@@ -98,7 +98,7 @@
 	PidginConversation *gtk_conv = PIDGIN_CONVERSATION(conv);
 	GtkTextBuffer *buffer;
 
-	if (!g_list_find((GList *)purple_get_conversations(), conv))
+	if (!g_list_find(purple_get_conversations(), conv))
 		return;
 
 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtk_conv->imhtml));
--- a/pidgin/plugins/xmppconsole.c	Sat Jun 16 07:03:31 2007 +0000
+++ b/pidgin/plugins/xmppconsole.c	Tue Jun 19 17:28:41 2007 +0000
@@ -731,7 +731,7 @@
 	GtkWidget *label;
 	GtkTextBuffer *buffer;
 	GtkWidget *toolbar;
-	const GList *connections;
+	GList *connections;
 #if GTK_CHECK_VERSION(2,4,0)
 	GtkToolItem *button;
 #endif