changeset 22058:3abf33e2572f

merge of 'd32a0c1772bb88a80d5370ff93e7c4b8cf007608' and 'd6936cb019234c5f9985eceac8678731c6b7bf25'
author Hallvard Glad <hallvard.glad@gmail.com>
date Tue, 08 Jan 2008 13:17:59 +0000
parents a7e8e98d48d1 (current diff) 4a204ebed41c (diff)
children fdebef95b300
files
diffstat 141 files changed, 2299 insertions(+), 1185 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Sun Dec 30 23:52:38 2007 +0000
+++ b/COPYRIGHT	Tue Jan 08 13:17:59 2008 +0000
@@ -151,6 +151,7 @@
 Michael Golden
 Charlie Gordon
 Ryan C. Gordon
+Konrad Gräfe
 Miah Gregory
 David Grohmann
 Christian Hammond
@@ -167,6 +168,7 @@
 Nick Hebner
 Mike Heffner
 Justin Heiner
+Moos Heintzen
 Benjamin Herrenschmidt
 Fernando Herrera
 hjheins
@@ -298,6 +300,7 @@
 Jory A. Pratt
 Brent Priddy
 Justin Pryzby
+Ignacio Casal Quinteiro
 Federicco Mena Quintero
 Yosef Radchenko
 David Raeman
@@ -347,6 +350,7 @@
 Scott Shedden
 Dossy Shiobara
 Michael Shkutkov
+Shreevatsa R
 Ettore Simone
 John Silvestri
 Craig Slusher
@@ -414,6 +418,7 @@
 Zsombor Welker
 Andrew Wellington
 Adam Wendt
+Simon Wenner
 Dave West
 Zac West
 Daniel Westermann-Clark
--- a/ChangeLog	Sun Dec 30 23:52:38 2007 +0000
+++ b/ChangeLog	Tue Jan 08 13:17:59 2008 +0000
@@ -7,13 +7,17 @@
 	* Eliminated unmaintained Howl backend implementation for the
 	  Bonjour protocol.  Avahi (or Apple's Bonjour runtime on win32) is
 	  now required to use Bonjour.
+	* Partial support for viewing ICQ status notes (Collin from
+	  ComBOTS GmbH).
 
 	Pidgin:
 	* Added the ability to theme conversation name colors (red and blue)
 	  through your GTK+ theme, and exposed those theme settings to the 
 	  Pidgin GTK+ Theme Control plugin (Dustin Howett)
-	* Fixed having multiple alias edit areas in the infopane (Elliott Sales de
-	  Andrade)
+	* Fixed having multiple alias edit areas in the infopane (Elliott Sales
+	  de Andrade)
+	* Save the conversation "Enable Logging" option per-contact (Moos
+	  Heintzen)
 
 	Finch:
 	* Color is used in the buddylist to indicate status, and the conversation
@@ -22,6 +26,11 @@
 	* The default keybinding for dump-screen is now M-D and uses a file
 	  request dialog. M-d will properly delete-forward-word, and M-f has been
 	  fixed to imitate readline's behavior.
+	* New bindings alt+tab and alt+shift+tab to help navigating between the
+	  higlighted windows (details on the man-page).
+	* Recently signed on (or off) buddies blink in the buddy list.
+	* New action 'Room List' in the action-list can be used to get the list of
+	  available chat rooms for an online account.
 
 version 2.3.1 (12/7/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.3.1
--- a/ChangeLog.API	Sun Dec 30 23:52:38 2007 +0000
+++ b/ChangeLog.API	Tue Jan 08 13:17:59 2008 +0000
@@ -8,6 +8,16 @@
 		* purple_major_version, purple_minor_version,
 		  purple_micro_version variables are exported by version.h,
 		  giving the version of libpurple in use at runtime.
+		* purple_util_set_current_song, purple_util_format_song_info
+		* Some accessor functions to the Roomlist API:
+			* purple_roomlist_get_fields
+			* purple_roomlist_room_get_type
+			* purple_roomlist_room_get_name
+			* purple_roomlist_room_get_parent
+			* purple_roomlist_room_get_fields
+			* purple_roomlist_field_get_type
+			* purple_roomlist_field_get_label
+			* purple_roomlist_field_get_hidden
 
 	Pidgin:
 		Added:
@@ -24,8 +34,17 @@
 		* pidgin_tooltip_setup_for_treeview, pidgin_tooltip_destroy,
 		  pidgin_tooltip_show and pidgin_tooltip_setup_for_widget to simplify
 		  the process of drawing tooltips.
+		* pidgin_add_widget_to_vbox to simplify adding a labeled widget to a
+		  window.
+
+		Deprecated:
+		* PIDGIN_DIALOG
 
 	Finch:
+		* finch_roomlist_get_ui_ops and finch_roomlist_show_all
+		* finch_request_field_get_widget to get the widget for a request
+		  field.
+
 		libgnt:
 		* Added gnt_tree_set_row_color to set the color for a row in a tree.
 		* Added gnt_style_get_string_list
--- a/ChangeLog.win32	Sun Dec 30 23:52:38 2007 +0000
+++ b/ChangeLog.win32	Tue Jan 08 13:17:59 2008 +0000
@@ -1,3 +1,6 @@
+version 2.3.1 (12/7/2007):
+	* No changes
+
 version 2.3.0 (11/24/2007):
 	* Updated GTK+ to 2.12.1 (This was actually included in 2.2.2, but 
 	  didn't get into the Changelog.)
@@ -135,7 +138,7 @@
 
 version 0.82 (08/26/2004):
 	* Selecting away messages using the system tray icon works
-	  (Thanks Fran?ois Gagn?)
+	  (Thanks François Gagné)
 	* Transparency plugin will save your settings again (Kevin Stange)
 	* Updated gtk-wimp to 0.6.2
 	* Updated libpng to 1.2.6 (major security update)
--- a/config.h.mingw	Sun Dec 30 23:52:38 2007 +0000
+++ b/config.h.mingw	Tue Jan 08 13:17:59 2008 +0000
@@ -355,7 +355,7 @@
 
 /* Loads static protocol plugin module initialization functions. */
 #ifndef STATIC_PROTO_INIT
-#define STATIC_PROTO_INIT static void static_proto_init() {  }
+#define STATIC_PROTO_INIT static void static_proto_init(void) {  }
 #endif
 
 /* Define to 1 if you have the ANSI C header files. */
--- a/configure.ac	Sun Dec 30 23:52:38 2007 +0000
+++ b/configure.ac	Tue Jan 08 13:17:59 2008 +0000
@@ -142,7 +142,7 @@
 dnl If we don't have msgfmt, then po/ is going to fail -- ensure that
 dnl AM_GLIB_GNU_GETTEXT found it.
 
-if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT = x
+if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT$INTLTOOL_MSGFMT = x
 then
 	AC_ERROR([
 
@@ -978,7 +978,7 @@
 AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes")
 AM_CONDITIONAL(STATIC_ZEPHYR, test "x$static_zephyr" = "xyes")
 AC_SUBST(STATIC_LINK_LIBS)
-AC_DEFINE_UNQUOTED(STATIC_PROTO_INIT, $extern_init static void static_proto_init() { $load_proto },
+AC_DEFINE_UNQUOTED(STATIC_PROTO_INIT, $extern_init static void static_proto_init(void) { $load_proto },
 	[Loads static protocol plugin module initialization functions.])
 
 AC_ARG_WITH(dynamic_prpls, [AC_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`])
--- a/doc/finch.1.in	Sun Dec 30 23:52:38 2007 +0000
+++ b/doc/finch.1.in	Tue Jan 08 13:17:59 2008 +0000
@@ -105,6 +105,12 @@
 .B Alt \+ 1 2 ... 0
 Jump to the 1st, 2nd ... 10th window.
 .TP
+.B Alt \+ Tab
+Jump to the next URGENT (highlighted) window.
+.TP
+.B Alt \+ Shift \+ Tab
+Jump to the previous URGENT (highlighted) window.
+.TP
 .B Ctrl \+ o
 Bring up the menu (if there is one) for a window.
 .TP
@@ -460,6 +466,7 @@
 .br
 # switch-window-n
 .br
+# Other actions: window-next-urgent, window-prev-urgent
 
 # For the sample custom window manager
 .br
--- a/finch/Makefile.am	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/Makefile.am	Tue Jan 08 13:17:59 2008 +0000
@@ -30,6 +30,7 @@
 	gntpounce.c \
 	gntprefs.c \
 	gntrequest.c \
+	gntroomlist.c \
 	gntsound.c \
 	gntstatus.c \
 	gntui.c
@@ -49,6 +50,7 @@
 	gntpounce.h \
 	gntprefs.h \
 	gntrequest.h \
+	gntroomlist.h \
 	gntsound.h \
 	gntstatus.h \
 	gntui.h
--- a/finch/finch.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/finch.c	Tue Jan 08 13:17:59 2008 +0000
@@ -49,14 +49,14 @@
 #include "config.h"
 
 static void
-debug_init()
+debug_init(void)
 {
 	finch_debug_init();
 	purple_debug_set_ui_ops(finch_debug_get_ui_ops());
 }
 
 static GHashTable *ui_info = NULL;
-static GHashTable *finch_ui_get_info()
+static GHashTable *finch_ui_get_info(void)
 {
 	if (ui_info == NULL) {
 		ui_info = g_hash_table_new(g_str_hash, g_str_equal);
@@ -91,7 +91,7 @@
 };
 
 static PurpleCoreUiOps *
-gnt_core_get_ui_ops()
+gnt_core_get_ui_ops(void)
 {
 	return &core_ops;
 }
--- a/finch/gntaccount.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntaccount.c	Tue Jan 08 13:17:59 2008 +0000
@@ -722,7 +722,7 @@
 }
 
 static gpointer
-finch_accounts_get_handle()
+finch_accounts_get_handle(void)
 {
 	static int handle;
 
--- a/finch/gntblist.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntblist.c	Tue Jan 08 13:17:59 2008 +0000
@@ -83,6 +83,12 @@
 	GntMenuItem *plugins;
 } FinchBlist;
 
+typedef struct
+{
+	gpointer row;                /* the row in the GntTree */
+	guint signed_timer;          /* used when 'recently' signed on/off */
+} FinchBlistNode;
+
 typedef enum
 {
 	STATUS_PRIMITIVE = 0,
@@ -131,6 +137,31 @@
 static int color_offline;
 static int color_idle;
 
+static FinchBlistNode *
+create_finch_blist_node(PurpleBlistNode *node, gpointer row)
+{
+	FinchBlistNode *fnode = node->ui_data;
+	if (!fnode) {
+		fnode = g_new0(FinchBlistNode, 1);
+		fnode->signed_timer = 0;
+		node->ui_data = fnode;
+	}
+	fnode->row = row;
+	return fnode;
+}
+
+static void
+reset_blist_node_ui_data(PurpleBlistNode *node)
+{
+	FinchBlistNode *fnode = node->ui_data;
+	if (fnode == NULL)
+		return;
+	if (fnode->signed_timer)
+		purple_timeout_remove(fnode->signed_timer);
+	g_free(fnode);
+	node->ui_data = NULL;
+}
+
 static int
 get_display_color(PurpleBlistNode  *node)
 {
@@ -157,6 +188,34 @@
 	return color;
 }
 
+static GntTextFormatFlags
+get_blist_node_flag(PurpleBlistNode *node)
+{
+	GntTextFormatFlags flag = 0;
+	FinchBlistNode *fnode = node->ui_data;
+
+	if (ggblist->tagged && g_list_find(ggblist->tagged, node))
+		flag |= GNT_TEXT_FLAG_BOLD;
+
+	if (fnode && fnode->signed_timer)
+		flag |= GNT_TEXT_FLAG_BLINK;
+	else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
+		node = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact *)node);
+		fnode = node->ui_data;
+		if (fnode && fnode->signed_timer)
+			flag |= GNT_TEXT_FLAG_BLINK;
+	}
+
+	return flag;
+}
+
+static void
+blist_update_row_flags(PurpleBlistNode *node)
+{
+	gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), node, get_blist_node_flag(node));
+	gnt_tree_set_row_color(GNT_TREE(ggblist->tree), node, get_display_color(node));
+}
+
 static gboolean
 is_contact_online(PurpleContact *contact)
 {
@@ -217,7 +276,7 @@
 		return;
 
 	gnt_tree_remove(GNT_TREE(ggblist->tree), node);
-	node->ui_data = NULL;
+	reset_blist_node_ui_data(node);
 	if (ggblist->tagged)
 		ggblist->tagged = g_list_remove(ggblist->tagged, node);
 
@@ -234,7 +293,7 @@
 				(!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_group_online(group)))
 			node_remove(list, node->parent);
 		for (node = node->child; node; node = node->next)
-			node->ui_data = NULL;
+			reset_blist_node_ui_data(node);
 	} else {
 		for (node = node->child; node; node = node->next)
 			node_remove(list, node);
@@ -261,7 +320,7 @@
 		gnt_tree_change_text(GNT_TREE(ggblist->tree), node,
 				0, get_display_name(node));
 		gnt_tree_sort_row(GNT_TREE(ggblist->tree), node);
-		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), node, get_display_color(node));
+		blist_update_row_flags(node);
 	}
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
@@ -269,8 +328,6 @@
 		if (purple_account_is_connected(buddy->account) &&
 				(PURPLE_BUDDY_IS_ONLINE(buddy) || purple_prefs_get_bool(PREF_ROOT "/showoffline")))
 			add_node((PurpleBlistNode*)buddy, list->ui_data);
-		else
-			node_remove(purple_get_blist(), node);
 
 		node_update(list, node->parent);
 	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
@@ -279,7 +336,7 @@
 		PurpleContact *contact = (PurpleContact*)node;
 		if ((!purple_prefs_get_bool(PREF_ROOT "/showoffline") && !is_contact_online(contact)) ||
 				contact->currentsize < 1)
-			node_remove(purple_get_blist(), node);
+			/* nothing */;
 		else {
 			if (node->ui_data == NULL) {
 				/* The core seems to expect the UI to add the buddies. */
@@ -483,7 +540,7 @@
 }
 
 static void
-finch_request_add_group()
+finch_request_add_group(void)
 {
 	purple_request_input(NULL, _("Add Group"), NULL, _("Enter the name of the group"),
 			NULL, FALSE, FALSE, NULL,
@@ -511,7 +568,7 @@
 };
 
 static gpointer
-finch_blist_get_handle()
+finch_blist_get_handle(void)
 {
 	static int handle;
 
@@ -524,8 +581,8 @@
 	PurpleBlistNode *node = (PurpleBlistNode *)group;
 	if (node->ui_data)
 		return;
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
-			gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), NULL, NULL);
+	create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group,
+			gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)), NULL, NULL));
 	gnt_tree_set_expanded(GNT_TREE(ggblist->tree), node,
 		!purple_blist_node_get_bool(node, "collapsed"));
 }
@@ -539,7 +596,7 @@
 
 	if (PURPLE_BLIST_NODE_IS_CONTACT(node))
 		node = (PurpleBlistNode*)purple_contact_get_priority_buddy((PurpleContact*)node);  /* XXX: this can return NULL?! */
-	
+
 	if (node == NULL)
 		return NULL;
 
@@ -550,7 +607,7 @@
 		PurplePresence *presence;
 		PurpleStatus *now;
 		gboolean ascii = gnt_ascii_only();
-		
+
 		presence = purple_buddy_get_presence(buddy);
 		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOBILE))
 			strncpy(status, ascii ? ":" : "☎", sizeof(status) - 1);
@@ -601,9 +658,9 @@
 	group = purple_chat_get_group(chat);
 	add_node((PurpleBlistNode*)group, ggblist);
 
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), chat,
+	create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), chat,
 				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
-				group, NULL);
+				group, NULL));
 }
 
 static void
@@ -623,9 +680,9 @@
 	group = (PurpleGroup*)node->parent;
 	add_node((PurpleBlistNode*)group, ggblist);
 
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), contact,
+	create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), contact,
 				gnt_tree_create_row(GNT_TREE(ggblist->tree), name),
-				group, NULL);
+				group, NULL));
 
 	gnt_tree_set_expanded(GNT_TREE(ggblist->tree), contact, FALSE);
 }
@@ -635,7 +692,7 @@
 {
 	PurpleContact *contact;
 	PurpleBlistNode *node = (PurpleBlistNode *)buddy;
-	int color = 0;
+
 	if (node->ui_data)
 		return;
 
@@ -647,14 +704,13 @@
 		return;
 	add_node((PurpleBlistNode*)contact, ggblist);
 
-	node->ui_data = gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy,
+	create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), buddy,
 				gnt_tree_create_row(GNT_TREE(ggblist->tree), get_display_name(node)),
-				contact, NULL);
-
-	color = get_display_color((PurpleBlistNode*)buddy);
-	gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color);
+				contact, NULL));
+
+	blist_update_row_flags((PurpleBlistNode*)buddy);
 	if (buddy == purple_contact_get_priority_buddy(contact))
-		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color);
+		blist_update_row_flags((PurpleBlistNode*)contact);
 }
 
 #if 0
@@ -1564,9 +1620,7 @@
 static void
 update_node_display(PurpleBlistNode *node, FinchBlist *ggblist)
 {
-	GntTextFormatFlags flag = 0;
-	if (ggblist->tagged && g_list_find(ggblist->tagged, node))
-		flag |= GNT_TEXT_FLAG_BOLD;
+	GntTextFormatFlags flag = get_blist_node_flag(node);
 	gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), node, flag);
 }
 
@@ -1574,33 +1628,18 @@
 update_buddy_display(PurpleBuddy *buddy, FinchBlist *ggblist)
 {
 	PurpleContact *contact;
-	GntTextFormatFlags bflag = 0, cflag = 0;
-	int color = 0;
 
 	contact = purple_buddy_get_contact(buddy);
 
 	gnt_tree_change_text(GNT_TREE(ggblist->tree), buddy, 0, get_display_name((PurpleBlistNode*)buddy));
 	gnt_tree_change_text(GNT_TREE(ggblist->tree), contact, 0, get_display_name((PurpleBlistNode*)contact));
 
-	if (ggblist->tagged && g_list_find(ggblist->tagged, buddy))
-		bflag |= GNT_TEXT_FLAG_BOLD;
-	if (ggblist->tagged && g_list_find(ggblist->tagged, contact))
-		cflag |= GNT_TEXT_FLAG_BOLD;
+	blist_update_row_flags((PurpleBlistNode *)buddy);
+	if (buddy == purple_contact_get_priority_buddy(contact))
+		blist_update_row_flags((PurpleBlistNode *)contact);
 
 	if (ggblist->tnode == (PurpleBlistNode*)buddy)
 		draw_tooltip(ggblist);
-
-	color = get_display_color((PurpleBlistNode*)buddy);
-	gnt_tree_set_row_color(GNT_TREE(ggblist->tree), buddy, color);
-	if (buddy == purple_contact_get_priority_buddy(contact))
-		gnt_tree_set_row_color(GNT_TREE(ggblist->tree), contact, color);
-
-	gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), buddy, bflag);
-	if (buddy == purple_contact_get_priority_buddy(contact))
-		gnt_tree_set_row_flags(GNT_TREE(ggblist->tree), contact, cflag);
-
-	if (buddy != purple_contact_get_priority_buddy(contact))
-			update_buddy_display(purple_contact_get_priority_buddy(contact), ggblist);
 }
 
 static void
@@ -1649,7 +1688,7 @@
 
 	node = purple_blist_get_root();
 	while (node) {
-		node->ui_data = NULL;
+		reset_blist_node_ui_data(node);
 		node = purple_blist_node_next(node, TRUE);
 	}
 
@@ -1663,7 +1702,7 @@
 }
 
 static void
-populate_buddylist()
+populate_buddylist(void)
 {
 	PurpleBlistNode *node;
 	PurpleBuddyList *list;
@@ -1696,7 +1735,7 @@
 }
 
 static void
-populate_status_dropdown()
+populate_status_dropdown(void)
 {
 	int i;
 	GList *iter;
@@ -1762,7 +1801,7 @@
 	gnt_tree_remove_all(GNT_TREE(ggblist->tree));
 	node = purple_blist_get_root();
 	for (; node; node = purple_blist_node_next(node, TRUE))
-		node->ui_data = NULL;
+		reset_blist_node_ui_data(node);
 	populate_buddylist();
 	gnt_tree_set_selected(GNT_TREE(ggblist->tree), sel);
 	draw_tooltip(ggblist);
@@ -2122,8 +2161,53 @@
 	}
 }
 
+static gboolean
+buddy_recent_signed_on_off(gpointer data)
+{
+	PurpleBlistNode *node = data;
+	FinchBlistNode *fnode = node->ui_data;
+	PurpleBuddy *buddy = (PurpleBuddy*)node;
+
+	purple_timeout_remove(fnode->signed_timer);
+	fnode->signed_timer = 0;
+
+	if (!purple_account_is_connected(buddy->account) ||
+			(!PURPLE_BUDDY_IS_ONLINE(buddy) && !purple_prefs_get_bool(PREF_ROOT "/showoffline"))) {
+		node_remove(purple_get_blist(), node);
+	} else {
+		update_node_display(node, ggblist);
+		if (node->parent && PURPLE_BLIST_NODE_IS_CONTACT(node->parent))
+			update_node_display(node->parent, ggblist);
+	}
+
+	return FALSE;
+}
+
+static gboolean
+buddy_signed_on_off_cb(gpointer data)
+{
+	PurpleBlistNode *node = data;
+	FinchBlistNode *fnode = node->ui_data;
+	if (!ggblist || !fnode)
+		return FALSE;
+
+	if (fnode->signed_timer)
+		purple_timeout_remove(fnode->signed_timer);
+	fnode->signed_timer = purple_timeout_add_seconds(6, (GSourceFunc)buddy_recent_signed_on_off, data);
+	update_node_display(node, ggblist);
+	if (node->parent && PURPLE_BLIST_NODE_IS_CONTACT(node->parent))
+		update_node_display(node->parent, ggblist);
+	return FALSE;
+}
+
 static void
-reconstruct_plugins_menu()
+buddy_signed_on_off(PurpleBuddy* buddy, gpointer null)
+{
+	g_idle_add(buddy_signed_on_off_cb, buddy);
+}
+
+static void
+reconstruct_plugins_menu(void)
 {
 	GntWidget *sub;
 	GntMenuItem *plg;
@@ -2155,7 +2239,7 @@
 }
 
 static void
-reconstruct_accounts_menu()
+reconstruct_accounts_menu(void)
 {
 	GntWidget *sub;
 	GntMenuItem *acc, *item;
@@ -2355,7 +2439,7 @@
 }
 
 static void
-create_menu()
+create_menu(void)
 {
 	GntWidget *menu, *sub, *subsub;
 	GntMenuItem *item;
@@ -2513,12 +2597,12 @@
 	purple_signal_connect(purple_plugins_get_handle(), "plugin-unload", finch_blist_get_handle(),
 				PURPLE_CALLBACK(reconstruct_plugins_menu), NULL);
 
+	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", finch_blist_get_handle(),
+				PURPLE_CALLBACK(buddy_signed_on_off), ggblist);
+	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", finch_blist_get_handle(),
+				PURPLE_CALLBACK(buddy_signed_on_off), ggblist);
+
 #if 0
-	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", finch_blist_get_handle(),
-				PURPLE_CALLBACK(buddy_signed_on), ggblist);
-	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", finch_blist_get_handle(),
-				PURPLE_CALLBACK(buddy_signed_off), ggblist);
-
 	/* These I plan to use to indicate unread-messages etc. */
 	purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", finch_blist_get_handle(),
 				PURPLE_CALLBACK(received_im_msg), list);
--- a/finch/gntcertmgr.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntcertmgr.c	Tue Jan 08 13:17:59 2008 +0000
@@ -246,7 +246,7 @@
 
 /* populate the list */
 static void
-populate_cert_list()
+populate_cert_list(void)
 {
 	GList *idlist, *l;
 
--- a/finch/gntconv.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntconv.c	Tue Jan 08 13:17:59 2008 +0000
@@ -350,7 +350,7 @@
 }
 
 static gpointer
-finch_conv_get_handle()
+finch_conv_get_handle(void)
 {
 	static int handle;
 	return &handle;
@@ -1119,7 +1119,7 @@
 static PurpleCmdRet
 cmd_show_window(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data)
 {
-	void (*callback)() = data;
+	void (*callback)(void) = data;
 	callback();
 	return PURPLE_CMD_STATUS_OK;
 }
--- a/finch/gntft.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntft.c	Tue Jan 08 13:17:59 2008 +0000
@@ -85,7 +85,7 @@
  **************************************************************************/
 
 static void
-update_title_progress()
+update_title_progress(void)
 {
 	GList *list;
 	int num_active_xfers = 0;
--- a/finch/gntft.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntft.h	Tue Jan 08 13:17:59 2008 +0000
@@ -55,7 +55,7 @@
 /**
  * Hides the file transfer dialog.
  */
-void finch_xfer_dialog_hide();
+void finch_xfer_dialog_hide(void);
 
 /**
  * Adds a file transfer to the dialog.
--- a/finch/gntidle.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntidle.c	Tue Jan 08 13:17:59 2008 +0000
@@ -28,7 +28,7 @@
 #include "idle.h"
 
 static time_t
-finch_get_idle_time()
+finch_get_idle_time(void)
 {
 	return gnt_wm_get_idle_time();
 }
--- a/finch/gntnotify.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntnotify.c	Tue Jan 08 13:17:59 2008 +0000
@@ -147,14 +147,14 @@
 }
 
 static void
-reset_email_dialog()
+reset_email_dialog(void)
 {
 	emaildialog.window = NULL;
 	emaildialog.tree = NULL;
 }
 
 static void
-setup_email_dialog()
+setup_email_dialog(void)
 {
 	GntWidget *box, *tree, *button;
 	if (emaildialog.window)
--- a/finch/gntplugin.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntplugin.c	Tue Jan 08 13:17:59 2008 +0000
@@ -171,7 +171,7 @@
 }
 
 static void
-confwin_init()
+confwin_init(void)
 {
 	confwins = g_hash_table_new(g_direct_hash, g_direct_equal);
 }
--- a/finch/gntplugin.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntplugin.h	Tue Jan 08 13:17:59 2008 +0000
@@ -40,7 +40,7 @@
  **********************************************************************/
 /*@{*/
 
-typedef GntWidget* (*FinchPluginFrame) ();
+typedef GntWidget* (*FinchPluginFrame) (void);
 
 /* Guess where these came from */
 #define FINCH_PLUGIN_TYPE FINCH_UI
--- a/finch/gntprefs.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntprefs.c	Tue Jan 08 13:17:59 2008 +0000
@@ -76,17 +76,17 @@
 	PurplePrefType type;
 	const char *pref;
 	const char *label;
-	GList *(*lv)();   /* If the value is to be selected from a number of choices */
+	GList *(*lv)(void);   /* If the value is to be selected from a number of choices */
 } Prefs;
 
 static GList *
-get_log_options()
+get_log_options(void)
 {
 	return purple_log_logger_get_options();
 }
 
 static GList *
-get_idle_options()
+get_idle_options(void)
 {
 	GList *list = NULL;
 	list = g_list_append(list, (char *)_("Based on keyboard use"));
@@ -99,7 +99,7 @@
 }
 
 static GList *
-get_status_titles()
+get_status_titles(void)
 {
 	GList *list = NULL;
 	GList *iter;
@@ -212,7 +212,7 @@
 };
 
 static void
-free_strings()
+free_strings(void)
 {
 	g_list_foreach(pref_request.freestrings, (GFunc)g_free, NULL);
 	g_list_free(pref_request.freestrings);
--- a/finch/gntrequest.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntrequest.c	Tue Jan 08 13:17:59 2008 +0000
@@ -36,6 +36,7 @@
 
 #include "finch.h"
 #include "gntrequest.h"
+#include "debug.h"
 #include "util.h"
 
 typedef struct
@@ -824,3 +825,32 @@
 	}
 }
 
+GntWidget *finch_request_field_get_widget(PurpleRequestField *field)
+{
+	GntWidget *ret = NULL;
+	switch (purple_request_field_get_type(field)) {
+		case PURPLE_REQUEST_FIELD_BOOLEAN:
+			ret = create_boolean_field(field);
+			break;
+		case PURPLE_REQUEST_FIELD_STRING:
+			ret = create_string_field(field, NULL);
+			break;
+		case PURPLE_REQUEST_FIELD_INTEGER:
+			ret = create_integer_field(field);
+			break;
+		case PURPLE_REQUEST_FIELD_CHOICE:
+			ret = create_choice_field(field);
+			break;
+		case PURPLE_REQUEST_FIELD_LIST:
+			ret = create_list_field(field);
+			break;
+		case PURPLE_REQUEST_FIELD_ACCOUNT:
+			ret = create_account_field(field);
+			break;
+		default:
+			purple_debug_error("GntRequest", "Unimplemented request-field %d\n", purple_request_field_get_type(field));
+			break;
+	}
+	return ret;
+}
+
--- a/finch/gntrequest.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntrequest.h	Tue Jan 08 13:17:59 2008 +0000
@@ -27,6 +27,7 @@
 #define _GNT_REQUEST_H
 
 #include "request.h"
+#include "gnt.h"
 
 /**********************************************************************
  * @name GNT Request API
@@ -56,6 +57,15 @@
  */
 void finch_request_save_in_prefs(gpointer null, PurpleRequestFields *fields);
 
+/**
+ * Create a widget field for a request-field.
+ *
+ * @param field   The request field.
+ *
+ * @return A GntWidget for the request field.
+ * @since 2.4.0
+ */
+GntWidget *finch_request_field_get_widget(PurpleRequestField *field);
 /*@}*/
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntroomlist.c	Tue Jan 08 13:17:59 2008 +0000
@@ -0,0 +1,415 @@
+/**
+ * @file gntroomlist.c GNT Room List API
+ * @ingroup finch
+ */
+
+/* finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include"internal.h"
+
+#include "gntrequest.h"
+#include "gntroomlist.h"
+
+#include "gntbox.h"
+#include "gntbutton.h"
+#include "gntcombobox.h"
+#include "gnttextview.h"
+#include "gnttree.h"
+#include "gntwindow.h"
+
+#include "debug.h"
+
+#define PREF_ROOT "/finch/roomlist"
+
+/* Yes, just one roomlist at a time. Let's not get greedy. Aight? */
+struct _FinchRoomlist
+{
+	GntWidget *window;
+
+	GntWidget *accounts;
+	GntWidget *tree;
+	GntWidget *details;
+
+	GntWidget *getlist;
+	GntWidget *add;
+	GntWidget *join;
+	GntWidget *stop;
+	GntWidget *close;
+
+	PurpleAccount *account;
+	PurpleRoomlist *roomlist;
+} froomlist;
+
+typedef struct _FinchRoomlist FinchRoomlist;
+
+static void
+unset_roomlist(gpointer null)
+{
+	froomlist.window = NULL;
+	if (froomlist.roomlist)
+		purple_roomlist_unref(froomlist.roomlist);
+}
+
+static void
+update_roomlist(PurpleRoomlist *list)
+{
+	if (froomlist.roomlist == list)
+		return;
+
+	if (froomlist.roomlist)
+		purple_roomlist_unref(froomlist.roomlist);
+
+	if ((froomlist.roomlist = list) != NULL)
+		purple_roomlist_ref(list);
+}
+
+static void fl_stop(GntWidget *button, gpointer null)
+{
+	if (froomlist.roomlist &&
+			purple_roomlist_get_in_progress(froomlist.roomlist))
+		purple_roomlist_cancel_get_list(froomlist.roomlist);
+}
+
+static void fl_get_list(GntWidget *button, gpointer null)
+{
+	PurpleAccount *account = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(froomlist.accounts));
+	PurpleConnection *gc = purple_account_get_connection(account);
+
+	if (!gc)
+		return;
+
+	froomlist.roomlist = purple_roomlist_get_list(gc);
+	gnt_box_give_focus_to_child(GNT_BOX(froomlist.window), froomlist.tree);
+}
+
+static void fl_add_chat(GntWidget *button, gpointer null)
+{
+	char *name;
+	PurpleRoomlistRoom *room = gnt_tree_get_selection_data(GNT_TREE(froomlist.tree));
+	PurpleConnection *gc = purple_account_get_connection(froomlist.account);
+	PurplePluginProtocolInfo *prpl_info = NULL;
+
+	if (gc == NULL || room == NULL)
+		return;
+
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+
+	if(prpl_info != NULL && prpl_info->roomlist_room_serialize)
+		name = prpl_info->roomlist_room_serialize(room);
+	else
+		name = g_strdup(purple_roomlist_room_get_name(room));
+
+	purple_blist_request_add_chat(froomlist.account, NULL, NULL, name);
+
+	g_free(name);
+}
+
+static void fl_close(GntWidget *button, gpointer null)
+{
+	gnt_widget_destroy(froomlist.window);
+}
+
+static void
+roomlist_activated(GntWidget *widget)
+{
+	PurpleRoomlistRoom *room = gnt_tree_get_selection_data(GNT_TREE(widget));
+	if (!room)
+		return;
+
+	switch (purple_roomlist_room_get_type(room)) {
+		case PURPLE_ROOMLIST_ROOMTYPE_ROOM:
+			purple_roomlist_room_join(froomlist.roomlist, room);
+			break;
+		case PURPLE_ROOMLIST_ROOMTYPE_CATEGORY:
+			if (!room->expanded_once) {
+				purple_roomlist_expand_category(froomlist.roomlist, room);
+				room->expanded_once = TRUE;
+			}
+			break;
+	}
+	gnt_tree_set_expanded(GNT_TREE(widget), room, TRUE);
+}
+
+static void
+roomlist_selection_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
+{
+	GList *iter, *field;
+	PurpleRoomlistRoom *room = current;
+	GntTextView *tv = GNT_TEXT_VIEW(froomlist.details);
+	gboolean first = TRUE;
+
+	gnt_text_view_clear(tv);
+
+	if (!room)
+		return;
+
+	for (iter = purple_roomlist_room_get_fields(room),
+			field = purple_roomlist_get_fields(froomlist.roomlist);
+			iter && field;
+			iter = iter->next, field = field->next) {
+		PurpleRoomlistField *f = field->data;
+		char *label = NULL;
+
+		if (purple_roomlist_field_get_hidden(f)) {
+			continue;
+		}
+
+		if (!first)
+			gnt_text_view_append_text_with_flags(tv, "\n", GNT_TEXT_FLAG_NORMAL);
+
+		gnt_text_view_append_text_with_flags(tv,
+				purple_roomlist_field_get_label(f), GNT_TEXT_FLAG_BOLD);
+		gnt_text_view_append_text_with_flags(tv, ": ", GNT_TEXT_FLAG_BOLD);
+
+		switch (purple_roomlist_field_get_type(f)) {
+			case PURPLE_ROOMLIST_FIELD_BOOL:
+				label = g_strdup(iter->data ? "True" : "False");
+				break;
+			case PURPLE_ROOMLIST_FIELD_INT:
+				label = g_strdup_printf("%d", (int)iter->data);
+				break;
+			case PURPLE_ROOMLIST_FIELD_STRING:
+				label = g_strdup(iter->data);
+				break;
+		}
+		gnt_text_view_append_text_with_flags(tv, label, GNT_TEXT_FLAG_NORMAL);
+		g_free(label);
+		first = FALSE;
+	}
+
+	if (purple_roomlist_room_get_type(room) == PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) {
+		if (!first)
+			gnt_text_view_append_text_with_flags(tv, "\n", GNT_TEXT_FLAG_NORMAL);
+		gnt_text_view_append_text_with_flags(tv,
+				_("Hit 'Enter' to find more rooms of this category."),
+				GNT_TEXT_FLAG_NORMAL);
+	}
+}
+
+static void
+roomlist_account_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null)
+{
+	if (froomlist.account == current) {
+		return;
+	}
+
+	froomlist.account = current;
+	if (froomlist.roomlist) {
+		if (purple_roomlist_get_in_progress(froomlist.roomlist))
+			purple_roomlist_cancel_get_list(froomlist.roomlist);
+		update_roomlist(NULL);
+	}
+
+	gnt_tree_remove_all(GNT_TREE(froomlist.tree));
+	gnt_widget_draw(froomlist.tree);
+}
+
+static void
+reset_account_list(PurpleAccount *account)
+{
+	GList *list;
+	GntComboBox *accounts = GNT_COMBO_BOX(froomlist.accounts);
+	gnt_combo_box_remove_all(accounts);
+	for (list = purple_connections_get_all(); list; list = list->next) {
+		PurplePluginProtocolInfo *prpl_info = NULL;
+		PurpleConnection *gc = list->data;
+
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+		if (prpl_info->roomlist_get_list != NULL) {
+			PurpleAccount *account = purple_connection_get_account(gc);
+			char *text = g_strdup_printf("%s (%s)",
+					purple_account_get_username(account),
+					purple_account_get_protocol_name(account));
+			gnt_combo_box_add_data(accounts, account, text);
+			g_free(text);
+		}
+	}
+}
+
+static void
+size_changed_cb(GntWidget *widget, int oldw, int oldh)
+{
+	int w, h;
+	gnt_widget_get_size(widget, &w, &h);
+	purple_prefs_set_int(PREF_ROOT "/size/width", w);
+	purple_prefs_set_int(PREF_ROOT "/size/height", h);
+}
+
+static void
+setup_roomlist(PurpleAccount *account)
+{
+	GntWidget *window, *tree, *hbox, *accounts;
+	int iter;
+	struct {
+		const char *label;
+		GCallback callback;
+		GntWidget **widget;
+	} buttons[] = {
+		{_("Stop"), G_CALLBACK(fl_stop), &froomlist.stop},
+		{_("Get"), G_CALLBACK(fl_get_list), &froomlist.getlist},
+		{_("Add"), G_CALLBACK(fl_add_chat), &froomlist.add},
+		{_("Close"), G_CALLBACK(fl_close), &froomlist.close},
+		{NULL, NULL, NULL}
+	};
+
+	if (froomlist.window)
+		return;
+
+	froomlist.window = window = gnt_window_new();
+	g_object_set(G_OBJECT(window), "vertical", TRUE, NULL);
+	gnt_box_set_pad(GNT_BOX(window), 0);
+	gnt_box_set_title(GNT_BOX(window), _("Room List"));
+	gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID);
+
+	froomlist.accounts = accounts = gnt_combo_box_new();
+	reset_account_list(account);
+	gnt_box_add_widget(GNT_BOX(window), froomlist.accounts);
+	g_signal_connect(G_OBJECT(froomlist.accounts), "selection-changed",
+			G_CALLBACK(roomlist_account_changed), NULL);
+	froomlist.account = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(froomlist.accounts));
+
+	froomlist.tree = tree = gnt_tree_new_with_columns(2);
+	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
+	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(roomlist_activated), NULL);
+	gnt_tree_set_column_titles(GNT_TREE(tree), _("Name"), "");
+	gnt_tree_set_show_separator(GNT_TREE(tree), FALSE);
+	gnt_tree_set_col_width(GNT_TREE(tree), 1, 1);
+	gnt_tree_set_column_resizable(GNT_TREE(tree), 1, FALSE);
+	gnt_tree_set_search_column(GNT_TREE(tree), 0);
+
+	gnt_box_add_widget(GNT_BOX(window), tree);
+
+	froomlist.details = gnt_text_view_new();
+	gnt_text_view_set_flag(GNT_TEXT_VIEW(froomlist.details), GNT_TEXT_VIEW_TOP_ALIGN);
+	gnt_box_add_widget(GNT_BOX(window), froomlist.details);
+	gnt_widget_set_size(froomlist.details, -1, 8);
+
+	hbox = gnt_hbox_new(FALSE);
+	gnt_box_add_widget(GNT_BOX(window), hbox);
+
+	for (iter = 0; buttons[iter].label; iter++) {
+		GntWidget *button = gnt_button_new(buttons[iter].label);
+		gnt_box_add_widget(GNT_BOX(hbox), button);
+		g_signal_connect(G_OBJECT(button), "activate", buttons[iter].callback, NULL);
+		*buttons[iter].widget = button;
+		gnt_text_view_attach_scroll_widget(GNT_TEXT_VIEW(froomlist.details), button);
+	}
+
+	g_signal_connect(G_OBJECT(tree), "selection-changed", G_CALLBACK(roomlist_selection_changed), NULL);
+
+	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(unset_roomlist), NULL);
+}
+
+static void
+fl_show_with_account(PurpleAccount *account)
+{
+	setup_roomlist(account);
+	g_signal_handlers_disconnect_matched(G_OBJECT(froomlist.window), G_SIGNAL_MATCH_FUNC,
+			0, 0, NULL, G_CALLBACK(size_changed_cb), NULL);
+	gnt_widget_show(froomlist.window);
+	gnt_screen_resize_widget(froomlist.window,
+			purple_prefs_get_int(PREF_ROOT "/size/width"),
+			purple_prefs_get_int(PREF_ROOT "/size/height"));
+	g_signal_connect(G_OBJECT(froomlist.window), "size_changed", G_CALLBACK(size_changed_cb), NULL);
+	gnt_window_present(froomlist.window);
+}
+
+static void
+fl_create(PurpleRoomlist *list)
+{
+	list->ui_data = &froomlist;
+	setup_roomlist(NULL);
+	update_roomlist(list);
+}
+
+static void
+fl_set_fields(PurpleRoomlist *list, GList *fields)
+{
+}
+
+static void
+fl_add_room(PurpleRoomlist *roomlist, PurpleRoomlistRoom *room)
+{
+	gboolean category;
+	if (froomlist.roomlist != roomlist)
+		return;
+
+	category = (purple_roomlist_room_get_type(room) == PURPLE_ROOMLIST_ROOMTYPE_CATEGORY);
+	gnt_tree_remove(GNT_TREE(froomlist.tree), room);
+	gnt_tree_add_row_after(GNT_TREE(froomlist.tree), room,
+			gnt_tree_create_row(GNT_TREE(froomlist.tree),
+				purple_roomlist_room_get_name(room),
+				category ? "<" : ""),
+			purple_roomlist_room_get_parent(room), NULL);
+	gnt_tree_set_expanded(GNT_TREE(froomlist.tree), room, !category);
+}
+
+static void
+fl_destroy(PurpleRoomlist *list)
+{
+	if (!froomlist.window)
+		return;
+
+	if (froomlist.roomlist == list) {
+		froomlist.roomlist = NULL;
+		gnt_tree_remove_all(GNT_TREE(froomlist.tree));
+		gnt_widget_draw(froomlist.tree);
+	}
+}
+
+static PurpleRoomlistUiOps ui_ops =
+{
+	fl_show_with_account, /* void (*show_with_account)(PurpleAccount *account); **< Force the ui to pop up a dialog and get the list */
+	fl_create, /* void (*create)(PurpleRoomlist *list); **< A new list was created. */
+	fl_set_fields, /* void (*set_fields)(PurpleRoomlist *list, GList *fields); **< Sets the columns. */
+	fl_add_room, /* void (*add_room)(PurpleRoomlist *list, PurpleRoomlistRoom *room); **< Add a room to the list. */
+	NULL, /* void (*in_progress)(PurpleRoomlist *list, gboolean flag); **< Are we fetching stuff still? */
+	fl_destroy, /* void (*destroy)(PurpleRoomlist *list); **< We're destroying list. */
+
+	NULL, /* void (*_purple_reserved1)(void); */
+	NULL, /* void (*_purple_reserved2)(void); */
+	NULL, /* void (*_purple_reserved3)(void); */
+	NULL /* void (*_purple_reserved4)(void); */
+};
+
+PurpleRoomlistUiOps *finch_roomlist_get_ui_ops(void)
+{
+	return &ui_ops;
+}
+
+void finch_roomlist_show_all(void)
+{
+	purple_roomlist_show_with_account(NULL);
+}
+
+void finch_roomlist_init(void)
+{
+	purple_prefs_add_none(PREF_ROOT);
+	purple_prefs_add_none(PREF_ROOT "/size");
+	purple_prefs_add_int(PREF_ROOT "/size/width", 60);
+	purple_prefs_add_int(PREF_ROOT "/size/height", 15);
+}
+
+void finch_roomlist_uninit(void)
+{
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/gntroomlist.h	Tue Jan 08 13:17:59 2008 +0000
@@ -0,0 +1,61 @@
+/**
+ * @file gntroomlist.h GNT Room List API
+ * @ingroup finch
+ */
+
+/* finch
+ *
+ * Finch is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef _GNT_ROOMLIST_H
+#define _GNT_ROOMLIST_H
+
+#include "roomlist.h"
+
+/**********************************************************************
+ * @name GNT Room List API
+ **********************************************************************/
+/*@{*/
+
+/**
+ * Initialize the roomlist subsystem.
+ */
+void finch_roomlist_init(void);
+
+/**
+ * Get the ui-functions.
+ *
+ * @return The PurpleRoomlistUiOps structure populated with the appropriate functions.
+ */
+PurpleRoomlistUiOps *finch_roomlist_get_ui_ops(void);
+
+/**
+ * Show the roomlist dialog.
+ */
+void finch_roomlist_show_all(void);
+
+/**
+ * Uninitialize the roomlist subsystem.
+ */
+void finch_roomlist_uninit(void);
+
+/*@}*/
+
+#endif
+
--- a/finch/gntsound.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntsound.c	Tue Jan 08 13:17:59 2008 +0000
@@ -286,7 +286,7 @@
 }
 
 static void *
-finch_sound_get_handle()
+finch_sound_get_handle(void)
 {
 	static int handle;
 
--- a/finch/gntui.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/gntui.c	Tue Jan 08 13:17:59 2008 +0000
@@ -35,6 +35,7 @@
 #include "gntpounce.h"
 #include "gntprefs.h"
 #include "gntrequest.h"
+#include "gntroomlist.h"
 #include "gntstatus.h"
 #include "gntsound.h"
 
@@ -71,14 +72,21 @@
 	finch_notify_init();
 	purple_notify_set_ui_ops(finch_notify_get_ui_ops());
 
+	/* Request */
 	finch_request_init();
 	purple_request_set_ui_ops(finch_request_get_ui_ops());
 
+	/* Pounce */
 	finch_pounces_init();
 
+	/* File transfer */
 	finch_xfers_init();
 	purple_xfers_set_ui_ops(finch_xfers_get_ui_ops());
 
+	/* Roomlist */
+	finch_roomlist_init();
+	purple_roomlist_set_ui_ops(finch_roomlist_get_ui_ops());
+
 	gnt_register_action(_("Accounts"), finch_accounts_show_all);
 	gnt_register_action(_("Buddy List"), finch_blist_show);
 	gnt_register_action(_("Buddy Pounces"), finch_pounces_manager_show);
@@ -86,6 +94,7 @@
 	gnt_register_action(_("Debug Window"), finch_debug_window_show);
 	gnt_register_action(_("File Transfers"), finch_xfer_dialog_show);
 	gnt_register_action(_("Plugins"), finch_plugins_show_all);
+	gnt_register_action(_("Room List"), finch_roomlist_show_all);
 	gnt_register_action(_("Sounds"), finch_sounds_show_all);
 	gnt_register_action(_("Preferences"), finch_prefs_show_all);
 	gnt_register_action(_("Statuses"), finch_savedstatus_show_all);
@@ -118,6 +127,9 @@
 	finch_xfers_uninit();
 	purple_xfers_set_ui_ops(NULL);
 
+	finch_roomlist_uninit();
+	purple_roomlist_set_ui_ops(NULL);
+
 	gnt_quit();
 #endif
 }
--- a/finch/libgnt/gnt.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gnt.h	Tue Jan 08 13:17:59 2008 +0000
@@ -141,7 +141,7 @@
  * @param label      The user-visible label for the action.
  * @param callback   The callback function for the action.
  */
-void gnt_register_action(const char *label, void (*callback)());
+void gnt_register_action(const char *label, void (*callback)(void));
 
 /**
  * Show a menu.
--- a/finch/libgnt/gntbindable.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gntbindable.c	Tue Jan 08 13:17:59 2008 +0000
@@ -45,7 +45,7 @@
 } rebind_info;
 
 static void 
-gnt_bindable_free_rebind_info()
+gnt_bindable_free_rebind_info(void)
 {
 	g_free(rebind_info.name);
 	g_free(rebind_info.keys);
--- a/finch/libgnt/gntcolors.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gntcolors.c	Tue Jan 08 13:17:59 2008 +0000
@@ -40,7 +40,7 @@
 } colors[GNT_TOTAL_COLORS];
 
 static void
-backup_colors()
+backup_colors(void)
 {
 	short i;
 	for (i = 0; i < GNT_TOTAL_COLORS; i++)
@@ -51,13 +51,13 @@
 }
 
 static gboolean
-can_use_custom_color()
+can_use_custom_color(void)
 {
 	return (gnt_style_get_bool(GNT_STYLE_COLOR, FALSE) && can_change_color());
 }
 
 static void
-restore_colors()
+restore_colors(void)
 {
 	short i;
 	for (i = 0; i < GNT_TOTAL_COLORS; i++)
--- a/finch/libgnt/gntentry.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gntentry.c	Tue Jan 08 13:17:59 2008 +0000
@@ -916,7 +916,7 @@
 }
 
 static GntEntryKillRing *
-new_killring()
+new_killring(void)
 {
 	GntEntryKillRing *kr = g_new0(GntEntryKillRing, 1);
 	kr->buffer = g_string_new(NULL);
--- a/finch/libgnt/gntmain.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gntmain.c	Tue Jan 08 13:17:59 2008 +0000
@@ -72,7 +72,7 @@
 
 static void setup_io(void);
 
-static gboolean refresh_screen();
+static gboolean refresh_screen(void);
 
 static GntWM *wm;
 static GntClipboard *clipboard;
@@ -326,7 +326,7 @@
 }
 
 static gboolean
-refresh_screen()
+refresh_screen(void)
 {
 	gnt_bindable_perform_action_named(GNT_BINDABLE(wm), "refresh-screen", NULL);
 	return FALSE;
@@ -363,7 +363,7 @@
 }
 
 static void
-ask_before_exit()
+ask_before_exit(void)
 {
 	static GntWidget *win = NULL;
 	GntWidget *bbox, *button;
@@ -412,7 +412,7 @@
 #ifdef SIGWINCH
 	case SIGWINCH:
 		erase();
-		g_idle_add(refresh_screen, NULL);
+		g_idle_add((GSourceFunc)refresh_screen, NULL);
 		if (org_winch_handler)
 			org_winch_handler(sig);
 		signal(SIGWINCH, sighandler);
@@ -430,7 +430,7 @@
 }
 
 static void
-init_wm()
+init_wm(void)
 {
 	const char *name = gnt_style_get(GNT_STYLE_WM);
 	gpointer handle;
@@ -614,7 +614,7 @@
 	gnt_wm_update_window(wm, widget);
 }
 
-void gnt_register_action(const char *label, void (*callback)())
+void gnt_register_action(const char *label, void (*callback)(void))
 {
 	GntAction *action = g_new0(GntAction, 1);
 	action->label = g_strdup(label);
--- a/finch/libgnt/gnttextview.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gnttextview.c	Tue Jan 08 13:17:59 2008 +0000
@@ -830,7 +830,7 @@
 
 
 static void
-cleanup_pageditor()
+cleanup_pageditor(void)
 {
 	unlink(pageditor.file);
 	g_free(pageditor.file);
--- a/finch/libgnt/gntwm.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gntwm.c	Tue Jan 08 13:17:59 2008 +0000
@@ -135,7 +135,7 @@
  * to expose the entire character, it is not always redrawn.
  */
 static void
-work_around_for_ncurses_bug()
+work_around_for_ncurses_bug(void)
 {
 #ifndef NO_WIDECHAR
 	PANEL *panel = NULL;
@@ -183,7 +183,7 @@
 }
 
 static void
-update_act_msg()
+update_act_msg(void)
 {
 	GntWidget *label;
 	GList *iter;
@@ -388,10 +388,10 @@
 }
 
 static void
-switch_window(GntWM *wm, int direction)
+switch_window(GntWM *wm, int direction, gboolean urgent)
 {
 	GntWidget *w = NULL, *wid = NULL;
-	int pos;
+	int pos, orgpos;
 
 	if (wm->_list.window || wm->menu)
 		return;
@@ -404,15 +404,20 @@
 	}
 
 	w = wm->cws->ordered->data;
-	pos = g_list_index(wm->cws->list, w);
-	pos += direction;
+	orgpos = pos = g_list_index(wm->cws->list, w);
+
+	do {
+		pos += direction;
 
-	if (pos < 0)
-		wid = g_list_last(wm->cws->list)->data;
-	else if (pos >= g_list_length(wm->cws->list))
-		wid = wm->cws->list->data;
-	else if (pos >= 0)
-		wid = g_list_nth_data(wm->cws->list, pos);
+		if (pos < 0) {
+			wid = g_list_last(wm->cws->list)->data;
+			pos = g_list_length(wm->cws->list) - 1;
+		} else if (pos >= g_list_length(wm->cws->list)) {
+			wid = wm->cws->list->data;
+			pos = 0;
+		} else
+			wid = g_list_nth_data(wm->cws->list, pos);
+	} while (urgent && !GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_URGENT) && pos != orgpos);
 
 	gnt_wm_raise_window(wm, wid);
 }
@@ -421,7 +426,7 @@
 window_next(GntBindable *bindable, GList *null)
 {
 	GntWM *wm = GNT_WM(bindable);
-	switch_window(wm, 1);
+	switch_window(wm, 1, FALSE);
 	return TRUE;
 }
 
@@ -429,7 +434,7 @@
 window_prev(GntBindable *bindable, GList *null)
 {
 	GntWM *wm = GNT_WM(bindable);
-	switch_window(wm, -1);
+	switch_window(wm, -1, FALSE);
 	return TRUE;
 }
 
@@ -1202,6 +1207,22 @@
 	return ignore_keys ? !(ignore_keys = FALSE) : FALSE;
 }
 
+static gboolean
+window_next_urgent(GntBindable *bindable, GList *n)
+{
+	GntWM *wm = GNT_WM(bindable);
+	switch_window(wm, 1, TRUE);
+	return TRUE;
+}
+
+static gboolean
+window_prev_urgent(GntBindable *bindable, GList *n)
+{
+	GntWM *wm = GNT_WM(bindable);
+	switch_window(wm, -1, TRUE);
+	return TRUE;
+}
+
 #ifdef USE_PYTHON
 static void
 python_script_selected(GntFileSel *fs, const char *path, const char *f, gpointer n)
@@ -1323,6 +1344,7 @@
 {
 	int i;
 	GObjectClass *gclass = G_OBJECT_CLASS(klass);
+	char key[32];
 
 	gclass->dispose = gnt_wm_destroy;
 
@@ -1482,10 +1504,15 @@
 				"\033" "\\", NULL);
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-window", help_for_window,
 				"\033" "|", NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-start", ignore_keys_start, 
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-start", ignore_keys_start,
 				GNT_KEY_CTRL_G, NULL);
-	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-end", ignore_keys_end, 
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-end", ignore_keys_end,
 				"\033" GNT_KEY_CTRL_G, NULL);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next-urgent", window_next_urgent,
+				"\033" "\t", NULL);
+	snprintf(key, sizeof(key), "\033%s", GNT_KEY_BACK_TAB);
+	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-prev-urgent", window_prev_urgent,
+				key[1] ? key : NULL, NULL);
 #ifdef USE_PYTHON
 	gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "run-python", run_python,
 				GNT_KEY_F3, NULL);
--- a/finch/libgnt/gntwm.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/gntwm.h	Tue Jan 08 13:17:59 2008 +0000
@@ -73,7 +73,7 @@
 typedef struct _GntAction
 {
 	const char *label;
-	void (*callback)();
+	void (*callback)(void);
 } GntAction;
 
 struct _GntWM
--- a/finch/libgnt/pygnt/test.py	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/libgnt/pygnt/test.py	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 import gobject
 import gnt
 
--- a/finch/plugins/gntgf.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/finch/plugins/gntgf.c	Tue Jan 08 13:17:59 2008 +0000
@@ -122,7 +122,7 @@
 }
 
 static void
-urgent()
+urgent(void)
 {
 	/* This is from deryni/tuomov's urgent_test.c */
 	Display *dpy;
@@ -322,7 +322,7 @@
 }
 
 static GntWidget *
-config_frame()
+config_frame(void)
 {
 	GntWidget *window, *tree, *check;
 	int i;
--- a/libpurple/account.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/account.c	Tue Jan 08 13:17:59 2008 +0000
@@ -467,7 +467,7 @@
 }
 
 static void
-schedule_accounts_save()
+schedule_accounts_save(void)
 {
 	if (save_timer == 0)
 		save_timer = purple_timeout_add_seconds(5, save_cb, NULL);
--- a/libpurple/blist.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/blist.c	Tue Jan 08 13:17:59 2008 +0000
@@ -298,7 +298,7 @@
 }
 
 static xmlnode *
-blist_to_xmlnode()
+blist_to_xmlnode(void)
 {
 	xmlnode *node, *child, *grandchild;
 	PurpleBlistNode *gnode;
@@ -332,7 +332,7 @@
 }
 
 static void
-purple_blist_sync()
+purple_blist_sync(void)
 {
 	xmlnode *node;
 	char *data;
--- a/libpurple/buddyicon.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/buddyicon.c	Tue Jan 08 13:17:59 2008 +0000
@@ -49,6 +49,8 @@
 static GHashTable *icon_data_cache = NULL;
 static GHashTable *icon_file_cache = NULL;
 
+static void delete_buddy_icon_settings(PurpleBlistNode *node, const char *setting_name);
+
 /* This one is used for both custom buddy icons
  * on PurpleContacts and account icons. */
 static GHashTable *pointer_icon_cache = NULL;
@@ -124,7 +126,7 @@
 							purple_imgstore_get_size(img));	
 	} else 	{
 		purple_debug_error("buddyicon", "Unable to create file %s: %s\n",
-		                   path, g_strerror(errno));
+		                   path, "File already exists.");
 	}
 	g_free(path);
 }
@@ -614,13 +616,16 @@
 				checksum = purple_blist_node_get_string((PurpleBlistNode*)b, "icon_checksum");
 				purple_buddy_icon_set_data(icon, data, len, checksum);
 			}
+			else
+				delete_buddy_icon_settings((PurpleBlistNode*)b, "buddy_icon");
+
 			g_free(path);
 		}
 
 		purple_buddy_icons_set_caching(caching);
 	}
 
-	return purple_buddy_icon_ref(icon);
+	return (icon ? purple_buddy_icon_ref(icon) : NULL);
 }
 
 gboolean
--- a/libpurple/cipher.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/cipher.c	Tue Jan 08 13:17:59 2008 +0000
@@ -775,7 +775,7 @@
 static void
 hmac_set_key(PurpleCipherContext *context, const guchar * key)
 {
-	hmac_set_key_with_len(context, key, strlen(key));
+	hmac_set_key_with_len(context, key, strlen((char *)key));
 }
 
 static size_t 
--- a/libpurple/connection.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/connection.c	Tue Jan 08 13:17:59 2008 +0000
@@ -542,8 +542,10 @@
 
 	switch (ssl_error) {
 		case PURPLE_SSL_HANDSHAKE_FAILED:
+			reason = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
+			break;
 		case PURPLE_SSL_CONNECT_FAILED:
-			reason = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
+			reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
 			break;
 		case PURPLE_SSL_CERTIFICATE_INVALID:
 			/* TODO: maybe PURPLE_SSL_* should be more specific? */
@@ -551,7 +553,7 @@
 			break;
 		default:
 			g_assert_not_reached ();
-			reason = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
+			reason = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR;
 	}
 
 	purple_connection_error_reason (gc, reason,
@@ -564,12 +566,12 @@
 	switch (reason)
 	{
 		case PURPLE_CONNECTION_ERROR_NETWORK_ERROR:
+		case PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR:
 			return FALSE;
 		case PURPLE_CONNECTION_ERROR_INVALID_USERNAME:
 		case PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED:
 		case PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE:
 		case PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT:
-		case PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR:
 		case PURPLE_CONNECTION_ERROR_NAME_IN_USE:
 		case PURPLE_CONNECTION_ERROR_INVALID_SETTINGS:
 		case PURPLE_CONNECTION_ERROR_OTHER_ERROR:
--- a/libpurple/connection.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/connection.h	Tue Jan 08 13:17:59 2008 +0000
@@ -196,11 +196,11 @@
 	 *  available; on Windows, it uses Win32's network change notification
 	 *  infrastructure.
 	 */
-	void (*network_connected)();
+	void (*network_connected)(void);
 	/** Called when libpurple discovers that the computer's network
 	 *  connection has gone away.
 	 */
-	void (*network_disconnected)();
+	void (*network_disconnected)(void);
 
 	/** Called when an error causes a connection to be disconnected.
 	 *  Called before #disconnected.  This op is intended to replace
--- a/libpurple/conversation.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/conversation.h	Tue Jan 08 13:17:59 2008 +0000
@@ -490,7 +490,8 @@
  *
  * @param conv The conversation.
  *
- * @return The conversation's name.
+ * @return The conversation's name. If the conversation is an IM with a PurpleBuddy,
+ *         then it's the name of the PurpleBuddy.
  */
 const char *purple_conversation_get_name(const PurpleConversation *conv);
 
@@ -718,7 +719,7 @@
  *
  * @param msg   A PurpleConvMessage
  *
- * @return   The name of the sender of the message
+ * @return   The message flags
  *
  * @since 2.2.0
  */
@@ -729,7 +730,7 @@
  *
  * @param msg   A PurpleConvMessage
  *
- * @return   The name of the sender of the message
+ * @return   The timestamp of the message
  *
  * @since 2.2.0
  */
--- a/libpurple/core.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/core.h	Tue Jan 08 13:17:59 2008 +0000
@@ -67,13 +67,14 @@
  * Calls purple_core_quit().  This can be used as the function 
  * passed to purple_timeout_add() when you want to shutdown Purple 
  * in a specified amount of time.  When shutting down Purple 
- * from a plugin, you must use this with a timeout value of 0: 
+ * from a plugin, you must use this instead of purple_core_quit();
+ * for an immediate exit, use a timeout value of 0: 
  *   purple_timeout_add(0, purple_core_quitcb, NULL);
  * This is ensures that code from your plugin is not being 
- * executed when purple_core_quit() is called.  Otherwise you 
- * would get a core dump after purple_core_quit() executes and 
- * control returns to your plugin because purple_core_quit() frees 
- * all plugins.
+ * executed when purple_core_quit() is called.  If the plugin
+ * called purple_core_quit() directly, you would get a core dump
+ * after purple_core_quit() executes and control returns to your
+ * plugin because purple_core_quit() frees all plugins.
  */
 gboolean purple_core_quit_cb(gpointer unused);
 
--- a/libpurple/dnsquery.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/dnsquery.c	Tue Jan 08 13:17:59 2008 +0000
@@ -142,7 +142,7 @@
  */
 #ifdef HAVE_SIGNAL_H
 G_GNUC_NORETURN static void
-trap_gdb_bug()
+trap_gdb_bug(int sig)
 {
 	const char *message =
 		"Purple's DNS child got a SIGTRAP signal.\n"
@@ -286,7 +286,7 @@
  * Begin the functions for dealing with the DNS child processes.
  */
 static void
-cope_with_gdb_brokenness()
+cope_with_gdb_brokenness(void)
 {
 #ifdef __linux__
 	static gboolean already_done = FALSE;
@@ -460,7 +460,7 @@
 static void host_resolved(gpointer data, gint source, PurpleInputCondition cond);
 
 static void
-handle_next_queued_request()
+handle_next_queued_request(void)
 {
 	PurpleDnsQueryData *query_data;
 	PurpleDnsQueryResolverProcess *resolver;
--- a/libpurple/example/nullclient.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/example/nullclient.c	Tue Jan 08 13:17:59 2008 +0000
@@ -167,7 +167,7 @@
 };
 
 static void
-null_ui_init()
+null_ui_init(void)
 {
 	/**
 	 * This should initialize the UI components for all the modules. Here we
@@ -191,7 +191,7 @@
 };
 
 static void
-init_libpurple()
+init_libpurple(void)
 {
 	/* Set a custom user directory (optional) */
 	purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
@@ -250,14 +250,14 @@
 }
 
 static void
-connect_to_signals_for_demonstration_purposes_only()
+connect_to_signals_for_demonstration_purposes_only(void)
 {
 	static int handle;
 	purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
 				PURPLE_CALLBACK(signed_on), NULL);
 }
 
-int main()
+int main(int argc, char *argv[])
 {
 	GList *iter;
 	int i, num;
--- a/libpurple/idle.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/idle.c	Tue Jan 08 13:17:59 2008 +0000
@@ -215,8 +215,8 @@
 /*
  * Check idle and set the timer to fire at the next idle-worth event 
  */
-static gint
-check_idleness_timer()
+static gboolean
+check_idleness_timer(void)
 {
 	check_idleness();
 	if (time_until_next_idle_event == 0)
@@ -225,7 +225,7 @@
 	{
 		/* +1 for the boundary,
 		 * +1 more for g_timeout_add_seconds rounding. */
-		idle_timer = purple_timeout_add_seconds(time_until_next_idle_event + 2, check_idleness_timer, NULL);
+		idle_timer = purple_timeout_add_seconds(time_until_next_idle_event + 2, (GSourceFunc)check_idleness_timer, NULL);
 	}
 	return FALSE;
 }
@@ -295,7 +295,7 @@
 }
 
 static void *
-purple_idle_get_handle()
+purple_idle_get_handle(void)
 {
 	static int handle;
 
@@ -307,7 +307,7 @@
 	int idle_poll_minutes = purple_prefs_get_int("/purple/away/mins_before_away");
 
 	 /* +1 more for g_timeout_add_seconds rounding. */
-	idle_timer = purple_timeout_add_seconds((idle_poll_minutes * 60) + 2, check_idleness_timer, NULL);
+	idle_timer = purple_timeout_add_seconds((idle_poll_minutes * 60) + 2, (GSourceFunc)check_idleness_timer, NULL);
 
 	purple_idle_touch();
 
--- a/libpurple/plugin.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugin.c	Tue Jan 08 13:17:59 2008 +0000
@@ -667,7 +667,10 @@
 			}
 			else
 			{
+#if 0
+				/* This isn't necessary. This has already been done when unloading dep_plugin. */
 				plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l);
+#endif
 			}
 		}
 	}
--- a/libpurple/plugins/ciphertest.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugins/ciphertest.c	Tue Jan 08 13:17:59 2008 +0000
@@ -61,7 +61,7 @@
 };
 
 static void
-cipher_test_md5() {
+cipher_test_md5(void) {
 	PurpleCipher *cipher;
 	PurpleCipherContext *context;
 	gchar digest[33];
@@ -113,12 +113,12 @@
 	{"a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"},
 	{"abc", "a9993e364706816aba3e25717850c26c9cd0d89d"} ,
 	{"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1"} ,
-    {NULL, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"},
+	{NULL, "34aa973cd4c4daa4f61eeb2bdbad27316534016f"},
 	{NULL, NULL}
 };
 
 static void
-cipher_test_sha1() {
+cipher_test_sha1(void) {
 	PurpleCipher *cipher;
 	PurpleCipherContext *context;
 	gchar digest[41];
@@ -176,7 +176,7 @@
 }
 
 static void
-cipher_test_digest()
+cipher_test_digest(void)
 {
 	const gchar *nonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093";
 	const gchar *client_nonce = "0a4f113b";
--- a/libpurple/plugins/log_reader.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugins/log_reader.c	Tue Jan 08 13:17:59 2008 +0000
@@ -2426,7 +2426,7 @@
 
 }
 
-static void log_reader_init_prefs() {
+static void log_reader_init_prefs(void) {
 	char *path;
 #ifdef _WIN32
 	char *folder;
--- a/libpurple/plugins/perl/common/fallback/const-c.inc	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugins/perl/common/fallback/const-c.inc	Tue Jan 08 13:17:59 2008 +0000
@@ -33,7 +33,7 @@
      Regenerate these constant functions by feeding this entire source file to
      perl -x
 
-#!/usr/bin/perl -w
+#!/usr/bin/env perl -w
 use ExtUtils::Constant qw (constant_types C_constant XS_constant);
 
 my $types = {map {($_, 1)} qw(IV)};
--- a/libpurple/plugins/ssl/ssl-nss.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugins/ssl/ssl-nss.c	Tue Jan 08 13:17:59 2008 +0000
@@ -109,7 +109,7 @@
 	}
 }
 
-static gchar *get_error_text()
+static gchar *get_error_text(void)
 {
 	PRInt32 len = PR_GetErrorTextLength();
 	gchar *ret = NULL;
--- a/libpurple/plugins/tcl/tcl.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugins/tcl/tcl.c	Tue Jan 08 13:17:59 2008 +0000
@@ -149,7 +149,7 @@
 	return 0;
 }
 
-static Tcl_Interp *tcl_create_interp()
+static Tcl_Interp *tcl_create_interp(void)
 {
 	Tcl_Interp *interp;
 
--- a/libpurple/plugins/test.pl	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/plugins/test.pl	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl -w
 
 use Gaim;
 
--- a/libpurple/protocols/bonjour/bonjour.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Tue Jan 08 13:17:59 2008 +0000
@@ -617,7 +617,7 @@
 #endif
 
 static void
-initialize_default_account_values()
+initialize_default_account_values(void)
 {
 #ifndef _WIN32
 	struct passwd *info;
--- a/libpurple/protocols/bonjour/mdns_win32.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Tue Jan 08 13:17:59 2008 +0000
@@ -30,19 +30,21 @@
 
 static GSList *pending_buddies = NULL;
 
+typedef struct _dnssd_service_ref_handler {
+	DNSServiceRef sdRef;
+	PurpleAccount *account;
+	guint input_handler;
+} DnsSDServiceRefHandlerData;
+
 /* data used by win32 bonjour implementation */
 typedef struct _win32_session_impl_data {
-	DNSServiceRef presence_svc;
-	DNSServiceRef browser_svc;
+	DnsSDServiceRefHandlerData *presence_query;
+	DnsSDServiceRefHandlerData *browser_query;
 	DNSRecordRef buddy_icon_rec;
-
-	guint presence_handler;
-	guint browser_handler;
 } Win32SessionImplData;
 
 typedef struct _win32_buddy_service_resolver_data {
-	DNSServiceRef txt_query;
-	guint txt_query_handler;
+	DnsSDServiceRefHandlerData *txt_query;
 	uint32_t if_idx;
 	gchar *name;
 	gchar *type;
@@ -53,21 +55,20 @@
 
 typedef struct _win32_buddy_impl_data {
 	GSList *resolvers;
-	DNSServiceRef null_query;
-	guint null_query_handler;
+	DnsSDServiceRefHandlerData *null_query;
 } Win32BuddyImplData;
 
 /* data structure for the resolve callback */
 typedef struct _ResolveCallbackArgs {
-	DNSServiceRef resolver;
-	guint resolver_handler;
+	DnsSDServiceRefHandlerData *resolver_query;
 	PurpleAccount *account;
 	BonjourBuddy *bb;
 	Win32SvcResolverData *res_data;
 	gchar *full_service_name;
-	PurpleDnsQueryData *query;
+	PurpleDnsQueryData *dns_query;
 } ResolveCallbackArgs;
 
+
 static gint
 _find_resolver_data(gconstpointer a, gconstpointer b) {
 	const Win32SvcResolverData *rd_a = a;
@@ -87,8 +88,9 @@
 static void
 _cleanup_resolver_data(Win32SvcResolverData *rd) {
 	if (rd->txt_query != NULL) {
-		purple_input_remove(rd->txt_query_handler);
-		DNSServiceRefDeallocate(rd->txt_query);
+		purple_input_remove(rd->txt_query->input_handler);
+		DNSServiceRefDeallocate(rd->txt_query->sdRef);
+		g_free(rd->txt_query);
 	}
 	g_free(rd->name);
 	g_free(rd->type);
@@ -98,7 +100,16 @@
 
 static void
 _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) {
-	DNSServiceProcessResult((DNSServiceRef) data);
+	DnsSDServiceRefHandlerData *srh = data;
+	DNSServiceErrorType errorCode = DNSServiceProcessResult(srh->sdRef);
+	if (errorCode != kDNSServiceErr_NoError) {
+		purple_debug_error("bonjour", "Error (%d) handling mDNS response.\n", errorCode);
+		/* This happens when the mDNSResponder goes down, I haven't seen it happen any other time (in my limited testing) */
+		if (errorCode == kDNSServiceErr_Unknown) {
+			purple_connection_error_reason(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+				_("Error communicating with local mDNSResponder."));
+		}
+	}
 }
 
 static void
@@ -123,7 +134,7 @@
 	uint32_t ttl, void *context)
 {
 
-	if (kDNSServiceErr_NoError != errorCode) {
+	if (errorCode != kDNSServiceErr_NoError) {
 		purple_debug_error("bonjour", "record query - callback error.\n");
 		/* TODO: Probably should remove the buddy when this happens */
 	} else if (flags & kDNSServiceFlagsAdd) {
@@ -142,9 +153,9 @@
 			bonjour_buddy_got_buddy_icon(bb, rdata, rdlen);
 
 			/* We've got what we need; stop listening */
-			purple_input_remove(idata->null_query_handler);
-			idata->null_query_handler = 0;
-			DNSServiceRefDeallocate(idata->null_query);
+			purple_input_remove(idata->null_query->input_handler);
+			DNSServiceRefDeallocate(idata->null_query->sdRef);
+			g_free(idata->null_query);
 			idata->null_query = NULL;
 		}
 	}
@@ -153,7 +164,7 @@
 static void
 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message)
 {
-	ResolveCallbackArgs* args = (ResolveCallbackArgs*) data;
+	ResolveCallbackArgs *args = (ResolveCallbackArgs*) data;
 	Win32BuddyImplData *idata = args->bb->mdns_impl_data;
 	gboolean delete_buddy = FALSE;
 	PurpleBuddy *pb;
@@ -168,27 +179,31 @@
 		delete_buddy = TRUE;
 	} else {
 		struct sockaddr_in *addr = g_slist_nth_data(hosts, 1);
+		DNSServiceErrorType errorCode;
+		DNSServiceRef txt_query_sr;
 
 		/* finally, set up the continuous txt record watcher, and add the buddy to purple */
-
-		if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&args->res_data->txt_query, kDNSServiceFlagsLongLivedQuery,
+		errorCode = DNSServiceQueryRecord(&txt_query_sr, kDNSServiceFlagsLongLivedQuery,
 				kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT,
-				kDNSServiceClass_IN, _mdns_record_query_callback, args->bb)) {
-
+				kDNSServiceClass_IN, _mdns_record_query_callback, args->bb);
+		if (errorCode == kDNSServiceErr_NoError) {
 			const char *ip = inet_ntoa(addr->sin_addr);
 
 			purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj);
 
-
 			args->bb->ips = g_slist_prepend(args->bb->ips, g_strdup(ip));
 			args->res_data->ip = args->bb->ips->data;
 
-			args->res_data->txt_query_handler = purple_input_add(DNSServiceRefSockFD(args->res_data->txt_query),
+			args->res_data->txt_query = g_new(DnsSDServiceRefHandlerData, 1);
+			args->res_data->txt_query->sdRef = txt_query_sr;
+			args->res_data->txt_query->account = args->account;
+
+			args->res_data->txt_query->input_handler = purple_input_add(DNSServiceRefSockFD(txt_query_sr),
 				PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query);
 
 			bonjour_buddy_add_to_purple(args->bb, NULL);
 		} else {
-			purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s\n", args->bb->name);
+			purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s (%d)\n", args->bb->name, errorCode);
 			delete_buddy = TRUE;
 		}
 
@@ -230,21 +245,21 @@
 _mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
     const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context)
 {
-	ResolveCallbackArgs *args = (ResolveCallbackArgs*)context;
+	ResolveCallbackArgs *args = (ResolveCallbackArgs*) context;
 	Win32BuddyImplData *idata = args->bb->mdns_impl_data;
 
 	/* remove the input fd and destroy the service ref */
-	purple_input_remove(args->resolver_handler);
-	args->resolver_handler = 0;
-	DNSServiceRefDeallocate(args->resolver);
-	args->resolver = NULL;
+	purple_input_remove(args->resolver_query->input_handler);
+	DNSServiceRefDeallocate(args->resolver_query->sdRef);
+	g_free(args->resolver_query);
+	args->resolver_query = NULL;
 
-	if (kDNSServiceErr_NoError != errorCode)
+	if (errorCode != kDNSServiceErr_NoError)
 		purple_debug_error("bonjour", "service resolver - callback error.\n");
 	else {
 		/* set more arguments, and start the host resolver */
 
-		if ((args->query =
+		if ((args->dns_query =
 				purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)) != NULL) {
 
 			args->full_service_name = g_strdup(fullname);
@@ -286,7 +301,7 @@
 				const char *name, const char *regtype, const char *domain, void *context) {
 
 	/* TODO: deal with collision */
-	if (kDNSServiceErr_NoError != errorCode)
+	if (errorCode != kDNSServiceErr_NoError)
 		purple_debug_error("bonjour", "service advertisement - callback error (%d).\n", errorCode);
 	else
 		purple_debug_info("bonjour", "service advertisement - callback.\n");
@@ -298,26 +313,28 @@
 {
 	PurpleAccount *account = (PurpleAccount*)context;
 
-	if (kDNSServiceErr_NoError != errorCode)
-		purple_debug_error("bonjour", "service browser - callback error\n");
+	if (errorCode != kDNSServiceErr_NoError)
+		purple_debug_error("bonjour", "service browser - callback error (%d)\n", errorCode);
 	else if (flags & kDNSServiceFlagsAdd) {
 		/* A presence service instance has been discovered... check it isn't us! */
 		if (purple_utf8_strcasecmp(serviceName, account->username) != 0) {
+			DNSServiceErrorType resErrorCode;
 			/* OK, lets go ahead and resolve it to add to the buddy list */
 			ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1);
+			DNSServiceRef resolver_sr;
 
 			purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n",
 							  serviceName, interfaceIndex, regtype ? regtype : "",
 							  replyDomain ? replyDomain : "");
 
-			if (kDNSServiceErr_NoError == DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype,
-					replyDomain, _mdns_service_resolve_callback, args)) {
+			resErrorCode = DNSServiceResolve(&resolver_sr, 0, 0, serviceName, regtype,
+					replyDomain, _mdns_service_resolve_callback, args);
+			if (resErrorCode == kDNSServiceErr_NoError) {
 				GSList *tmp = pending_buddies;
 				PurpleBuddy *pb;
 				BonjourBuddy* bb = NULL;
 				Win32SvcResolverData *rd;
 				Win32BuddyImplData *idata;
-				gint fd;
 
 				/* Is there an existing buddy? */
 				if ((pb = purple_find_buddy(account, serviceName)))
@@ -344,7 +361,6 @@
 						pb->proto_data = bb;
 				}
 
-
 				rd = g_new0(Win32SvcResolverData, 1);
 				rd->if_idx = interfaceIndex;
 				rd->name = g_strdup(serviceName);
@@ -358,11 +374,14 @@
 				args->res_data = rd;
 				args->account = account;
 
+				args->resolver_query = g_new(DnsSDServiceRefHandlerData, 1);
+				args->resolver_query->sdRef = resolver_sr;
+				args->resolver_query->account = account;
 				/* get a file descriptor for this service ref, and add it to the input list */
-				fd = DNSServiceRefSockFD(args->resolver);
-				args->resolver_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver);
+				args->resolver_query->input_handler = purple_input_add(DNSServiceRefSockFD(resolver_sr),
+					PURPLE_INPUT_READ, _mdns_handle_event, args->resolver_query);
 			} else {
-				purple_debug_error("bonjour", "service browser - failed to resolve service.\n");
+				purple_debug_error("bonjour", "service browser - failed to resolve service. (%d)\n", resErrorCode);
 				g_free(args);
 			}
 		}
@@ -432,7 +451,7 @@
 gboolean _mdns_publish(BonjourDnsSd *data, PublishType type, GSList *records) {
 	TXTRecordRef dns_data;
 	gboolean ret = TRUE;
-	DNSServiceErrorType set_ret = kDNSServiceErr_NoError;
+	DNSServiceErrorType errorCode = kDNSServiceErr_NoError;
 	Win32SessionImplData *idata = data->mdns_impl_data;
 
 	g_return_val_if_fail(idata != NULL, FALSE);
@@ -441,44 +460,46 @@
 
 	while (records) {
 		PurpleKeyValuePair *kvp = records->data;
-		set_ret = TXTRecordSetValue(&dns_data, kvp->key, strlen(kvp->value), kvp->value);
-		if (set_ret != kDNSServiceErr_NoError)
+		errorCode = TXTRecordSetValue(&dns_data, kvp->key, strlen(kvp->value), kvp->value);
+		if (errorCode != kDNSServiceErr_NoError)
 			break;
 		records = records->next;
 	}
 
-	if (set_ret != kDNSServiceErr_NoError) {
-		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+	if (errorCode != kDNSServiceErr_NoError) {
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.(%d)\n", errorCode);
 		ret = FALSE;
 	} else {
-		DNSServiceErrorType err = kDNSServiceErr_NoError;
-
 		/* OK, we're done constructing the text record, (re)publish the service */
+		DNSServiceRef presence_sr;
 
 		switch (type) {
 			case PUBLISH_START:
 				purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj);
-				err = DNSServiceRegister(&idata->presence_svc, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
+				errorCode = DNSServiceRegister(&presence_sr, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
 					NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data),
 					_mdns_service_register_callback, NULL);
 				break;
 
 			case PUBLISH_UPDATE:
 				purple_debug_info("bonjour", "Updating presence.\n");
-				err = DNSServiceUpdateRecord(idata->presence_svc, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
+				errorCode = DNSServiceUpdateRecord(idata->presence_query->sdRef, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
 				break;
 		}
 
-		if (err != kDNSServiceErr_NoError) {
-			purple_debug_error("bonjour", "Failed to publish presence service.\n");
+		if (errorCode != kDNSServiceErr_NoError) {
+			purple_debug_error("bonjour", "Failed to publish presence service.(%d)\n", errorCode);
 			ret = FALSE;
 		} else if (type == PUBLISH_START) {
 			/* We need to do this because according to the Apple docs:
 			 * "the client is responsible for ensuring that DNSServiceProcessResult() is called
 			 * whenever there is a reply from the daemon - the daemon may terminate its connection
 			 * with a client that does not process the daemon's responses */
-			idata->presence_handler = purple_input_add(DNSServiceRefSockFD(idata->presence_svc),
-				PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_svc);
+			idata->presence_query = g_new(DnsSDServiceRefHandlerData, 1);
+			idata->presence_query->sdRef = presence_sr;
+			idata->presence_query->account = data->account;
+			idata->presence_query->input_handler = purple_input_add(DNSServiceRefSockFD(presence_sr),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->presence_query);
 		}
 	}
 
@@ -488,17 +509,24 @@
 }
 
 gboolean _mdns_browse(BonjourDnsSd *data) {
+	DNSServiceErrorType errorCode;
 	Win32SessionImplData *idata = data->mdns_impl_data;
+	DNSServiceRef browser_sr;
 
 	g_return_val_if_fail(idata != NULL, FALSE);
 
-	if (DNSServiceBrowse(&idata->browser_svc, 0, 0, ICHAT_SERVICE, NULL,
-				 _mdns_service_browse_callback, data->account)
-			== kDNSServiceErr_NoError) {
-		idata->browser_handler = purple_input_add(DNSServiceRefSockFD(idata->browser_svc),
-			PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_svc);
+	errorCode = DNSServiceBrowse(&browser_sr, 0, 0, ICHAT_SERVICE, NULL,
+		_mdns_service_browse_callback, data->account);
+	if (errorCode == kDNSServiceErr_NoError) {
+		idata->browser_query = g_new(DnsSDServiceRefHandlerData, 1);
+		idata->browser_query->sdRef = browser_sr;
+		idata->browser_query->account = data->account;
+		idata->browser_query->input_handler = purple_input_add(DNSServiceRefSockFD(browser_sr),
+			PURPLE_INPUT_READ, _mdns_handle_event, idata->browser_query);
 		return TRUE;
-	}
+	} else
+		purple_debug_error("bonjour", "Error registering Local Link presence browser. (%d)\n", errorCode);
+
 
 	return FALSE;
 }
@@ -509,14 +537,16 @@
 	if (idata == NULL)
 		return;
 
-	if (idata->presence_svc != NULL) {
-		purple_input_remove(idata->presence_handler);
-		DNSServiceRefDeallocate(idata->presence_svc);
+	if (idata->presence_query != NULL) {
+		purple_input_remove(idata->presence_query->input_handler);
+		DNSServiceRefDeallocate(idata->presence_query->sdRef);
+		g_free(idata->presence_query);
 	}
 
-	if (idata->browser_svc != NULL) {
-		purple_input_remove(idata->browser_handler);
-		DNSServiceRefDeallocate(idata->browser_svc);
+	if (idata->browser_query != NULL) {
+		purple_input_remove(idata->browser_query->input_handler);
+		DNSServiceRefDeallocate(idata->browser_query->sdRef);
+		g_free(idata->browser_query);
 	}
 
 	g_free(idata);
@@ -526,28 +556,30 @@
 
 gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data, gsize avatar_len) {
 	Win32SessionImplData *idata = data->mdns_impl_data;
-	DNSServiceErrorType err = kDNSServiceErr_NoError;
+	DNSServiceErrorType errorCode = kDNSServiceErr_NoError;
 
 	g_return_val_if_fail(idata != NULL, FALSE);
 
 	if (avatar_data != NULL && idata->buddy_icon_rec == NULL) {
 		purple_debug_info("bonjour", "Setting new buddy icon.\n");
-		err = DNSServiceAddRecord(idata->presence_svc, &idata->buddy_icon_rec,
+		errorCode = DNSServiceAddRecord(idata->presence_query->sdRef, &idata->buddy_icon_rec,
 			0, kDNSServiceType_NULL, avatar_len, avatar_data, 0);
 	} else if (avatar_data != NULL) {
 		purple_debug_info("bonjour", "Updating existing buddy icon.\n");
-		err = DNSServiceUpdateRecord(idata->presence_svc, idata->buddy_icon_rec,
+		errorCode = DNSServiceUpdateRecord(idata->presence_query->sdRef, idata->buddy_icon_rec,
 			0, avatar_len, avatar_data, 0);
 	} else if (idata->buddy_icon_rec != NULL) {
 		purple_debug_info("bonjour", "Removing existing buddy icon.\n");
-		DNSServiceRemoveRecord(idata->presence_svc, idata->buddy_icon_rec, 0);
+		errorCode = DNSServiceRemoveRecord(idata->presence_query->sdRef, idata->buddy_icon_rec, 0);
 		idata->buddy_icon_rec = NULL;
 	}
 
-	if (err != kDNSServiceErr_NoError)
-		purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", err);
+	if (errorCode != kDNSServiceErr_NoError) {
+		purple_debug_error("bonjour", "Error (%d) setting buddy icon record.\n", errorCode);
+		return FALSE;
+	}
 
-	return (err == kDNSServiceErr_NoError);
+	return TRUE;
 }
 
 void _mdns_init_buddy(BonjourBuddy *buddy) {
@@ -566,8 +598,9 @@
 	}
 
 	if (idata->null_query != NULL) {
-		purple_input_remove(idata->null_query_handler);
-		DNSServiceRefDeallocate(idata->null_query);
+		purple_input_remove(idata->null_query->input_handler);
+		DNSServiceRefDeallocate(idata->null_query->sdRef);
+		g_free(idata->null_query);
 	}
 
 	g_free(idata);
@@ -583,17 +616,30 @@
 
 	/* Cancel any existing query */
 	if (idata->null_query != NULL) {
-		purple_input_remove(idata->null_query_handler);
-		idata->null_query_handler = 0;
-		DNSServiceRefDeallocate(idata->null_query);
+		purple_input_remove(idata->null_query->input_handler);
+		DNSServiceRefDeallocate(idata->null_query->sdRef);
+		g_free(idata->null_query);
 		idata->null_query = NULL;
 	}
 
-	DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local");
-	if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, kDNSServiceInterfaceIndexAny, svc_name,
-			kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy)) {
-		idata->null_query_handler = purple_input_add(DNSServiceRefSockFD(idata->null_query),
-			PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
+	if (DNSServiceConstructFullName(svc_name, buddy->name, ICHAT_SERVICE, "local") != 0)
+		purple_debug_error("bonjour", "Unable to construct full name to retrieve buddy icon for %s.\n", buddy->name);
+	else {
+		DNSServiceRef null_query_sr;
+
+		DNSServiceErrorType errorCode = DNSServiceQueryRecord(&null_query_sr, 0, kDNSServiceInterfaceIndexAny,
+			svc_name, kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_record_query_callback, buddy);
+
+		if (errorCode == kDNSServiceErr_NoError) {
+			idata->null_query = g_new(DnsSDServiceRefHandlerData, 1);
+
+			idata->null_query->sdRef = null_query_sr;
+			idata->null_query->account = buddy->account;
+
+			idata->null_query->input_handler = purple_input_add(DNSServiceRefSockFD(null_query_sr),
+				PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query);
+		} else
+			purple_debug_error("bonjour", "Unable to query buddy icon record for %s. (%d)\n", buddy->name, errorCode);
 	}
 
 }
--- a/libpurple/protocols/bonjour/parser.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/bonjour/parser.c	Tue Jan 08 13:17:59 2008 +0000
@@ -39,7 +39,7 @@
 	for(i=0; i < nb_attributes * 5; i+=5) {
 		if(!xmlStrcmp(attributes[i], (xmlChar*) "from")) {
 			int len = attributes[i+4] - attributes[i+3];
-			bconv->buddy_name = g_strndup(attributes[i+3], len);
+			bconv->buddy_name = g_strndup((char *)attributes[i+3], len);
 			bonjour_jabber_conv_match_by_name(bconv);
 
 			return (bconv->pb != NULL);
--- a/libpurple/protocols/irc/cmds.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/irc/cmds.c	Tue Jan 08 13:17:59 2008 +0000
@@ -367,7 +367,12 @@
 		if (!end)
 			end = cur + strlen(cur);
 		msg = g_strndup(cur, end - cur);
-		buf = irc_format(irc, "vt:", "PRIVMSG", args[0], msg);
+
+		if(!strcmp(cmd, "msg"))
+			buf = irc_format(irc, "vt:", "PRIVMSG", args[0], msg);
+		else /* seding a notice if we get here */
+			buf = irc_format(irc, "vt:", "NOTICE", args[0], msg);
+
 		irc_send(irc, buf);
 		g_free(msg);
 		g_free(buf);
--- a/libpurple/protocols/irc/parse.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/irc/parse.c	Tue Jan 08 13:17:59 2008 +0000
@@ -136,6 +136,7 @@
 	{ "names", "c", irc_cmd_names, N_("names [channel]:  List the users currently in a channel.") },
 	{ "nick", "n", irc_cmd_nick, N_("nick &lt;new nickname&gt;:  Change your nickname.") },
 	{ "nickserv", ":", irc_cmd_service, N_("nickserv: Send a command to nickserv") },
+	{ "notice", "t:", irc_cmd_privmsg, N_("notice &lt;target&lt;:  Send a notice to a user or channel.") },
 	{ "op", ":", irc_cmd_op, N_("op &lt;nick1&gt; [nick2] ...:  Grant channel operator status to someone. You must be a channel operator to do this.") },
 	{ "operwall", ":", irc_cmd_wallops, N_("operwall &lt;message&gt;:  If you don't know what this is, you probably can't use it.") },
 	{ "operserv", ":", irc_cmd_service, N_("operserv: Send a command to operserv") },
--- a/libpurple/protocols/jabber/jabber.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Tue Jan 08 13:17:59 2008 +0000
@@ -391,25 +391,28 @@
 static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer timeout) 
 {
 	purple_timeout_remove(GPOINTER_TO_INT(timeout));
+	js->keepalive_timeout = -1;
 }
 
 static gboolean jabber_pong_timeout(PurpleConnection *gc)
 {
+	JabberStream *js = gc->proto_data;
 	purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
 					_("Ping timeout"));
+	js->keepalive_timeout = -1;
 	return FALSE;
 }
 
 void jabber_keepalive(PurpleConnection *gc)
 {
-	JabberIq *iq = jabber_iq_new(gc->proto_data, JABBER_IQ_GET);
-	guint timeout;
+	JabberStream *js = gc->proto_data;
+	JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET);
 
-        xmlnode *ping = xmlnode_new_child(iq->node, "ping");
-        xmlnode_set_namespace(ping, "urn:xmpp:ping");
+	xmlnode *ping = xmlnode_new_child(iq->node, "ping");
+	xmlnode_set_namespace(ping, "urn:xmpp:ping");
 
-	timeout = purple_timeout_add_seconds(20, (GSourceFunc)(jabber_pong_timeout), gc);
-        jabber_iq_set_callback(iq, jabber_pong_cb, GINT_TO_POINTER(timeout));
+	js->keepalive_timeout = purple_timeout_add_seconds(20, (GSourceFunc)(jabber_pong_timeout), gc);
+	jabber_iq_set_callback(iq, jabber_pong_cb, GINT_TO_POINTER(js->keepalive_timeout));
 	jabber_iq_send(iq);
 }
 
@@ -556,13 +559,12 @@
 	purple_input_remove(js->gc->inpa);
 	js->gc->inpa = 0;
 	js->gsc = purple_ssl_connect_with_host_fd(js->gc->account, js->fd,
-			jabber_login_callback_ssl, jabber_ssl_connect_failure, js->host, js->gc);
+			jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
 }
 
 static void jabber_login_connect(JabberStream *js, const char *fqdn, const char *host, int port)
 {
 	js->serverFQDN = g_strdup(fqdn);
-	js->host = g_strdup(host);
 
 	if (purple_proxy_connect(js->gc, js->gc->account, host,
 			port, jabber_login_callback, js->gc) == NULL)
@@ -611,7 +613,9 @@
 	js->user = jabber_id_new(purple_account_get_username(account));
 	js->next_id = g_random_int();
 	js->write_buffer = purple_circ_buffer_new(512);
-	js->old_length = -1;
+	js->old_length = 0;
+	js->keepalive_timeout = -1;
+	js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
 
 	if(!js->user) {
 		purple_connection_error_reason (gc,
@@ -649,7 +653,7 @@
 	if(purple_account_get_bool(js->gc->account, "old_ssl", FALSE)) {
 		if(purple_ssl_is_supported()) {
 			js->gsc = purple_ssl_connect(js->gc->account,
-					connect_server[0] ? connect_server : js->user->domain,
+					js->certificate_CN,
 					purple_account_get_int(account, "port", 5223), jabber_login_callback_ssl,
 					jabber_ssl_connect_failure, js->gc);
 		} else {
@@ -1096,7 +1100,7 @@
 			g_free, g_free);
 	js->user = jabber_id_new(purple_account_get_username(account));
 	js->next_id = g_random_int();
-	js->old_length = -1;
+	js->old_length = 0;
 
 	if(!js->user) {
 		purple_connection_error_reason (gc,
@@ -1124,6 +1128,7 @@
 		my_jb->subscription |= JABBER_SUB_BOTH;
 
 	server = connect_server[0] ? connect_server : js->user->domain;
+	js->certificate_CN = g_strdup(server);
 
 	jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
 
@@ -1300,7 +1305,7 @@
 		js->commands = g_list_delete_link(js->commands, js->commands);
 	}
 	g_free(js->server_name);
-	g_free(js->host);
+	g_free(js->certificate_CN);
 	g_free(js->gmail_last_time);
 	g_free(js->gmail_last_tid);
 	g_free(js->old_msg);
@@ -1311,6 +1316,9 @@
 	g_free(js->old_uri);
 	g_free(js->old_track);
 
+	if (js->keepalive_timeout != -1)
+		purple_timeout_remove(js->keepalive_timeout);
+	
 	g_free(js);
 
 	gc->proto_data = NULL;
@@ -1516,10 +1524,16 @@
 				} else
 					purple_notify_user_info_add_pair(user_info, _("Mood"), mood);
 			}
-			if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {	
+			if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
 				PurpleStatus *tune = purple_presence_get_status(presence, "tune");
 				const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
-				purple_notify_user_info_add_pair(user_info, _("Current media"), title);
+				const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
+				const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
+				char *playing = purple_util_format_song_info(title, artist, album, NULL);
+				if (playing) {
+					purple_notify_user_info_add_pair(user_info, _("Now Listening"), playing);
+					g_free(playing);
+				}
 			}
 		}
 
--- a/libpurple/protocols/jabber/jabber.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Tue Jan 08 13:17:59 2008 +0000
@@ -192,7 +192,10 @@
 	int old_length;
 	char *old_track;
 	
-	char *host;
+	char *certificate_CN;
+	
+	/* A purple timeout tag for the keepalive */
+	int keepalive_timeout;
 };
 
 typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *shortname, const gchar *namespace);
--- a/libpurple/protocols/jabber/usertune.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/jabber/usertune.c	Tue Jan 08 13:17:59 2008 +0000
@@ -35,11 +35,12 @@
 	xmlnode *tuneinfo, *tune;
 	PurpleJabberTuneInfo tuneinfodata;
 	JabberBuddyResource *resource;
-	
+	gboolean valid = FALSE;
+
 	/* ignore the tune of people not on our buddy list */
 	if (!buddy || !item)
 		return;
-	
+
 	tuneinfodata.artist = NULL;
 	tuneinfodata.title = NULL;
 	tuneinfodata.album = NULL;
@@ -58,36 +59,47 @@
 			if (!strcmp(tuneinfo->name, "artist")) {
 				if (tuneinfodata.artist == NULL) /* only pick the first one */
 					tuneinfodata.artist = xmlnode_get_data(tuneinfo);
+				valid = TRUE;
 			} else if (!strcmp(tuneinfo->name, "length")) {
 				if (tuneinfodata.time == -1) {
 					char *length = xmlnode_get_data(tuneinfo);
 					if (length)
 						tuneinfodata.time = strtol(length, NULL, 10);
 					g_free(length);
+					if (tuneinfodata.time > 0)
+						valid = TRUE;
 				}
 			} else if (!strcmp(tuneinfo->name, "source")) {
 				if (tuneinfodata.album == NULL) /* only pick the first one */
 					tuneinfodata.album = xmlnode_get_data(tuneinfo);
+				valid = TRUE;
 			} else if (!strcmp(tuneinfo->name, "title")) {
 				if (tuneinfodata.title == NULL) /* only pick the first one */
 					tuneinfodata.title = xmlnode_get_data(tuneinfo);
+				valid = TRUE;
 			} else if (!strcmp(tuneinfo->name, "track")) {
 				if (tuneinfodata.track == NULL) /* only pick the first one */
 					tuneinfodata.track = xmlnode_get_data(tuneinfo);
+				valid = TRUE;
 			} else if (!strcmp(tuneinfo->name, "uri")) {
 				if (tuneinfodata.url == NULL) /* only pick the first one */
 					tuneinfodata.url = xmlnode_get_data(tuneinfo);
+				valid = TRUE;
 			}
 		}
 	}
 
-	purple_prpl_got_user_status(js->gc->account, from, "tune",
-			PURPLE_TUNE_ARTIST, tuneinfodata.artist,
-			PURPLE_TUNE_TITLE, tuneinfodata.title,
-			PURPLE_TUNE_ALBUM, tuneinfodata.album,
-			PURPLE_TUNE_TRACK, tuneinfodata.track,
-			PURPLE_TUNE_TIME, tuneinfodata.time,
-			PURPLE_TUNE_URL, tuneinfodata.url, NULL);
+	if (valid) {
+		purple_prpl_got_user_status(js->gc->account, from, "tune",
+				PURPLE_TUNE_ARTIST, tuneinfodata.artist,
+				PURPLE_TUNE_TITLE, tuneinfodata.title,
+				PURPLE_TUNE_ALBUM, tuneinfodata.album,
+				PURPLE_TUNE_TRACK, tuneinfodata.track,
+				PURPLE_TUNE_TIME, tuneinfodata.time,
+				PURPLE_TUNE_URL, tuneinfodata.url, NULL);
+	} else {
+		purple_prpl_got_user_status_deactive(js->gc->account, from, "tune");
+	}
 
 	g_free(tuneinfodata.artist);
 	g_free(tuneinfodata.title);
@@ -119,7 +131,7 @@
 			xmlnode_insert_data(xmlnode_new_child(tunenode, "source"),tuneinfo->album,-1);
 		if(tuneinfo->url && tuneinfo->url[0] != '\0')
 			xmlnode_insert_data(xmlnode_new_child(tunenode, "uri"),tuneinfo->url,-1);
-		if(tuneinfo->time >= 0) {
+		if(tuneinfo->time > 0) {
 			char *length = g_strdup_printf("%d", tuneinfo->time);
 			xmlnode_insert_data(xmlnode_new_child(tunenode, "length"),length,-1);
 			g_free(length);
--- a/libpurple/protocols/msn/msn.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Tue Jan 08 13:17:59 2008 +0000
@@ -461,7 +461,7 @@
 	msn_switchboard_request_add_user(swboard, buddy->name);
 
 	/* TODO: This might move somewhere else, after USR might be */
-	swboard->chat_id = session->conv_seq++;
+	swboard->chat_id = msn_switchboard_get_chat_id();
 	swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
 	swboard->flag = MSN_SB_FLAG_IM;
 
@@ -593,8 +593,8 @@
 			PurpleStatus *tune = purple_presence_get_status(presence, "tune");
 			const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
 			const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
-			currentmedia = g_strdup_printf("%s%s%s", title, artist ? " - " : "",
-					artist ? artist : "");
+			const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
+			currentmedia = purple_util_format_song_info(title, artist, album, NULL);
 			/* We could probably just use user->media.title etc. here */
 		}
 
@@ -643,9 +643,7 @@
 		}
 
 		if (currentmedia) {
-			tmp = g_markup_escape_text(currentmedia, -1);
-			purple_notify_user_info_add_pair(user_info, _("Current media"), tmp);
-			g_free(tmp);
+			purple_notify_user_info_add_pair(user_info, _("Now Listening"), currentmedia);
 			g_free(currentmedia);
 		}
 	}
--- a/libpurple/protocols/msn/session.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msn/session.c	Tue Jan 08 13:17:59 2008 +0000
@@ -48,7 +48,6 @@
 	/*if you want to chat with Yahoo Messenger*/
 	//session->protocol_ver = WLM_YAHOO_PROT_VER;
 	session->protocol_ver = WLM_PROT_VER;
-	session->conv_seq = 1;
 
 	return session;
 }
--- a/libpurple/protocols/msn/session.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msn/session.h	Tue Jan 08 13:17:59 2008 +0000
@@ -107,8 +107,6 @@
 	GList *directconns; /**< The list of all the directconnections. */
 	GList *slplinks; /**< The list of all the slplinks. */
 
-	int conv_seq; /**< The current conversation sequence number. */
-
 	/*psm info*/
 	char *psm;
 
--- a/libpurple/protocols/msn/switchboard.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Tue Jan 08 13:17:59 2008 +0000
@@ -164,6 +164,14 @@
 	return swboard->session_id;
 }
 
+int
+msn_switchboard_get_chat_id(void)
+{
+	static int chat_id = 1;
+
+	return chat_id++;
+}
+
 void
 msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited)
 {
@@ -250,7 +258,7 @@
 				purple_conversation_destroy(swboard->conv);
 #endif
 
-			swboard->chat_id = cmdproc->session->conv_seq++;
+			swboard->chat_id = msn_switchboard_get_chat_id();
 			swboard->flag |= MSN_SB_FLAG_IM;
 			swboard->conv = serv_got_joined_chat(account->gc,
 												 swboard->chat_id,
--- a/libpurple/protocols/msn/switchboard.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msn/switchboard.h	Tue Jan 08 13:17:59 2008 +0000
@@ -167,6 +167,13 @@
 const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard);
 
 /**
+ * Returns the next chat ID for use by a switchboard.
+ *
+ * @return The chat ID.
+ */
+int msn_switchboard_get_chat_id(void);
+
+/**
  * Sets whether or not we were invited to this switchboard.
  *
  * @param swboard The switchboard.
--- a/libpurple/protocols/msnp9/msn.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msnp9/msn.c	Tue Jan 08 13:17:59 2008 +0000
@@ -435,7 +435,7 @@
 	msn_switchboard_request_add_user(swboard, buddy->name);
 
 	/* TODO: This might move somewhere else, after USR might be */
-	swboard->chat_id = session->conv_seq++;
+	swboard->chat_id = msn_switchboard_get_chat_id();
 	swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
 	swboard->flag = MSN_SB_FLAG_IM;
 
--- a/libpurple/protocols/msnp9/session.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msnp9/session.c	Tue Jan 08 13:17:59 2008 +0000
@@ -44,7 +44,6 @@
 								 purple_account_get_username(account), NULL);
 
 	session->protocol_ver = 9;
-	session->conv_seq = 1;
 
 	return session;
 }
--- a/libpurple/protocols/msnp9/session.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msnp9/session.h	Tue Jan 08 13:17:59 2008 +0000
@@ -103,8 +103,6 @@
 	GList *directconns; /**< The list of all the directconnections. */
 	GList *slplinks; /**< The list of all the slplinks. */
 
-	int conv_seq; /**< The current conversation sequence number. */
-
 	struct
 	{
 		char *kv;
--- a/libpurple/protocols/msnp9/slpcall.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msnp9/slpcall.c	Tue Jan 08 13:17:59 2008 +0000
@@ -34,7 +34,7 @@
  **************************************************************************/
 
 static char *
-rand_guid()
+rand_guid(void)
 {
 	return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
 			rand() % 0xAAFF + 0x1111,
--- a/libpurple/protocols/msnp9/switchboard.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msnp9/switchboard.c	Tue Jan 08 13:17:59 2008 +0000
@@ -166,6 +166,14 @@
 	return swboard->session_id;
 }
 
+int
+msn_switchboard_get_chat_id(void)
+{
+	static int chat_id = 1;
+
+	return chat_id++;
+}
+
 void
 msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited)
 {
@@ -252,7 +260,7 @@
 				purple_conversation_destroy(swboard->conv);
 #endif
 
-			swboard->chat_id = cmdproc->session->conv_seq++;
+			swboard->chat_id = msn_switchboard_get_chat_id();
 			swboard->flag |= MSN_SB_FLAG_IM;
 			swboard->conv = serv_got_joined_chat(account->gc,
 												 swboard->chat_id,
--- a/libpurple/protocols/msnp9/switchboard.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/msnp9/switchboard.h	Tue Jan 08 13:17:59 2008 +0000
@@ -167,6 +167,13 @@
 const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard);
 
 /**
+ * Returns the next chat ID for use by a switchboard.
+ *
+ * @return The chat ID.
+ */
+int msn_switchboard_get_chat_id(void);
+
+/**
  * Sets whether or not we were invited to this switchboard.
  *
  * @param swboard The switchboard.
--- a/libpurple/protocols/myspace/myspace.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Tue Jan 08 13:17:59 2008 +0000
@@ -2912,8 +2912,7 @@
 	menu = g_list_append(menu, act);
 #endif
 
-	act = purple_plugin_action_new(g_strdup_printf("%s",
-				_("Add friends from MySpace.com")), msim_import_friends);
+	act = purple_plugin_action_new(_("Add friends from MySpace.com"), msim_import_friends);
 	menu = g_list_append(menu, act);
 
 	return menu;
--- a/libpurple/protocols/novell/novell.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/novell/novell.c	Tue Jan 08 13:17:59 2008 +0000
@@ -1029,7 +1029,7 @@
  ******************************************************************************/
 
 static char *
-_user_agent_string()
+_user_agent_string(void)
 {
 
 #if !defined(_WIN32)
--- a/libpurple/protocols/oscar/family_auth.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/family_auth.c	Tue Jan 08 13:17:59 2008 +0000
@@ -196,6 +196,10 @@
  *   unknown= 0x0000008b
  *   serverstore = 0x01
  *
+ * @param truncate_pass Truncate the password to 8 characters.  This
+ *        usually happens for AOL accounts.  We are told that we
+ *        should truncate it if the 0x0017/0x0007 SNAC contains
+ *        a TLV of type 0x0026 with data 0x0000.
  */
 int
 aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key)
@@ -522,8 +526,8 @@
 
 	/*
 	 * If the truncate_pass TLV exists then we should truncate the
-	 * user's password to 8 characters.  This flag is sent when you
-	 * try to log in with an AOL user's screen name.
+	 * user's password to 8 characters.  This flag is sent to us
+	 * when logging in with an AOL user's screen name.
 	 */
 	truncate_pass = aim_tlv_gettlv(tlvlist, 0x0026, 1) != NULL;
 
--- a/libpurple/protocols/oscar/family_icbm.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Tue Jan 08 13:17:59 2008 +0000
@@ -51,6 +51,9 @@
 #include "win32dep.h"
 #endif
 
+#include "util.h"
+
+
 /**
  * Add a standard ICBM header to the given bstream with the given
  * information.
@@ -2335,11 +2338,166 @@
 	sn = byte_stream_getstr(bs, snlen);
 	reason = byte_stream_get16(bs);
 
-	if (channel == 0x0002) { /* File transfer declined */
+	if (channel == 0x0002)
+	{
+		/* parse status note text */
+
+		struct aim_icq_info *info = NULL;
+		struct aim_icq_info *prev_info = NULL;
+		char *response = NULL;
+		char *encoding = NULL;
+		char *stripped_encoding = NULL;
+		char *status_note_text = NULL;
+		char *stripped_status_note_text = NULL;
+		char *status_note = NULL;
+
+		/*
+		 * TODO: Using a while statement here is kind of an ugly hack
+		 *       to be able to use 'break'.  We might as well be using
+		 *       'goto'.  Should probably get rid of this.
+		 */
+		while (reason == 0x0003) /* channel-specific */
+		{
+			guint32 length;
+			guint16 version;
+			guint32 capability;
+			guint8 message_type;
+			guint16 status_code;
+			guint16 text_length;
+			guint32 request_length;
+			guint32 response_length;
+			guint32 encoding_length;
+			PurpleAccount *account;
+			PurpleBuddy *buddy;
+			PurplePresence *presence;
+			PurpleStatus *status;
+
+			for (info = od->icq_info; info != NULL; info = info->next)
+			{
+				if (memcmp(&info->icbm_cookie, cookie, 8) == 0)
+				{
+					if (prev_info == NULL)
+						od->icq_info = info->next;
+					else
+						prev_info->next = info->next;
+
+					break;
+				}
+
+				prev_info = info;
+			}
+
+			if (info == NULL)
+				break;
+
+			if ((length = byte_stream_getle16(bs)) != 27)
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 27, received %u.\n", length);
+				break;
+			}
+			if ((version = byte_stream_getle16(bs)) != 9)
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect version; expected 9, received %u.\n", version);
+				break;
+			}
+			capability = aim_locate_getcaps(od, bs, 0x10);
+			if (capability != OSCAR_CAPABILITY_EMPTY)
+			{
+				purple_debug_misc("oscar", "clientautoresp: plugin ID is not null.\n");
+				break;
+			}
+			byte_stream_advance(bs, 2); /* unknown */
+			byte_stream_advance(bs, 4); /* client capabilities flags */
+			byte_stream_advance(bs, 1); /* unknown */
+			byte_stream_advance(bs, 2); /* downcouner? */
+
+			if ((length = byte_stream_getle16(bs)) != 14)
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect header size; expected 14, received %u.\n", length);
+				break;
+			}
+			byte_stream_advance(bs, 2); /* downcounter? */
+			byte_stream_advance(bs, 12); /* unknown */
+
+			if ((message_type = byte_stream_get8(bs)) != 0x1a)
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect message type; expected 0x1a, received 0x%x.\n", message_type);
+				break;
+			}
+			byte_stream_advance(bs, 1); /* message flags */
+			if ((status_code = byte_stream_getle16(bs)) != 0)
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect status code; expected 0, received %u.\n", status_code);
+				break;
+			}
+			byte_stream_advance(bs, 2); /* priority code */
+
+			text_length = byte_stream_getle16(bs);
+			byte_stream_advance(bs, text_length); /* text */
+
+			length = byte_stream_getle16(bs);
+			byte_stream_advance(bs, 18); /* unknown */
+			if (length != 18 + 4 + (request_length = byte_stream_getle32(bs)) + 17)
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 18 + 4 + request_length + 17, length);
+				break;
+			}
+			byte_stream_advance(bs, request_length); /* x request */
+			byte_stream_advance(bs, 17); /* unknown */
+
+			length = byte_stream_getle32(bs);
+			response_length = byte_stream_getle32(bs);
+			response = byte_stream_getstr(bs, response_length);
+			if (length != 4 + response_length + 4 + (encoding_length = byte_stream_getle32(bs)))
+			{
+				purple_debug_misc("oscar", "clientautoresp: incorrect block; expected length is %u, got %u.\n", 4 + response_length + 4 + encoding_length, length);
+				break;
+			}
+			encoding = byte_stream_getstr(bs, encoding_length);
+
+			account = purple_connection_get_account(od->gc);
+			stripped_encoding = oscar_encoding_extract(encoding);
+			status_note_text = oscar_encoding_to_utf8(account, stripped_encoding, response, response_length);
+			stripped_status_note_text = purple_markup_strip_html(status_note_text);
+
+			if (stripped_status_note_text != NULL && stripped_status_note_text[0] != 0)
+				status_note = g_strdup_printf("%s: %s", info->status_note_title, stripped_status_note_text);
+			else
+				status_note = g_strdup(info->status_note_title);
+
+			buddy = purple_find_buddy(account, sn);
+			if (buddy == NULL)
+			{
+				purple_debug_misc("oscar", "clientautoresp: buddy %s was not found.\n", sn);
+				break;
+			}
+
+			purple_debug_misc("oscar", "clientautoresp: setting status message to \"%s\".\n", status_note);
+
+			presence = purple_buddy_get_presence(buddy);
+			status = purple_presence_get_active_status(presence);
+
+			purple_prpl_got_user_status(account, sn,
+					purple_status_get_id(status),
+					"message", status_note, NULL);
+
+			break;
+		}
+
+		g_free(status_note);
+		g_free(stripped_status_note_text);
+		g_free(status_note_text);
+		g_free(stripped_encoding);
+		g_free(encoding);
+		g_free(response);
+		g_free(info->status_note_title);
+		g_free(info);
+
 		byte_stream_get16(bs); /* Unknown */
 		byte_stream_get16(bs); /* Unknown */
 		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 			ret = userfunc(od, conn, frame, channel, sn, reason, cookie);
+
 	} else if (channel == 0x0004) { /* ICQ message */
 		switch (reason) {
 			case 0x0003: { /* ICQ status message.  Maybe other stuff too, you never know with these people. */
--- a/libpurple/protocols/oscar/family_icq.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/family_icq.c	Tue Jan 08 13:17:59 2008 +0000
@@ -435,6 +435,65 @@
 	return 0;
 }
 
+/*
+ * getstatusnote may be a misleading name because the response
+ * contains a lot of different information but currently it's only
+ * used to get that.
+ */
+int aim_icq_getstatusnote(OscarData *od, const char *uin, guint8 *note_hash, guint16 note_hash_len)
+{
+	FlapConnection *conn;
+	FlapFrame *frame;
+	aim_snacid_t snacid;
+	int bslen;
+
+	purple_debug_misc("oscar", "aim_icq_getstatusnote: requesting status note for %s.\n", uin);
+
+	if (!od || !(conn = flap_connection_findbygroup(od, 0x0015)))
+	{
+		purple_debug_misc("oscar", "aim_icq_getstatusnote: no connection.\n");
+		return -EINVAL;
+	}
+
+	bslen = 2 + 4 + 2 + 2 + 2 + 2 + 58 + strlen(uin);
+
+	frame = flap_frame_new(od, 0x02, 10 + 4 + bslen);
+
+	snacid = aim_cachesnac(od, 0x0015, 0x0002, 0x0000, NULL, 0);
+	aim_putsnac(&frame->data, 0x0015, 0x0002, 0x0000, snacid);
+
+	/* For simplicity, don't bother using a tlvlist */
+	byte_stream_put16(&frame->data, 0x0001);
+	byte_stream_put16(&frame->data, bslen);
+
+	byte_stream_putle16(&frame->data, bslen - 2);
+	byte_stream_putle32(&frame->data, atoi(od->sn));
+	byte_stream_putle16(&frame->data, 0x07d0); /* I command thee. */
+	byte_stream_putle16(&frame->data, snacid); /* eh. */
+	byte_stream_putle16(&frame->data, 0x0fa0); /* shrug. */
+	byte_stream_putle16(&frame->data, 58 + strlen(uin));
+
+	byte_stream_put32(&frame->data, 0x05b90002);    /* don't ask */
+	byte_stream_put32(&frame->data, 0x80000000);
+	byte_stream_put32(&frame->data, 0x00000006);
+	byte_stream_put32(&frame->data, 0x00010002);
+	byte_stream_put32(&frame->data, 0x00020000);
+	byte_stream_put32(&frame->data, 0x04e30000);
+	byte_stream_put32(&frame->data, 0x00020002);
+	byte_stream_put32(&frame->data, 0x00000001);
+
+	byte_stream_put16(&frame->data, 24 + strlen(uin));
+	byte_stream_put32(&frame->data, 0x003c0010);
+	byte_stream_putraw(&frame->data, note_hash, 16); /* status note hash */
+	byte_stream_put16(&frame->data, 0x0032);        /* buddy uin */
+	byte_stream_put16(&frame->data, strlen(uin));
+	byte_stream_putstr(&frame->data, uin);
+
+	flap_connection_send(conn, frame);
+
+	return 0;
+}
+
 static void aim_icq_freeinfo(struct aim_icq_info *info) {
 	int i;
 
@@ -467,6 +526,7 @@
 	g_free(info->workposition);
 	g_free(info->workwebpage);
 	g_free(info->info);
+	g_free(info->status_note_title);
 	g_free(info);
 }
 
@@ -641,6 +701,178 @@
 			info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
 			/* Then 0x00 02 00 00 00 00 00 */
 		} break;
+
+		/* status note title and send request for status note text */
+		case 0x0fb4: {
+			GSList *tlvlist;
+			aim_tlv_t *tlv;
+			FlapConnection *conn;
+			char *uin = NULL;
+			char *status_note_title = NULL;
+
+			conn = flap_connection_findbygroup(od, 0x0004);
+			if (conn == NULL)
+			{
+				purple_debug_misc("oscar", "icq/0x0fb4: flap connection was not found.\n");
+				break;
+			}
+
+			byte_stream_advance(&qbs, 0x02); /* length */
+			byte_stream_advance(&qbs, 0x2f); /* unknown stuff */
+
+			tlvlist = aim_tlvlist_read(&qbs);
+
+			tlv = aim_tlv_gettlv(tlvlist, 0x0032, 1);
+			if (tlv != NULL)
+				/* Get user number */
+				uin = aim_tlv_getvalue_as_string(tlv);
+
+			tlv = aim_tlv_gettlv(tlvlist, 0x0226, 1);
+			if (tlv != NULL)
+				/* Get status note title */
+				status_note_title = aim_tlv_getvalue_as_string(tlv);
+
+			aim_tlvlist_free(tlvlist);
+
+			if (uin == NULL || status_note_title == NULL)
+			{
+				purple_debug_misc("oscar", "icq/0x0fb4: uin or "
+						"status_note_title was not found\n");
+				g_free(uin);
+				g_free(status_note_title);
+				break;
+			}
+
+			if (status_note_title[0] == '\0')
+			{
+				PurpleAccount *account;
+				PurpleBuddy *buddy;
+				PurplePresence *presence;
+				PurpleStatus *status;
+
+				account = purple_connection_get_account(od->gc);
+				buddy = purple_find_buddy(account, uin);
+				presence = purple_buddy_get_presence(buddy);
+				status = purple_presence_get_active_status(presence);
+
+				purple_prpl_got_user_status(account, uin,
+						purple_status_get_id(status),
+						"message", NULL, NULL);
+
+				g_free(status_note_title);
+			}
+			else
+			{
+				struct aim_icq_info *info;
+				guint32 data_len;
+				FlapFrame *frame;
+				aim_snacid_t snacid;
+				guchar cookie[8];
+
+				info = g_new0(struct aim_icq_info, 1);
+
+				if (info == NULL)
+				{
+					g_free(uin);
+					g_free(status_note_title);
+
+					break;
+				}
+
+				data_len = 13 + strlen(uin) + 30 + 6 + 4 + 55 + 85 + 4;
+				frame = flap_frame_new(od, 0x0002, 10 + 4 + data_len);
+				snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+
+				aim_putsnac(&frame->data, 0x0004, 0x0006, 0x0000, snacid);
+
+				aim_icbm_makecookie(cookie);
+
+				byte_stream_putraw(&frame->data, cookie, 8); /* ICBM cookie */
+				byte_stream_put16(&frame->data, 0x0002); /* message channel */
+				byte_stream_put8(&frame->data, strlen(uin)); /* uin */
+				byte_stream_putstr(&frame->data, uin);
+
+				byte_stream_put16(&frame->data, 0x0005); /* rendez vous data */
+				byte_stream_put16(&frame->data, 0x00b2);
+				byte_stream_put16(&frame->data, 0x0000); /* request */
+				byte_stream_putraw(&frame->data, cookie, 8); /* ICBM cookie */
+				byte_stream_put32(&frame->data, 0x09461349); /* ICQ server relaying */
+				byte_stream_put16(&frame->data, 0x4c7f);
+				byte_stream_put16(&frame->data, 0x11d1);
+				byte_stream_put32(&frame->data, 0x82224445);
+				byte_stream_put32(&frame->data, 0x53540000);
+
+				byte_stream_put16(&frame->data, 0x000a); /* unknown TLV */
+				byte_stream_put16(&frame->data, 0x0002);
+				byte_stream_put16(&frame->data, 0x0001);
+
+				byte_stream_put16(&frame->data, 0x000f); /* unknown TLV */
+				byte_stream_put16(&frame->data, 0x0000);
+
+				byte_stream_put16(&frame->data, 0x2711); /* extended data */
+				byte_stream_put16(&frame->data, 0x008a);
+				byte_stream_putle16(&frame->data, 0x001b); /* length */
+				byte_stream_putle16(&frame->data, 0x0009); /* version */
+				byte_stream_putle32(&frame->data, 0x00000000); /* plugin: none */
+				byte_stream_putle32(&frame->data, 0x00000000);
+				byte_stream_putle32(&frame->data, 0x00000000);
+				byte_stream_putle32(&frame->data, 0x00000000);
+				byte_stream_putle16(&frame->data, 0x0000); /* unknown */
+				byte_stream_putle32(&frame->data, 0x00000000); /* client capabilities flags */
+				byte_stream_put8(&frame->data, 0x00); /* unknown */
+				byte_stream_putle16(&frame->data, 0x0064); /* downcounter? */
+				byte_stream_putle16(&frame->data, 0x000e); /* length */
+				byte_stream_putle16(&frame->data, 0x0064); /* downcounter? */
+				byte_stream_putle32(&frame->data, 0x00000000); /* unknown */
+				byte_stream_putle32(&frame->data, 0x00000000);
+				byte_stream_putle32(&frame->data, 0x00000000);
+				byte_stream_put8(&frame->data, 0x1a); /* message type: plugin message descibed by text string */
+				byte_stream_put8(&frame->data, 0x00); /* message flags */
+				byte_stream_putle16(&frame->data, 0x0000); /* status code */
+				byte_stream_putle16(&frame->data, 0x0001); /* priority code */
+				byte_stream_putle16(&frame->data, 0x0000); /* text length */
+
+				byte_stream_put8(&frame->data, 0x3a); /* message dump */
+				byte_stream_put32(&frame->data, 0x00811a18);
+				byte_stream_put32(&frame->data, 0xbc0e6c18);
+				byte_stream_put32(&frame->data, 0x47a5916f);
+				byte_stream_put32(&frame->data, 0x18dcc76f);
+				byte_stream_put32(&frame->data, 0x1a010013);
+				byte_stream_put32(&frame->data, 0x00000041);
+				byte_stream_put32(&frame->data, 0x77617920);
+				byte_stream_put32(&frame->data, 0x53746174);
+				byte_stream_put32(&frame->data, 0x7573204d);
+				byte_stream_put32(&frame->data, 0x65737361);
+				byte_stream_put32(&frame->data, 0x67650100);
+				byte_stream_put32(&frame->data, 0x00000000);
+				byte_stream_put32(&frame->data, 0x00000000);
+				byte_stream_put32(&frame->data, 0x00000000);
+				byte_stream_put32(&frame->data, 0x00000015);
+				byte_stream_put32(&frame->data, 0x00000000);
+				byte_stream_put32(&frame->data, 0x0000000d);
+				byte_stream_put32(&frame->data, 0x00000074);
+				byte_stream_put32(&frame->data, 0x6578742f);
+				byte_stream_put32(&frame->data, 0x782d616f);
+				byte_stream_put32(&frame->data, 0x6c727466);
+
+				byte_stream_put16(&frame->data, 0x0003); /* server ACK requested */
+				byte_stream_put16(&frame->data, 0x0000);
+
+				info->uin = atoi(uin);
+				info->status_note_title = status_note_title;
+
+				memcpy(&info->icbm_cookie, cookie, 8);
+
+				info->next = od->icq_info;
+				od->icq_info = info;
+
+				flap_connection_send(conn, frame);
+			}
+
+			g_free(uin);
+
+		} break;
+
 		} /* End switch statement */
 
 		if (!(snac->flags & 0x0001)) {
--- a/libpurple/protocols/oscar/family_locate.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Tue Jan 08 13:17:59 2008 +0000
@@ -320,10 +320,10 @@
 		cur->away_encoding = g_strdup(userinfo->away_encoding);
 		cur->away_len = userinfo->away_len;
 
-	} else if (!(userinfo->flags & AIM_FLAG_AWAY)) {
+	} else {
 		/*
-		 * We don't have an away message specified in this user_info block.
-		 * If the user is not away, clear any cached away message now.
+		 * We don't have an away message specified in this user_info
+		 * block, so clear any cached away message now.
 		 */
 		if (cur->away) {
 			g_free(cur->away);
@@ -347,41 +347,6 @@
 		userfunc(od, conn, NULL, cur);
 }
 
-void
-aim_locate_dorequest(OscarData *od)
-{
-	struct userinfo_node *cur = od->locate.torequest;
-
-	if (od->locate.waiting_for_response == TRUE)
-		return;
-
-	od->locate.waiting_for_response = TRUE;
-	aim_locate_getinfoshort(od, cur->sn, 0x00000003);
-
-	/* Move this node to the "requested" queue */
-	od->locate.torequest = cur->next;
-	cur->next = od->locate.requested;
-	od->locate.requested = cur;
-}
-
-static gboolean
-purple_reqinfo_timeout_cb(void *data)
-{
-	OscarData *od;
-
-	od = data;
-
-	if (od->locate.torequest == NULL)
-	{
-		od->getinfotimer = 0;
-		return FALSE;
-	}
-
-	aim_locate_dorequest(od);
-
-	return TRUE;
-}
-
 /**
  * Remove this screen name from our queue.  If this info was requested
  * by our info request queue, then pop the next element off of the queue.
@@ -417,19 +382,6 @@
 			cur = cur->next;
 	}
 
-	if (!was_explicit) {
-		od->locate.waiting_for_response = FALSE;
-
-		/*
-		 * Wait a little while then call aim_locate_dorequest(od).
-		 * This keeps us from hitting the rate limit due to
-		 * requesting away messages and info too quickly.
-		 */
-		if (od->getinfotimer == 0)
-			od->getinfotimer = purple_timeout_add(500,
-					purple_reqinfo_timeout_cb, od);
-	}
-
 	return was_explicit;
 }
 
@@ -438,22 +390,18 @@
 {
 	struct userinfo_node *cur;
 
-	/* Make sure we aren't already requesting info for this buddy */
-	cur = od->locate.torequest;
-	while (cur != NULL) {
+	/* Make sure we haven't already requested info for this buddy */
+	for (cur = od->locate.requested; cur != NULL; cur = cur->next)
 		if (aim_sncmp(sn, cur->sn) == 0)
 			return;
-		cur = cur->next;
-	}
 
 	/* Add a new node to our request queue */
 	cur = (struct userinfo_node *)g_malloc(sizeof(struct userinfo_node));
 	cur->sn = g_strdup(sn);
-	cur->next = od->locate.torequest;
-	od->locate.torequest = cur;
+	cur->next = od->locate.requested;
+	od->locate.requested = cur;
 
-	/* Actually request some info up in this piece */
-	aim_locate_dorequest(od);
+	aim_locate_getinfoshort(od, cur->sn, 0x00000003);
 }
 
 aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *sn) {
--- a/libpurple/protocols/oscar/oscar.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue Jan 08 13:17:59 2008 +0000
@@ -7,6 +7,7 @@
  * Some code copyright (C) 2001-2007, Mark Doliner <thekingant@users.sourceforge.net>
  * Some code copyright (C) 2005, Jonathan Clark <ardentlygnarly@users.sourceforge.net>
  * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) <foss@combots.com>
+ * Some code copyright (C) 2008, Aman Gupta
  *
  * Most libfaim code copyright (C) 1998-2001 Adam Fritzler <afritz@auk.cx>
  * Some libfaim code copyright (C) 2001-2004 Mark Doliner <thekingant@users.sourceforge.net>
@@ -1722,8 +1723,7 @@
 	int type = 0;
 	gboolean buddy_is_away = FALSE;
 	const char *status_id;
-	gboolean have_status_message = FALSE;
-	char *message = NULL;
+	char *itmsurl = NULL;
 	va_list ap;
 	aim_userinfo_t *info;
 
@@ -1771,20 +1771,10 @@
 			status_id = OSCAR_STATUS_ID_AVAILABLE;
 	}
 
-	/*
-	 * Handle the available message.  If info->status is NULL then the user
-	 * may or may not have an available message, so don't do anything.  If
-	 * info->status is set to the empty string, then the user's client DOES
-	 * support available messages and the user DOES NOT have one set.
-	 * Otherwise info->status contains the available message.
-	 */
-	if (info->status != NULL)
-	{
-		have_status_message = TRUE;
-		if (info->status[0] != '\0')
-			message = oscar_encoding_to_utf8(account, info->status_encoding,
-											 info->status, info->status_len);
-	}
+	if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len)
+		/* Grab the iTunes Music Store URL */
+		itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding,
+				info->itmsurl, info->itmsurl_len);
 
 	if (info->flags & AIM_FLAG_WIRELESS)
 	{
@@ -1793,38 +1783,27 @@
 		purple_prpl_got_user_status_deactive(account, info->sn, OSCAR_STATUS_ID_MOBILE);
 	}
 
-	if (have_status_message)
+	if (status_id == OSCAR_STATUS_ID_AVAILABLE)
 	{
-		if ((!strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE)) && (info->itmsurl != NULL))
-		{
-			char *itmsurl;
-			itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding,
-					info->itmsurl, info->itmsurl_len);
-			purple_prpl_got_user_status(account, info->sn, status_id,
-					"message", message, "itmsurl", itmsurl, NULL);
-			g_free(itmsurl);
-		}
-		else
-		{
-			purple_prpl_got_user_status(account, info->sn, status_id,
-					"message", message, NULL);
-		}
+		char *message = NULL;
+
+		if (info->status != NULL && info->status[0] != '\0')
+			/* Grab the available message */
+			message = oscar_encoding_to_utf8(account, info->status_encoding,
+					info->status, info->status_len);
+
+		purple_prpl_got_user_status(account, info->sn, status_id,
+				"message", message, "itmsurl", itmsurl, NULL);
+
 		g_free(message);
 	}
 	else
 	{
-		PurpleBuddy *b = purple_find_buddy(account, info->sn);
-		PurpleStatus *status = NULL;
-		const char *active_status_id = NULL;
-
-		if (b != NULL) {
-			status = purple_presence_get_active_status(purple_buddy_get_presence(b));
-			active_status_id = purple_status_get_id(status);
-		}
-
-		if (!active_status_id || strcmp(active_status_id, status_id))
-			purple_prpl_got_user_status(account, info->sn, status_id, NULL);
-	}
+		purple_prpl_got_user_status(account, info->sn, status_id,
+				"itmsurl", itmsurl, NULL);
+	}
+
+	g_free(itmsurl);
 
 	/* Login time stuff */
 	if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE)
@@ -1879,6 +1858,31 @@
 		g_free(b16);
 	}
 
+	/*
+	 * If we didn't receive a status message with the status change,
+	 * or if the message is empty, and we have a note hash, then
+	 * query the ICQ6 status note.
+	 *
+	 * TODO: We should probably always query the status note regardless
+	 *       of whether they have a status message set, and we should
+	 *       figure out a way to display both the status note and the
+	 *       status message at the same time.
+	 */
+	if (info->status == NULL || info->status[0] == '\0')
+	{
+		struct aim_ssi_item *ssi_item;
+		aim_tlv_t *note_hash;
+
+		ssi_item = aim_ssi_itemlist_finditem(od->ssi.local,
+				NULL, info->sn, AIM_SSI_TYPE_BUDDY);
+		if (ssi_item != NULL)
+		{
+			note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1);
+			if (note_hash != NULL)
+				aim_icq_getstatusnote(od, info->sn, note_hash->value, note_hash->length);
+		}
+	}
+
 	return 1;
 }
 
@@ -3000,7 +3004,7 @@
 
 	if (!aim_snvalid_icq(userinfo->sn))
 	{
-		if (strcmp(purple_buddy_get_name(b), userinfo->sn))
+		if (strcmp(purple_buddy_get_name(b), userinfo->sn) != 0)
 			serv_got_alias(gc, purple_buddy_get_name(b), userinfo->sn);
 		else
 			serv_got_alias(gc, purple_buddy_get_name(b), NULL);
@@ -3009,23 +3013,19 @@
 	presence = purple_buddy_get_presence(b);
 	status = purple_presence_get_active_status(presence);
 
-	if (!purple_status_is_available(status) && purple_status_is_online(status))
+	if (purple_status_is_online(status) && !purple_status_is_available(status) &&
+			userinfo->flags & AIM_FLAG_AWAY && userinfo->away_len > 0 &&
+			userinfo->away != NULL && userinfo->away_encoding != NULL)
 	{
-		if ((userinfo->flags & AIM_FLAG_AWAY) &&
-			(userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
-			gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
-			message = oscar_encoding_to_utf8(account, charset,
-			                                 userinfo->away,
-			                                 userinfo->away_len);
-			g_free(charset);
-			purple_status_set_attr_string(status, "message", message);
-			g_free(message);
-		}
-		else
-			/* Set an empty message so that we know not to show "pending" */
-			purple_status_set_attr_string(status, "message", "");
-
-		purple_blist_update_buddy_status(b, status);
+		gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
+		message = oscar_encoding_to_utf8(account, charset,
+		                                 userinfo->away,
+		                                 userinfo->away_len);
+		g_free(charset);
+		purple_prpl_got_user_status(account, userinfo->sn,
+				purple_status_get_id(status),
+				"message", message, NULL);
+		g_free(message);
 	}
 
 	return 1;
@@ -4520,12 +4520,11 @@
 		/* This is needed for us to un-set any previous away message. */
 		away = g_strdup("");
 	}
-	else if ((primitive == PURPLE_STATUS_AWAY) ||
-			 (primitive == PURPLE_STATUS_EXTENDED_AWAY))
+	else
 	{
 		htmlaway = purple_status_get_attr_string(status, "message");
 		if ((htmlaway == NULL) || (*htmlaway == '\0'))
-			htmlaway = _("Away");
+			htmlaway = purple_status_type_get_name(status_type);
 		away = purple_prpl_oscar_convert_to_infotext(htmlaway, &awaylen, &away_encoding);
 
 		if (awaylen > od->rights.maxawaymsglen)
@@ -5099,6 +5098,8 @@
 	char *gname, *gname_utf8, *alias, *alias_utf8;
 	PurpleBuddy *b;
 	PurpleGroup *g;
+	struct aim_ssi_item *ssi_item;
+	aim_tlv_t *note_hash;
 	va_list ap;
 	guint16 snac_subtype, type;
 	const char *name;
@@ -5166,6 +5167,21 @@
 
 	}
 
+	ssi_item = aim_ssi_itemlist_finditem(od->ssi.local,
+			gname, name, AIM_SSI_TYPE_BUDDY);
+	if (ssi_item != NULL)
+	{
+		note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1);
+		if (note_hash != NULL)
+			aim_icq_getstatusnote(od, name, note_hash->value, note_hash->length);
+	}
+	else
+	{
+		purple_debug_error("oscar", "purple_ssi_parseaddmod: "
+				"Could not find ssi item for oncoming buddy %s, "
+				"group %s\n", name, gname);
+	}
+
 	g_free(gname_utf8);
 	g_free(alias_utf8);
 
--- a/libpurple/protocols/oscar/oscar.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Tue Jan 08 13:17:59 2008 +0000
@@ -3,8 +3,6 @@
  * This file is the legal property of its developers.
  * Please see the AUTHORS file distributed alongside this file.
  *
- * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) <foss@combots.com>
- *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -311,7 +309,7 @@
 }
 
 #define CLIENTINFO_AIM_KNOWNGOOD CLIENTINFO_AIM_5_1_3036
-#define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQ_5_45_3777
+#define CLIENTINFO_ICQ_KNOWNGOOD CLIENTINFO_ICQBASIC_14_34_3000
 
 typedef enum
 {
@@ -468,7 +466,6 @@
 
 	gboolean icq;
 	guint getblisttimer;
-	guint getinfotimer;
 
 	struct {
 		guint maxwatchers; /* max users who can watch you */
@@ -513,9 +510,7 @@
 
 	struct {
 		struct aim_userinfo_s *userinfo;
-		struct userinfo_node *torequest;
 		struct userinfo_node *requested;
-		gboolean waiting_for_response;
 	} locate;
 
 	/* Server-stored information (ssi) */
@@ -1329,6 +1324,10 @@
 
 	/* we keep track of these in a linked list because we're 1337 */
 	struct aim_icq_info *next;
+
+	/* status note info */
+	guint8 icbm_cookie[8];
+	char *status_note_title;
 };
 
 int aim_icq_reqofflinemsgs(OscarData *od);
@@ -1339,7 +1338,7 @@
 int aim_icq_getalias(OscarData *od, const char *uin);
 int aim_icq_getallinfo(OscarData *od, const char *uin);
 int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias);
-
+int aim_icq_getstatusnote(OscarData *od, const char *uin, guint8 *note_hash, guint16 note_hash_len);
 
 
 /* 0x0017 - family_auth.c */
--- a/libpurple/protocols/oscar/oscar_data.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/oscar/oscar_data.c	Tue Jan 08 13:17:59 2008 +0000
@@ -97,8 +97,6 @@
 	g_free(od->oldp);
 	if (od->getblisttimer > 0)
 		purple_timeout_remove(od->getblisttimer);
-	if (od->getinfotimer > 0)
-		purple_timeout_remove(od->getinfotimer);
 	while (od->oscar_connections != NULL)
 		flap_connection_destroy(od->oscar_connections->data,
 				OSCAR_DISCONNECT_DONE, NULL);
--- a/libpurple/protocols/qq/file_trans.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/qq/file_trans.c	Tue Jan 08 13:17:59 2008 +0000
@@ -59,7 +59,7 @@
 	return key;
 }
 		
-static guint32 _gen_file_key()
+static guint32 _gen_file_key(void)
 {
 	guint8 seed;
 	
--- a/libpurple/protocols/sametime/sametime.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Tue Jan 08 13:17:59 2008 +0000
@@ -3806,7 +3806,7 @@
 }
 
 
-static int mw_rand() {
+static int mw_rand(void) {
   static int seed = 0;
 
   /* for diversity, not security. don't touch */
@@ -3818,7 +3818,7 @@
 
 
 /** generates a random-ish content id string */
-static char *im_mime_content_id() {
+static char *im_mime_content_id(void) {
   return g_strdup_printf("%03x@%05xmeanwhile",
 			 mw_rand() & 0xfff, mw_rand() & 0xfffff);
 }
@@ -3826,7 +3826,7 @@
 
 /** generates a multipart/related content type with a random-ish
     boundary value */
-static char *im_mime_content_type() {
+static char *im_mime_content_type(void) {
   return g_strdup_printf("multipart/related; boundary=related_MW%03x_%04x",
                          mw_rand() & 0xfff, mw_rand() & 0xffff);
 }
--- a/libpurple/protocols/simple/simple.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/simple/simple.c	Tue Jan 08 13:17:59 2008 +0000
@@ -45,17 +45,17 @@
 #include "dnssrv.h"
 #include "ntlm.h"
 
-static char *gentag() {
+static char *gentag(void) {
 	return g_strdup_printf("%04d%04d", rand() & 0xFFFF, rand() & 0xFFFF);
 }
 
-static char *genbranch() {
+static char *genbranch(void) {
 	return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
 		rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
 		rand() & 0xFFFF, rand() & 0xFFFF);
 }
 
-static char *gencallid() {
+static char *gencallid(void) {
 	return g_strdup_printf("%04Xg%04Xa%04Xi%04Xm%04Xt%04Xb%04Xx%04Xx",
 		rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
 		rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
--- a/libpurple/protocols/zephyr/ZSendList.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/zephyr/ZSendList.c	Tue Jan 08 13:17:59 2008 +0000
@@ -24,7 +24,7 @@
     char *list[];
     int nitems;
     Z_AuthProc cert_routine;
-    Code_t (*send_routine)();
+    Code_t (*send_routine)(void);
 {
     Code_t retval;
     ZNotice_t newnotice;
--- a/libpurple/protocols/zephyr/ZSendNot.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/zephyr/ZSendNot.c	Tue Jan 08 13:17:59 2008 +0000
@@ -20,7 +20,7 @@
 Code_t ZSrvSendNotice(notice, cert_routine, send_routine)
     ZNotice_t *notice;
     Z_AuthProc cert_routine;
-    Code_t (*send_routine)();
+    Code_t (*send_routine)(void);
 {    
     Code_t retval;
     ZNotice_t newnotice;
--- a/libpurple/protocols/zephyr/Zinternal.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/zephyr/Zinternal.c	Tue Jan 08 13:17:59 2008 +0000
@@ -33,8 +33,6 @@
 #include <utmp.h>
 #endif
 
-extern char *inet_ntoa ();
-
 int __Zephyr_fd = -1;
 int __Zephyr_open;
 int __Zephyr_port = -1;
@@ -144,7 +142,7 @@
 
 /* Return 1 if there is a packet waiting, 0 otherwise */
 
-static int Z_PacketWaiting()
+static int Z_PacketWaiting(void)
 {
     struct timeval tv;
     fd_set read;
@@ -158,7 +156,7 @@
 
 /* Wait for a complete notice to become available */
 
-Code_t Z_WaitForComplete()
+Code_t Z_WaitForComplete(void)
 {
     Code_t retval;
 
@@ -195,9 +193,7 @@
  * notices that haven't been touched in a while
  */
 
-static struct _Z_InputQ *Z_SearchQueue(uid, kind)
-    ZUnique_Id_t *uid;
-    ZNotice_Kind_t kind;
+static struct _Z_InputQ *Z_SearchQueue(ZUnique_Id_t *uid, ZNotice_Kind_t kind)
 {
     register struct _Z_InputQ *qptr;
     struct _Z_InputQ *next;
--- a/libpurple/protocols/zephyr/zephyr.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/zephyr/zephyr.c	Tue Jan 08 13:17:59 2008 +0000
@@ -53,7 +53,7 @@
 
 extern Code_t ZGetLocations(ZLocations_t *, int *);
 extern Code_t ZSetLocation(char *);
-extern Code_t ZUnsetLocation();
+extern Code_t ZUnsetLocation(void);
 extern Code_t ZGetSubscriptions(ZSubscription_t *, int*);
 extern char __Zephyr_realm[];
 typedef struct _zframe zframe;
@@ -1386,7 +1386,7 @@
 
 #endif /* WIN32 */
 
-static char *get_exposure_level()
+static char *get_exposure_level(void)
 {
 	/* XXX add real error reporting */
 	char *exposure = ZGetVariable("exposure");
@@ -2058,7 +2058,7 @@
 static int zephyr_send_message(zephyr_account *zephyr,char* zclass, char* instance, char* recipient, const char *im, 
 			       const char *sig, char *opcode) ;
 
-static const char * zephyr_get_signature()
+static const char * zephyr_get_signature(void)
 {
 	/* XXX add zephyr error reporting */
 	const char * sig =ZGetVariable("zwrite-signature");
@@ -2676,7 +2676,7 @@
 		return PURPLE_CMD_RET_FAILED;
 }
 
-static void zephyr_register_slash_commands()
+static void zephyr_register_slash_commands(void)
 {
 
 	purple_cmd_register("msg","ws", PURPLE_CMD_P_PRPL,
--- a/libpurple/protocols/zephyr/zephyr.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/protocols/zephyr/zephyr.h	Tue Jan 08 13:17:59 2008 +0000
@@ -163,9 +163,9 @@
 Code_t ZReadAscii16 ZP((char *, int, unsigned short *));
 Code_t ZSendPacket ZP((char*, int, int));
 Code_t ZSendList ZP((ZNotice_t*, char *[], int, Z_AuthProc));
-Code_t ZSrvSendList ZP((ZNotice_t*, char*[], int, Z_AuthProc, Code_t (*)()));
+Code_t ZSrvSendList ZP((ZNotice_t*, char*[], int, Z_AuthProc, Code_t (*)(void)));
 Code_t ZSendNotice ZP((ZNotice_t *, Z_AuthProc));
-Code_t ZSrvSendNotice ZP((ZNotice_t*, Z_AuthProc, Code_t (*)()));
+Code_t ZSrvSendNotice ZP((ZNotice_t*, Z_AuthProc, Code_t (*)(void)));
 Code_t ZFormatNotice ZP((ZNotice_t*, char**, int*, Z_AuthProc));
 Code_t ZFormatSmallNotice ZP((ZNotice_t*, ZPacket_t, int*, Z_AuthProc));
 Code_t ZFormatRawNoticeList ZP((ZNotice_t *notice, char *list[], int nitems,
--- a/libpurple/purple-remote	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/purple-remote	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 import dbus
 import re
--- a/libpurple/purple-send	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/purple-send	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 METHOD_NAME=$1
 
--- a/libpurple/purple-send-async	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/purple-send-async	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 METHOD_NAME=$1
 
--- a/libpurple/purple-url-handler	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/purple-url-handler	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 
 import dbus
 import re
--- a/libpurple/roomlist.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/roomlist.c	Tue Jan 08 13:17:59 2008 +0000
@@ -218,6 +218,11 @@
 		prpl_info->roomlist_expand_category(list, category);
 }
 
+GList * purple_roomlist_get_fields(PurpleRoomlist *list)
+{
+	return list->fields;
+}
+
 /*@}*/
 
 /**************************************************************************/
@@ -293,6 +298,26 @@
 	g_hash_table_destroy(components);
 }
 
+PurpleRoomlistRoomType purple_roomlist_room_get_type(PurpleRoomlistRoom *room)
+{
+	return room->type;
+}
+
+const char * purple_roomlist_room_get_name(PurpleRoomlistRoom *room)
+{
+	return room->name;
+}
+
+PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room)
+{
+	return room->parent;
+}
+
+GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room)
+{
+	return room->fields;
+}
+
 /*@}*/
 
 /**************************************************************************/
@@ -319,6 +344,21 @@
 	return f;
 }
 
+PurpleRoomlistFieldType purple_roomlist_field_get_type(PurpleRoomlistField *field)
+{
+	return field->type;
+}
+
+const char * purple_roomlist_field_get_label(PurpleRoomlistField *field)
+{
+	return field->label;
+}
+
+gboolean purple_roomlist_field_get_hidden(PurpleRoomlistField *field)
+{
+	return field->hidden;
+}
+
 /*@}*/
 
 /**************************************************************************/
--- a/libpurple/roomlist.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/roomlist.h	Tue Jan 08 13:17:59 2008 +0000
@@ -237,6 +237,15 @@
  */
 void purple_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category);
 
+/**
+ * Get the list of fields for a roomlist.
+ *
+ * @param roomlist  The roomlist, which must not be @c NULL.
+ * @constreturn A list of fields
+ * @since 2.4.0
+ */
+GList * purple_roomlist_get_fields(PurpleRoomlist *roomlist);
+
 /*@}*/
 
 /**************************************************************************/
@@ -273,6 +282,39 @@
  */
 void purple_roomlist_room_join(PurpleRoomlist *list, PurpleRoomlistRoom *room);
 
+/**
+ * Get the type of a room.
+ * @param room  The room, which must not be @c NULL.
+ * @return The type of the room.
+ * @since 2.4.0
+ */
+PurpleRoomlistRoomType purple_roomlist_room_get_type(PurpleRoomlistRoom *room);
+
+/**
+ * Get the name of a room.
+ * @param room  The room, which must not be @c NULL.
+ * @return The name of the room.
+ * @since 2.4.0
+ */
+const char * purple_roomlist_room_get_name(PurpleRoomlistRoom *room);
+
+/**
+ * Get the parent of a room.
+ * @param room  The room, which must not be @c NULL.
+ * @return The parent of the room, which can be @c NULL.
+ * @since 2.4.0
+ */
+PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room);
+
+/**
+ * Get the list of fields for a room.
+ *
+ * @param room  The room, which must not be @c NULL.
+ * @constreturn A list of fields
+ * @since 2.4.0
+ */
+GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room);
+
 /*@}*/
 
 /**************************************************************************/
@@ -294,6 +336,36 @@
 PurpleRoomlistField *purple_roomlist_field_new(PurpleRoomlistFieldType type,
                                            const gchar *label, const gchar *name,
                                            gboolean hidden);
+
+/**
+ * Get the type of a field.
+ *
+ * @param field  A PurpleRoomlistField, which must not be @c NULL.
+ *
+ * @return  The type of the field.
+ * @since 2.4.0
+ */
+PurpleRoomlistFieldType purple_roomlist_field_get_type(PurpleRoomlistField *field);
+
+/**
+ * Get the label of a field.
+ *
+ * @param field  A PurpleRoomlistField, which must not be @c NULL.
+ *
+ * @return  The label of the field.
+ * @since 2.4.0
+ */
+const char * purple_roomlist_field_get_label(PurpleRoomlistField *field);
+
+/**
+ * Check whether a roomlist-field is hidden.
+ * @param field  A PurpleRoomlistField, which must not be @c NULL.
+ *
+ * @return  @c TRUE if the field is hidden, @c FALSE otherwise.
+ * @since 2.4.0
+ */
+gboolean purple_roomlist_field_get_hidden(PurpleRoomlistField *field);
+
 /*@}*/
 
 /**************************************************************************/
--- a/libpurple/savedstatuses.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/savedstatuses.c	Tue Jan 08 13:17:59 2008 +0000
@@ -190,7 +190,7 @@
  * does the expiration.
  */
 static void
-remove_old_transient_statuses()
+remove_old_transient_statuses(void)
 {
 	GList *l, *next;
 	PurpleSavedStatus *saved_status, *current_status;
--- a/libpurple/signals.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/signals.h	Tue Jan 08 13:17:59 2008 +0000
@@ -44,11 +44,24 @@
 /**************************************************************************/
 /*@{*/
 
-/**
- * Signal Connect Priorities
+/** The priority of a signal connected using purple_signal_connect().
+ *
+ *  @see purple_signal_connect_priority()
  */
 #define PURPLE_SIGNAL_PRIORITY_DEFAULT     0
+/** The largest signal priority; signals with this priority will be called
+ *  <em>last</em>.  (This is highest as in numerical value, not as in order of
+ *  importance.)
+ *
+ *  @see purple_signal_connect_priority().
+ */
 #define PURPLE_SIGNAL_PRIORITY_HIGHEST  9999
+/** The smallest signal priority; signals with this priority will be called
+ *  <em>first</em>.  (This is lowest as in numerical value, not as in order of
+ *  importance.)
+ *
+ *  @see purple_signal_connect_priority().
+ */
 #define PURPLE_SIGNAL_PRIORITY_LOWEST  -9999
 
 /**
@@ -109,19 +122,21 @@
  * @param handle   The handle of the receiver.
  * @param func     The callback function.
  * @param data     The data to pass to the callback function.
- * @param priority The priority with which the handler should be called. Signal handlers are called
- *                 in order from PURPLE_SIGNAL_PRIORITY_LOWEST to PURPLE_SIGNAL_PRIORITY_HIGHEST.
+ * @param priority The priority with which the handler should be called. Signal
+ *                 handlers are called in ascending numerical order of @a
+ *                 priority from #PURPLE_SIGNAL_PRIORITY_LOWEST to
+ *                 #PURPLE_SIGNAL_PRIORITY_HIGHEST.
  *
  * @return The signal handler ID.
  *
  * @see purple_signal_disconnect()
  */
 gulong purple_signal_connect_priority(void *instance, const char *signal,
-				   void *handle, PurpleCallback func, void *data, int priority);
+	void *handle, PurpleCallback func, void *data, int priority);
 
 /**
  * Connects a signal handler to a signal for a particular object.
- * (priority defaults to 0)
+ * (Its priority defaults to 0, aka #PURPLE_SIGNAL_PRIORITY_DEFAULT.)
  * 
  * Take care not to register a handler function twice. Purple will
  * not correct any mistakes for you in this area.
@@ -137,7 +152,7 @@
  * @see purple_signal_disconnect()
  */
 gulong purple_signal_connect(void *instance, const char *signal,
-						   void *handle, PurpleCallback func, void *data);
+	void *handle, PurpleCallback func, void *data);
 
 /**
  * Connects a signal handler to a signal for a particular object.
@@ -153,18 +168,22 @@
  * @param handle   The handle of the receiver.
  * @param func     The callback function.
  * @param data     The data to pass to the callback function.
- * @param priority The order in which the signal should be added to the list
+ * @param priority The priority with which the handler should be called. Signal
+ *                 handlers are called in ascending numerical order of @a
+ *                 priority from #PURPLE_SIGNAL_PRIORITY_LOWEST to
+ *                 #PURPLE_SIGNAL_PRIORITY_HIGHEST.
  *
  * @return The signal handler ID.
  *
  * @see purple_signal_disconnect()
  */
 gulong purple_signal_connect_priority_vargs(void *instance, const char *signal,
-					void *handle, PurpleCallback func, void *data, int priority);
+	void *handle, PurpleCallback func, void *data, int priority);
 
 /**
  * Connects a signal handler to a signal for a particular object.
- * (priority defaults to 0)
+ * (Its priority defaults to 0, aka #PURPLE_SIGNAL_PRIORITY_DEFAULT.)
+ *
  * The signal handler will take a va_args of arguments, instead of
  * individual arguments.
  *
@@ -182,7 +201,7 @@
  * @see purple_signal_disconnect()
  */
 gulong purple_signal_connect_vargs(void *instance, const char *signal,
-								 void *handle, PurpleCallback func, void *data);
+	void *handle, PurpleCallback func, void *data);
 
 /**
  * Disconnects a signal handler from a signal on an object.
--- a/libpurple/stun.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/stun.c	Tue Jan 08 13:17:59 2008 +0000
@@ -104,7 +104,7 @@
 	g_free(sc);
 }
 
-static void do_callbacks() {
+static void do_callbacks(void) {
 	while(callbacks) {
 		StunCallback cb = callbacks->data;
 		if(cb)
--- a/libpurple/upnp.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/upnp.c	Tue Jan 08 13:17:59 2008 +0000
@@ -777,7 +777,7 @@
 
 /* TODO: This could be exported */
 static const gchar *
-purple_upnp_get_internal_ip()
+purple_upnp_get_internal_ip(void)
 {
 	if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED
 			&& control_info.internalip
--- a/libpurple/util.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/util.c	Tue Jan 08 13:17:59 2008 +0000
@@ -4628,3 +4628,57 @@
 #endif /* HAVE_SIGNAL_H */
 #endif /* !_WIN32 */
 }
+
+void purple_util_set_current_song(const char *title, const char *artist, const char *album)
+{
+	GList *list = purple_accounts_get_all();
+	for (; list; list = list->next) {
+		PurplePresence *presence;
+		PurpleStatus *tune;
+		PurpleAccount *account = list->data;
+		if (!purple_account_get_enabled(account, purple_core_get_ui()))
+			continue;
+
+		presence = purple_account_get_presence(account);
+		tune = purple_presence_get_status(presence, "tune");
+		if (!tune)
+			continue;
+		if (title) {
+			purple_status_set_active(tune, TRUE);
+			purple_status_set_attr_string(tune, PURPLE_TUNE_TITLE, title);
+			purple_status_set_attr_string(tune, PURPLE_TUNE_ARTIST, artist);
+			purple_status_set_attr_string(tune, PURPLE_TUNE_ALBUM, album);
+		} else {
+			purple_status_set_active(tune, FALSE);
+		}
+	}
+}
+
+char * purple_util_format_song_info(const char *title, const char *artist, const char *album, gpointer unused)
+{
+	GString *string;
+	char *esc;
+
+	if (!title)
+		return NULL;
+
+	esc = g_markup_escape_text(title, -1);
+	string = g_string_new("");
+	g_string_append_printf(string, "%s", esc);
+	g_free(esc);
+
+	if (artist) {
+		esc = g_markup_escape_text(artist, -1);
+		g_string_append_printf(string, _(" - %s"), esc);
+		g_free(esc);
+	}
+
+	if (album) {
+		esc = g_markup_escape_text(album, -1);
+		g_string_append_printf(string, _(" (%s)"), esc);
+		g_free(esc);
+	}
+
+	return g_string_free(string, FALSE);
+}
+
--- a/libpurple/util.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/util.h	Tue Jan 08 13:17:59 2008 +0000
@@ -85,6 +85,31 @@
  */
 void purple_menu_action_free(PurpleMenuAction *act);
 
+/**
+ * Set the appropriate presence values for the currently playing song.
+ *
+ * @param title     The title of the song, @c NULL to unset the value.
+ * @param artist    The artist of the song, can be @c NULL.
+ * @param album     The album of the song, can be @c NULL.
+ * @since 2.4.0
+ */
+void purple_util_set_current_song(const char *title, const char *artist,
+		const char *album);
+
+/**
+ * Format song information.
+ *
+ * @param title     The title of the song, @c NULL to unset the value.
+ * @param artist    The artist of the song, can be @c NULL.
+ * @param album     The album of the song, can be @c NULL.
+ * @param unused    Currently unused, must be @c NULL.
+ *
+ * @return   The formatted string. The caller must #g_free the returned string.
+ * @since 2.4.0
+ */
+char * purple_util_format_song_info(const char *title, const char *artist,
+		const char *album, gpointer unused);
+
 /**************************************************************************/
 /** @name Utility Subsystem                                               */
 /**************************************************************************/
--- a/libpurple/xmlnode.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/libpurple/xmlnode.c	Tue Jan 08 13:17:59 2008 +0000
@@ -552,6 +552,9 @@
 		g_strdup_printf("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S "%s", xml);
 	g_free(xml);
 
+	if (len)
+		*len += sizeof("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S) - 1;
+
 	return xml_with_declaration;
 }
 
--- a/pidgin/gtkaccount.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkaccount.c	Tue Jan 08 13:17:59 2008 +0000
@@ -158,25 +158,7 @@
 add_pref_box(AccountPrefsDialog *dialog, GtkWidget *parent,
 			 const char *text, GtkWidget *widget)
 {
-	GtkWidget *hbox;
-	GtkWidget *label;
-
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0);
-	gtk_widget_show(hbox);
-
-	label = gtk_label_new_with_mnemonic(text);
-	gtk_size_group_add_widget(dialog->sg, label);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget);
-	gtk_widget_show(label);
-
-	gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, PIDGIN_HIG_BORDER);
-	gtk_widget_show(widget);
-	pidgin_set_accessible_label (widget, label);
-
-	return hbox;
+	return pidgin_add_widget_to_vbox(GTK_BOX(parent), text, dialog->sg, widget, TRUE, NULL);
 }
 
 static void
--- a/pidgin/gtkblist.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkblist.c	Tue Jan 08 13:17:59 2008 +0000
@@ -177,7 +177,7 @@
 } PidginBlistNode;
 
 static char dim_grey_string[8] = "";
-static char *dim_grey()
+static char *dim_grey(void)
 {
 	if (!gtkblist)
 		return "dim grey";
@@ -708,12 +708,12 @@
 	pidgin_blist_update(purple_get_blist(), node);
 }
 
-static void gtk_blist_show_systemlog_cb()
+static void gtk_blist_show_systemlog_cb(void)
 {
 	pidgin_syslog_show();
 }
 
-static void gtk_blist_show_onlinehelp_cb()
+static void gtk_blist_show_onlinehelp_cb(void)
 {
 	purple_notify_uri(NULL, PURPLE_WEBSITE "documentation");
 }
@@ -843,20 +843,10 @@
 
 	for (tmp = list; tmp; tmp = tmp->next)
 	{
-		GtkWidget *label;
-		GtkWidget *rowbox;
 		GtkWidget *input;
 
 		pce = tmp->data;
 
-		rowbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-		gtk_box_pack_start(GTK_BOX(data->entries_box), rowbox, FALSE, FALSE, 0);
-
-		label = gtk_label_new_with_mnemonic(pce->label);
-		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-		gtk_size_group_add_widget(data->sg, label);
-		gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-
 		if (pce->is_int)
 		{
 			GtkObject *adjust;
@@ -864,7 +854,7 @@
 										1, 10, 10);
 			input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
 			gtk_widget_set_size_request(input, 50, -1);
-			gtk_box_pack_end(GTK_BOX(rowbox), input, FALSE, FALSE, 0);
+			pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, FALSE, NULL);
 		}
 		else
 		{
@@ -880,7 +870,7 @@
 				if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*')
 					gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR);
 			}
-			gtk_box_pack_end(GTK_BOX(rowbox), input, TRUE, TRUE, 0);
+			pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, TRUE, NULL);
 			g_signal_connect(G_OBJECT(input), "changed",
 							 G_CALLBACK(joinchat_set_sensitive_if_input_cb), data);
 		}
@@ -891,8 +881,6 @@
 			gtk_widget_grab_focus(input);
 			focus = FALSE;
 		}
-		gtk_label_set_mnemonic_widget(GTK_LABEL(label), input);
-		pidgin_set_accessible_label(input, label);
 		g_object_set_data(G_OBJECT(input), "identifier", (gpointer)pce->identifier);
 		g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int));
 		g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required));
@@ -988,23 +976,14 @@
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 
-	rowbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, TRUE, TRUE, 0);
-
 	data->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
-	label = gtk_label_new_with_mnemonic(_("_Account:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(data->sg, label);
-
 	data->account_menu = pidgin_account_option_menu_new(NULL, FALSE,
 			G_CALLBACK(joinchat_select_account_cb),
 			chat_account_filter_func, data);
 	gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label),
-								  GTK_WIDGET(data->account_menu));
-	pidgin_set_accessible_label (data->account_menu, label);
+
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Account:"), data->sg, data->account_menu, TRUE, NULL);
 
 	data->entries_box = gtk_vbox_new(FALSE, 5);
 	gtk_container_add(GTK_CONTAINER(vbox), data->entries_box);
@@ -1117,7 +1096,7 @@
 	}
 }
 
-static void pidgin_blist_add_chat_cb()
+static void pidgin_blist_add_chat_cb(void)
 {
 	GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview));
 	GtkTreeIter iter;
@@ -1137,7 +1116,7 @@
 	}
 }
 
-static void pidgin_blist_add_buddy_cb()
+static void pidgin_blist_add_buddy_cb(void)
 {
 	GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview));
 	GtkTreeIter iter;
@@ -2576,6 +2555,35 @@
 	int height;
 };
 
+static PangoLayout * create_pango_layout(const char *markup, int *width, int *height)
+{
+	PangoLayout *layout;
+	int w, h;
+
+	layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL);
+	pango_layout_set_markup(layout, markup, -1);
+	pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
+	pango_layout_set_width(layout, 300000);
+
+	pango_layout_get_size (layout, &w, &h);
+	if (width)
+		*width = PANGO_PIXELS(w);
+	if (height)
+		*height = PANGO_PIXELS(h);
+	return layout;
+}
+
+static struct tooltip_data * create_tip_for_account(PurpleAccount *account)
+{
+	struct tooltip_data *td = g_new0(struct tooltip_data, 1);
+	td->status_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
+		/* Yes, status_icon, not prpl_icon */
+	if (purple_account_is_disconnected(account))
+		gdk_pixbuf_saturate_and_pixelate(td->status_icon, td->status_icon, 0.0, FALSE);
+	td->layout = create_pango_layout(purple_account_get_username(account), &td->width, &td->height);
+	return td;
+}
+
 static struct tooltip_data * create_tip_for_node(PurpleBlistNode *node, gboolean full)
 {
 	struct tooltip_data *td = g_new0(struct tooltip_data, 1);
@@ -2594,8 +2602,9 @@
 		td->prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
 	}
 	tooltip_text = pidgin_get_tooltip_text(node, full);
-	td->layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL);
-	td->name_layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL);
+	if (tooltip_text && *tooltip_text) {
+		td->layout = create_pango_layout(tooltip_text, &td->width, &td->height);
+	}
 
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		tmp = g_markup_escape_text(purple_buddy_get_name((PurpleBuddy*)node), -1);
@@ -2612,21 +2621,9 @@
 	node_name = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>", tmp);
 	g_free(tmp);
 
-	pango_layout_set_markup(td->layout, tooltip_text, -1);
-	pango_layout_set_wrap(td->layout, PANGO_WRAP_WORD);
-	pango_layout_set_width(td->layout, 300000);
-
-	pango_layout_get_size (td->layout, &td->width, &td->height);
-	td->width = PANGO_PIXELS(td->width);
-	td->height = PANGO_PIXELS(td->height);
-
-	pango_layout_set_markup(td->name_layout, node_name, -1);
-	pango_layout_set_wrap(td->name_layout, PANGO_WRAP_WORD);
-	pango_layout_set_width(td->name_layout, 300000);
-
-	pango_layout_get_size (td->name_layout, &td->name_width, &td->name_height);
-	td->name_width = PANGO_PIXELS(td->name_width) + SMALL_SPACE + PRPL_SIZE;
-	td->name_height = MAX(PANGO_PIXELS(td->name_height), PRPL_SIZE + SMALL_SPACE);
+	td->name_layout = create_pango_layout(node_name, &td->name_width, &td->name_height);
+	td->name_width += SMALL_SPACE + PRPL_SIZE;
+	td->name_height = MAX(td->name_height, PRPL_SIZE + SMALL_SPACE);
 #if 0  /* PRPL Icon as avatar */
 	if(!td->avatar && full) {
 		td->avatar = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE);
@@ -2654,6 +2651,7 @@
 	GList *l;
 	int prpl_col = 0;
 	GtkTextDirection dir = gtk_widget_get_direction(widget);
+	int status_size = 0;
 
 	if(gtkblist->tooltipdata == NULL)
 		return FALSE;
@@ -2670,13 +2668,15 @@
 		max_text_width = MAX(max_text_width,
 				MAX(td->width, td->name_width));
 		max_avatar_width = MAX(max_avatar_width, td->avatar_width);
-	}
-
-	max_width = TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
+		if (td->status_icon)
+			status_size = STATUS_SIZE;
+	}
+
+	max_width = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
 	if (dir == GTK_TEXT_DIR_RTL)
 		prpl_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE;
 	else
-		prpl_col = TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE + max_text_width - PRPL_SIZE;
+		prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE;
 
 	current_height = 12;
 	for(l = gtkblist->tooltipdata; l; l = l->next)
@@ -2700,7 +2700,7 @@
 		if (td->status_icon) {
 			if (dir == GTK_TEXT_DIR_RTL)
 				gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon,
-				                0, 0, max_width - TOOLTIP_BORDER - STATUS_SIZE, current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
+				                0, 0, max_width - TOOLTIP_BORDER - status_size, current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
 			else
 				gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon,
 				                0, 0, TOOLTIP_BORDER, current_height, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0);
@@ -2733,26 +2733,31 @@
 					max_width - (td->avatar_width + TOOLTIP_BORDER),
 					current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
 #endif
-		if (dir == GTK_TEXT_DIR_RTL) {
-			gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
-					NULL, gtkblist->tipwindow, "tooltip",
-					max_width  -(TOOLTIP_BORDER + STATUS_SIZE +SMALL_SPACE) - PANGO_PIXELS(300000),
-					current_height, td->name_layout);
-		} else {
-			gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
-					NULL, gtkblist->tipwindow, "tooltip",
-					TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE, current_height, td->name_layout);
+		if (td->name_layout) {
+			if (dir == GTK_TEXT_DIR_RTL) {
+				gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
+						max_width  -(TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
+						current_height, td->name_layout);
+			} else {
+				gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
+						TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height, td->name_layout);
+			}
 		}
-		if (dir != GTK_TEXT_DIR_RTL) {
-			gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
-					NULL, gtkblist->tipwindow, "tooltip",
-					TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE, current_height + td->name_height, td->layout);
-		} else {
-			gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
-					NULL, gtkblist->tipwindow, "tooltip",
-					max_width - (TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE) - PANGO_PIXELS(300000),
-					current_height + td->name_height,
-					td->layout);
+
+		if (td->layout) {
+			if (dir != GTK_TEXT_DIR_RTL) {
+				gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
+						TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout);
+			} else {
+				gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
+						NULL, gtkblist->tipwindow, "tooltip",
+						max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
+						current_height + td->name_height,
+						td->layout);
+			}
 		}
 
 		current_height += MAX(td->name_height + td->height, td->avatar_height) + TOOLTIP_BORDER;
@@ -2761,7 +2766,7 @@
 }
 
 static void
-pidgin_blist_destroy_tooltip_data()
+pidgin_blist_destroy_tooltip_data(void)
 {
 	while(gtkblist->tooltipdata) {
 		struct tooltip_data *td = gtkblist->tooltipdata->data;
@@ -2772,8 +2777,10 @@
 			g_object_unref(td->status_icon);
 		if(td->prpl_icon)
 			g_object_unref(td->prpl_icon);
-		g_object_unref(td->layout);
-		g_object_unref(td->name_layout);
+		if (td->layout)
+			g_object_unref(td->layout);
+		if (td->name_layout)
+			g_object_unref(td->name_layout);
 		g_free(td);
 		gtkblist->tooltipdata = g_list_delete_link(gtkblist->tooltipdata, gtkblist->tooltipdata);
 	}
@@ -2790,6 +2797,10 @@
 {
 	PurpleBlistNode *node = data;
 	int width, height;
+	GList *list;
+	int max_text_width = 0;
+	int max_avatar_width = 0;
+	int status_size = 0;
 
 	if (gtkblist->tooltipdata) {
 		gtkblist->tipwindow = NULL;
@@ -2797,20 +2808,27 @@
 	}
 
 	gtkblist->tipwindow = widget;
-	if(PURPLE_BLIST_NODE_IS_CHAT(node) ||
-	   PURPLE_BLIST_NODE_IS_BUDDY(node) ||
-	   PURPLE_BLIST_NODE_IS_GROUP(node)) {
+	if (PURPLE_BLIST_NODE_IS_CHAT(node) ||
+	   PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+		struct tooltip_data *td = create_tip_for_node(node, TRUE);
+		gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
+	} else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
+		PurpleGroup *group = (PurpleGroup*)node;
+		GSList *accounts;
 		struct tooltip_data *td = create_tip_for_node(node, TRUE);
 		gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
-		width = TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE +
-			MAX(td->width, td->name_width) + SMALL_SPACE + td->avatar_width + TOOLTIP_BORDER;
-		height = TOOLTIP_BORDER + MAX(td->height + td->name_height, MAX(STATUS_SIZE, td->avatar_height))
-			+ TOOLTIP_BORDER;
-	} else if(PURPLE_BLIST_NODE_IS_CONTACT(node)) {
+
+		/* Accounts with buddies in group */
+		accounts = purple_group_get_accounts(group);
+		for (; accounts != NULL;
+		     accounts = g_slist_delete_link(accounts, accounts)) {
+			PurpleAccount *account = accounts->data;
+			td = create_tip_for_account(account);
+			gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
+		}
+	} else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		PurpleBlistNode *child;
 		PurpleBuddy *b = purple_contact_get_priority_buddy((PurpleContact *)node);
-		int max_text_width = 0;
-		int max_avatar_width = 0;
 		width = height = 0;
 
 		for(child = node->child; child; child = child->next)
@@ -2822,18 +2840,25 @@
 				} else {
 					gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
 				}
-				max_text_width = MAX(max_text_width, MAX(td->width, td->name_width));
-				max_avatar_width = MAX(max_avatar_width, td->avatar_width);
-				height += MAX(TOOLTIP_BORDER + MAX(STATUS_SIZE,td->avatar_height),
-						TOOLTIP_BORDER + td->height + td->name_height);
 			}
 		}
-		height += TOOLTIP_BORDER;
-		width = TOOLTIP_BORDER + STATUS_SIZE + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
 	} else {
 		return FALSE;
 	}
 
+	height = width = 0;
+	for (list = gtkblist->tooltipdata; list; list = list->next) {
+		struct tooltip_data *td = list->data;
+		max_text_width = MAX(max_text_width, MAX(td->width, td->name_width));
+		max_avatar_width = MAX(max_avatar_width, td->avatar_width);
+		height += MAX(TOOLTIP_BORDER + MAX(STATUS_SIZE, td->avatar_height),
+				TOOLTIP_BORDER + td->height + td->name_height);
+		if (td->status_icon)
+			status_size = MAX(status_size, STATUS_SIZE);
+	}
+	height += TOOLTIP_BORDER;
+	width = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
+
 	if (w)
 		*w = width;
 	if (h)
@@ -3100,7 +3125,7 @@
 		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);
+			g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
 			g_free(tmp);
 		}
 
@@ -3293,7 +3318,6 @@
 
 		purple_notify_user_info_destroy(user_info);
 	} else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
-		GSList *accounts;
 		PurpleGroup *group = (PurpleGroup*)node;
 		PurpleNotifyUserInfo *user_info;
 
@@ -3313,14 +3337,6 @@
 		                                 tmp);
 		g_free(tmp);
 
-		/* Accounts with buddies in group */
-		accounts = purple_group_get_accounts(group);
-		for (; accounts != NULL;
-		     accounts = g_slist_delete_link(accounts, accounts)) {
-			PurpleAccount *account = accounts->data;
-			purple_notify_user_info_add_pair(user_info, _("Account"), purple_account_get_username(account));
-		}
-
 		tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n");
 		g_string_append(str, tmp);
 		g_free(tmp);
@@ -3750,7 +3766,7 @@
 	return text;
 }
 
-static void pidgin_blist_restore_position()
+static void pidgin_blist_restore_position(void)
 {
 	int blist_x, blist_y, blist_width, blist_height;
 
@@ -3897,7 +3913,7 @@
 }
 
 static void
-unseen_conv_menu()
+unseen_conv_menu(void)
 {
 	static GtkWidget *menu = NULL;
 	GList *convs = NULL;
@@ -4183,7 +4199,8 @@
 	pidgin_blist_sort_method_set(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/sort_type"));
 }
 
-static void _prefs_change_redo_list()
+static void _prefs_change_redo_list(const char *name, PurplePrefType type,
+                                    gconstpointer val, gpointer data)
 {
 	GtkTreeSelection *sel;
 	GtkTreeIter iter;
@@ -4853,6 +4870,9 @@
 #endif
 
 	gtk_tooltips_force_window (tooltips);
+#if GTK_CHECK_VERSION(2, 12, 0)
+	gtk_widget_set_name (tooltips->tip_window, "gtk-tooltips");
+#endif
 	gtk_widget_ensure_style (tooltips->tip_window);
 	style = gtk_widget_get_style (tooltips->tip_window);
 
@@ -5037,8 +5057,9 @@
 	gtk_label_set_line_wrap(GTK_LABEL(gtkblist->headline_label), TRUE);
 	gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), gtkblist->headline_image, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), gtkblist->headline_label, TRUE, TRUE, 0);
-	g_signal_connect(gtkblist->headline_hbox,
-			 "style-set",
+	g_signal_connect(gtkblist->headline_label,   /* connecting on headline_hbox doesn't work, because
+	                                                the signal is not emitted when theme is changed */
+			"style-set",
 			 G_CALLBACK(headline_style_set),
 			 NULL);
 	g_signal_connect (gtkblist->headline_hbox,
@@ -6475,20 +6496,10 @@
 
 	for (tmp = list; tmp; tmp = tmp->next)
 	{
-		GtkWidget *label;
-		GtkWidget *rowbox;
 		GtkWidget *input;
 
 		pce = tmp->data;
 
-		rowbox = gtk_hbox_new(FALSE, 5);
-		gtk_box_pack_start(GTK_BOX(data->entries_box), rowbox, FALSE, FALSE, 0);
-
-		label = gtk_label_new_with_mnemonic(pce->label);
-		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-		gtk_size_group_add_widget(data->sg, label);
-		gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-
 		if (pce->is_int)
 		{
 			GtkObject *adjust;
@@ -6496,7 +6507,7 @@
 										1, 10, 10);
 			input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
 			gtk_widget_set_size_request(input, 50, -1);
-			gtk_box_pack_end(GTK_BOX(rowbox), input, FALSE, FALSE, 0);
+			pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, FALSE, NULL);
 		}
 		else
 		{
@@ -6512,7 +6523,7 @@
 				if (gtk_entry_get_invisible_char(GTK_ENTRY(input)) == '*')
 					gtk_entry_set_invisible_char(GTK_ENTRY(input), PIDGIN_INVISIBLE_CHAR);
 			}
-			gtk_box_pack_end(GTK_BOX(rowbox), input, TRUE, TRUE, 0);
+			pidgin_add_widget_to_vbox(GTK_BOX(data->entries_box), pce->label, data->sg, input, TRUE, NULL);
 			g_signal_connect(G_OBJECT(input), "changed",
 							 G_CALLBACK(addchat_set_sensitive_if_input_cb), data);
 		}
@@ -6523,8 +6534,6 @@
 			gtk_widget_grab_focus(input);
 			focus = FALSE;
 		}
-		gtk_label_set_mnemonic_widget(GTK_LABEL(label), input);
-		pidgin_set_accessible_label(input, label);
 		g_object_set_data(G_OBJECT(input), "identifier", (gpointer)pce->identifier);
 		g_object_set_data(G_OBJECT(input), "is_spin", GINT_TO_POINTER(pce->is_int));
 		g_object_set_data(G_OBJECT(input), "required", GINT_TO_POINTER(pce->required));
@@ -6567,7 +6576,6 @@
 	GList *l;
 	PurpleConnection *gc;
 	GtkWidget *label;
-	GtkWidget *rowbox;
 	GtkWidget *hbox;
 	GtkWidget *vbox;
 	GtkWidget *img;
@@ -6643,20 +6651,10 @@
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("_Account:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_size_group_add_widget(data->sg, label);
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-
 	data->account_menu = pidgin_account_option_menu_new(account, FALSE,
 			G_CALLBACK(addchat_select_account_cb),
 			chat_account_filter_func, data);
-	gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_menu);
-	pidgin_set_accessible_label (data->account_menu, label);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Account:"), data->sg, data->account_menu, TRUE, NULL);
 
 	data->entries_box = gtk_vbox_new(FALSE, 5);
 	gtk_container_set_border_width(GTK_CONTAINER(data->entries_box), 0);
@@ -6664,36 +6662,17 @@
 
 	rebuild_addchat_entries(data);
 
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("A_lias:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_size_group_add_widget(data->sg, label);
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-
 	data->alias_entry = gtk_entry_new();
 	if (alias != NULL)
 		gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias);
-	gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0);
 	gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->alias_entry);
-	pidgin_set_accessible_label (data->alias_entry, label);
+
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("A_lias:"), data->sg, data->alias_entry, TRUE, NULL);
 	if (name != NULL)
 		gtk_widget_grab_focus(data->alias_entry);
 
-	rowbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("_Group:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_size_group_add_widget(data->sg, label);
-	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
-
 	data->group_combo = pidgin_text_combo_box_entry_new(group ? group->name : NULL, groups_tree());
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_BIN(data->group_combo)->child);
-	pidgin_set_accessible_label (data->group_combo, label);
-	gtk_box_pack_end(GTK_BOX(rowbox), data->group_combo, TRUE, TRUE, 0);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"), data->sg, data->group_combo, TRUE, NULL);
 	
 	data->autojoin = gtk_check_button_new_with_mnemonic(_("Auto_join when account becomes online."));
 	data->persistent = gtk_check_button_new_with_mnemonic(_("_Hide chat when the window is closed."));
@@ -6967,7 +6946,8 @@
 	pidgin_blist_update_sort_methods();
 }
 
-void pidgin_blist_sort_method_unreg(const char *id){
+void pidgin_blist_sort_method_unreg(const char *id)
+{
 	GList *l = pidgin_blist_sort_methods;
 
 	while(l) {
@@ -6979,6 +6959,7 @@
 			g_free(method);
 			break;
 		}
+		l = l->next;
 	}
 	pidgin_blist_update_sort_methods();
 }
--- a/pidgin/gtkcertmgr.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkcertmgr.c	Tue Jan 08 13:17:59 2008 +0000
@@ -430,7 +430,7 @@
 		/* Set up the display columns */
 		renderer = gtk_cell_renderer_text_new();
 		column = gtk_tree_view_column_new_with_attributes(
-			"Hostname",
+			_("Hostname"),
 			renderer,
 			"text", TPM_HOSTNAME_COLUMN,
 			NULL);
--- a/pidgin/gtkconn.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkconn.c	Tue Jan 08 13:17:59 2008 +0000
@@ -162,11 +162,6 @@
 		if (info != NULL)
 			g_hash_table_remove(auto_reconns, account);
 
-		/*
-		 * TODO: Do we really want to disable the account when it's
-		 * disconnected by wants_to_die?  This happens when you sign
-		 * on from somewhere else, or when you enter an invalid password.
-		 */
 		purple_account_set_enabled(account, PIDGIN_UI, FALSE);
 	}
 
@@ -182,7 +177,7 @@
 	}
 }
 
-static void pidgin_connection_network_connected ()
+static void pidgin_connection_network_connected (void)
 {
 	GList *list, *l;
 	PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
@@ -201,7 +196,7 @@
 	g_list_free(list);
 }
 
-static void pidgin_connection_network_disconnected ()
+static void pidgin_connection_network_disconnected (void)
 {
 	GList *list, *l;
 	PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
--- a/pidgin/gtkconv.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkconv.c	Tue Jan 08 13:17:59 2008 +0000
@@ -1350,6 +1350,7 @@
 	PidginWindow *win = data;
 	PurpleConversation *conv;
 	gboolean logging;
+	PurpleBlistNode *node;
 
 	conv = pidgin_conv_window_get_active_conversation(win);
 
@@ -1360,6 +1361,8 @@
 
 	if (logging == purple_conversation_is_logging(conv))
 		return;
+	
+	node = get_conversation_blist_node(conv);
 
 	if (logging)
 	{
@@ -1383,6 +1386,27 @@
 		/* Disable the logging second, so that the above message can be logged. */
 		purple_conversation_set_logging(conv, FALSE);
 	}
+
+	/* Save the setting IFF it's different than the pref. */
+	switch (conv->type)
+	{
+		case PURPLE_CONV_TYPE_IM:
+			if (logging == purple_prefs_get_bool("/purple/logging/log_ims"))
+				purple_blist_node_remove_setting(node, "enable-logging");
+			else
+				purple_blist_node_set_bool(node, "enable-logging", logging);
+			break;
+
+		case PURPLE_CONV_TYPE_CHAT:
+			if (logging == purple_prefs_get_bool("/purple/logging/log_chats"))
+				purple_blist_node_remove_setting(node, "enable-logging");
+			else
+				purple_blist_node_set_bool(node, "enable-logging", logging);
+			break;
+
+		default:
+			break;
+	}
 }
 
 static void
@@ -2420,7 +2444,6 @@
 {
 	PidginConversation *gtkconv;
 	PidginWindow *win;
-	PurpleBuddy *b;
 	GList *l;
 	GdkPixbuf *status = NULL;
 	GdkPixbuf *infopane_status = NULL;
@@ -2433,13 +2456,18 @@
 	if (conv != gtkconv->active_conv)
 		return;
 
-
 	status = pidgin_conv_get_tab_icon(conv, TRUE);
 	infopane_status = pidgin_conv_get_tab_icon(conv, FALSE);
 
-	b = purple_find_buddy(conv->account, conv->name);
-	if (b)
-		emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
+		PurpleBuddy *b = purple_find_buddy(conv->account, conv->name);
+		if (b)
+			emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
+	} else {
+		PurpleChat *c = purple_blist_find_chat(conv->account, conv->name);
+		if (c)
+			emblem = pidgin_blist_get_emblem((PurpleBlistNode*)c);
+	}
 
 	g_return_if_fail(status != NULL);
 
@@ -3337,6 +3365,7 @@
 	}
 }
 
+#if 0
 static gboolean
 typing_animation(gpointer data) {
 	PidginConversation *gtkconv = data;
@@ -3375,6 +3404,7 @@
 	gtk_widget_show(gtkwin->menu.typing_icon);
 	return TRUE;
 }
+#endif
 
 static void
 update_typing_message(PidginConversation *gtkconv, const char *message)
@@ -3410,8 +3440,6 @@
 	PidginWindow *gtkwin;
 	PurpleConvIm *im = NULL;
 	PurpleConversation *conv = gtkconv->active_conv;
-	char *stock_id;
-	const char *tooltip;
 	char *message = NULL;
 
 	gtkwin = gtkconv->win;
@@ -3419,55 +3447,20 @@
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 		im = PURPLE_CONV_IM(conv);
 
-	if (gtkwin->menu.typing_icon) {
-		gtk_widget_hide(gtkwin->menu.typing_icon);
-	}
-
 	if (im == NULL)
 		return;
 
 	if (purple_conv_im_get_typing_state(im) == PURPLE_NOT_TYPING) {
-		if (gtkconv->u.im->typing_timer != 0) {
-			g_source_remove(gtkconv->u.im->typing_timer);
-			gtkconv->u.im->typing_timer = 0;
-		}
 		update_typing_message(gtkconv, "\n");
 		return;
 	}
 
 	if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) {
-		if (gtkconv->u.im->typing_timer == 0) {
-			gtkconv->u.im->typing_timer = g_timeout_add(250, typing_animation, gtkconv);
-		}
-		stock_id = PIDGIN_STOCK_ANIMATION_TYPING1;
-		tooltip = _("User is typing...");
 		message = g_strdup_printf(_("\n%s is typing..."), purple_conversation_get_title(conv));
 	} else {
-		stock_id = PIDGIN_STOCK_ANIMATION_TYPING5;
-		tooltip = _("User has typed something and stopped");
-		message = g_strdup_printf(_("\n%s has typed something and stopped"), purple_conversation_get_title(conv));
-		if (gtkconv->u.im->typing_timer != 0) {
-			g_source_remove(gtkconv->u.im->typing_timer);
-			gtkconv->u.im->typing_timer = 0;
-		}
-	}
-
-	if (gtkwin->menu.typing_icon == NULL)
-	{
-		gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
-		pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray),
-								  gtkwin->menu.typing_icon,
-								  tooltip);
-	}
-	else
-	{
-		gtk_image_set_from_stock(GTK_IMAGE(gtkwin->menu.typing_icon), stock_id, GTK_ICON_SIZE_MENU);
-		pidgin_menu_tray_set_tooltip(PIDGIN_MENU_TRAY(gtkwin->menu.tray),
-									   gtkwin->menu.typing_icon,
-									   tooltip);
-	}
-
-	gtk_widget_show(gtkwin->menu.typing_icon);
+		message = g_strdup_printf(_("\n%s has stopped typing"), purple_conversation_get_title(conv));
+	}
+
 	update_typing_message(gtkconv, message);
 	g_free(message);
 }
@@ -4907,6 +4900,7 @@
 	GtkWidget *pane = NULL;
 	GtkWidget *tab_cont;
 	PurpleBlistNode *convnode;
+	PurpleValue *value;
 
 	if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
 		conv->ui_data = gtkconv;
@@ -4994,6 +4988,13 @@
 	if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
 		gtkconv->make_sound = TRUE;
 
+	if (convnode != NULL &&
+	    (value = g_hash_table_lookup(convnode->settings, "enable-logging")) &&
+	    purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN)
+	{
+		purple_conversation_set_logging(conv, purple_value_get_boolean(value));
+	}
+
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"))
 		gtk_widget_show(gtkconv->toolbar);
 	else
@@ -6558,7 +6559,7 @@
 			pango_attr_list_unref(list);
 		} else
 			gtk_label_set_attributes(GTK_LABEL(gtkconv->tab_label), NULL);
-
+		
 		if (pidgin_conv_window_is_active_conversation(conv))
 			update_typing_icon(gtkconv);
 
--- a/pidgin/gtkdebug.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkdebug.c	Tue Jan 08 13:17:59 2008 +0000
@@ -686,13 +686,11 @@
 	width  = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/width");
 	height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/height");
 
-	PIDGIN_DIALOG(win->window);
+	win->window = pidgin_create_dialog(_("Debug Window"), 0, "debug", TRUE);
 	purple_debug_info("gtkdebug", "Setting dimensions to %d, %d\n",
 					width, height);
 
 	gtk_window_set_default_size(GTK_WINDOW(win->window), width, height);
-	gtk_window_set_role(GTK_WINDOW(win->window), "debug");
-	gtk_window_set_title(GTK_WINDOW(win->window), _("Debug Window"));
 
 	g_signal_connect(G_OBJECT(win->window), "delete_event",
 	                 G_CALLBACK(debug_window_destroy), NULL);
@@ -700,7 +698,7 @@
 	                 G_CALLBACK(configure_cb), win);
 
 	handle = pidgin_debug_get_handle();
-	
+
 #ifdef HAVE_REGEX_H
 	/* the list store for all the messages */
 	win->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
@@ -716,8 +714,7 @@
 #endif /* HAVE_REGEX_H */
 
 	/* Setup the vbox */
-	vbox = gtk_vbox_new(FALSE, 0);
-	gtk_container_add(GTK_CONTAINER(win->window), vbox);
+	vbox = pidgin_dialog_get_vbox(GTK_DIALOG(win->window));
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/toolbar")) {
 		/* Setup our top button bar thingie. */
--- a/pidgin/gtkdialogs.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkdialogs.c	Tue Jan 08 13:17:59 2008 +0000
@@ -288,7 +288,7 @@
 	}
 }
 
-static void destroy_about()
+static void destroy_about(void)
 {
 	if (about != NULL)
 		gtk_widget_destroy(about);
@@ -337,12 +337,10 @@
 
 void pidgin_dialogs_about()
 {
-	GtkWidget *hbox;
 	GtkWidget *vbox;
 	GtkWidget *logo;
 	GtkWidget *frame;
 	GtkWidget *text;
-	GtkWidget *bbox;
 	GtkWidget *button;
 	GtkTextIter iter;
 	GString *str;
@@ -357,20 +355,12 @@
 		return;
 	}
 
-	PIDGIN_DIALOG(about);
 	tmp = g_strdup_printf(_("About %s"), PIDGIN_NAME);
-	gtk_window_set_title(GTK_WINDOW(about), tmp);
+	about = pidgin_create_dialog(tmp, PIDGIN_HIG_BORDER, "about", TRUE);
 	g_free(tmp);
-	gtk_window_set_role(GTK_WINDOW(about), "about");
-	gtk_window_set_resizable(GTK_WINDOW(about), TRUE);
 	gtk_window_set_default_size(GTK_WINDOW(about), 340, 450);
 
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_set_border_width(GTK_CONTAINER(hbox), PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(about), hbox);
-
-	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_container_add(GTK_CONTAINER(hbox), vbox);
+	vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(about), FALSE, PIDGIN_HIG_BORDER);
 
 	/* Generate a logo with a version number */
 	logo = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -709,15 +699,9 @@
 	gtk_text_buffer_place_cursor(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), &iter);
 
 	/* Close Button */
-	bbox = gtk_hbutton_box_new();
-	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
-	gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
+	button = pidgin_dialog_add_button(GTK_DIALOG(about), GTK_STOCK_CLOSE,
+	                G_CALLBACK(destroy_about), about);
 
-	button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
-	gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
-
-	g_signal_connect_swapped(G_OBJECT(button), "clicked",
-							 G_CALLBACK(destroy_about), G_OBJECT(about));
 	g_signal_connect(G_OBJECT(about), "destroy",
 					 G_CALLBACK(destroy_about), G_OBJECT(about));
 
--- a/pidgin/gtkdialogs.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkdialogs.h	Tue Jan 08 13:17:59 2008 +0000
@@ -54,11 +54,10 @@
 
 /* Everything after this should probably be moved elsewhere */
 
-/**
- * Our UI's identifier.
- */
+#ifndef PIDGIN_DISABLE_DEPRECATED
 #define PIDGIN_DIALOG(x)	x = gtk_window_new(GTK_WINDOW_TOPLEVEL); \
 			gtk_window_set_type_hint(GTK_WINDOW(x), GDK_WINDOW_TYPE_HINT_DIALOG)
+#endif
 #define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED)
 
 #endif /* _PIDGINDIALOGS_H_ */
--- a/pidgin/gtkdocklet-x11.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkdocklet-x11.c	Tue Jan 08 13:17:59 2008 +0000
@@ -48,7 +48,7 @@
 static void docklet_x11_create(gboolean);
 
 static gboolean
-docklet_x11_recreate_cb()
+docklet_x11_recreate_cb(gpointer data)
 {
 	docklet_x11_create(TRUE);
 
@@ -147,7 +147,7 @@
 }
 
 static void
-docklet_x11_blank_icon()
+docklet_x11_blank_icon(void)
 {
 	if (!blank_icon) {
 		GtkIconSize size = GTK_ICON_SIZE_LARGE_TOOLBAR;
@@ -205,7 +205,7 @@
 #endif
 
 static void
-docklet_x11_destroy()
+docklet_x11_destroy(void)
 {
 	g_return_if_fail(docklet != NULL);
 
@@ -230,7 +230,7 @@
 }
 
 static gboolean
-docklet_x11_embed_timeout_cb()
+docklet_x11_embed_timeout_cb(gpointer data)
 {
 	/* The docklet was not embedded within the timeout.
 	 * Remove it as a visibility manager, but leave the plugin
@@ -301,7 +301,7 @@
 }
 
 static void
-docklet_x11_create_ui_op()
+docklet_x11_create_ui_op(void)
 {
 	docklet_x11_create(FALSE);
 }
--- a/pidgin/gtkdocklet.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkdocklet.c	Tue Jan 08 13:17:59 2008 +0000
@@ -62,7 +62,7 @@
  * docklet status and utility functions
  **************************************************************************/
 static gboolean
-docklet_blink_icon()
+docklet_blink_icon(gpointer data)
 {
 	static gboolean blinked = FALSE;
 	gboolean ret = FALSE; /* by default, don't keep blinking */
@@ -108,7 +108,7 @@
 }
 
 static gboolean
-docklet_update_status()
+docklet_update_status(void)
 {
 	GList *convs, *l;
 	int count;
@@ -219,7 +219,7 @@
 }
 
 static gboolean
-online_account_supports_chat()
+online_account_supports_chat(void)
 {
 	GList *c = NULL;
 	c = purple_connections_get_all();
@@ -523,7 +523,7 @@
 }
 
 static GtkWidget *
-docklet_status_submenu()
+docklet_status_submenu(void)
 {
 	GtkWidget *submenu, *menuitem;
 	GList *popular_statuses, *cur;
@@ -667,7 +667,8 @@
 }
 
 static void
-docklet_menu() {
+docklet_menu(void)
+{
 	static GtkWidget *menu = NULL;
 	GtkWidget *menuitem;
 
--- a/pidgin/gtkidle.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkidle.c	Tue Jan 08 13:17:59 2008 +0000
@@ -69,7 +69,7 @@
  */
 #if defined(USE_SCREENSAVER) || defined(HAVE_IOKIT)
 static time_t
-pidgin_get_time_idle()
+pidgin_get_time_idle(void)
 {
 # ifdef HAVE_IOKIT
 	/* Query the IOKit API */
--- a/pidgin/gtkimhtml.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkimhtml.c	Tue Jan 08 13:17:59 2008 +0000
@@ -289,7 +289,7 @@
 #endif
 
 static GtkSmileyTree*
-gtk_smiley_tree_new ()
+gtk_smiley_tree_new (void)
 {
 	return g_new0 (GtkSmileyTree, 1);
 }
@@ -4277,33 +4277,6 @@
 	g_object_unref(object);
 }
 
-static void populate_popup_cb(GtkTextView *textview, GtkMenu *menu, gpointer nul)
-{
-	GtkWidget *mi, *img;
-	
-	mi = gtk_menu_item_new();
-	gtk_widget_show(mi);
-	gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), mi);
-
-	img = gtk_image_new_from_stock(GTK_STOCK_BOLD, GTK_ICON_SIZE_MENU);
-	mi = gtk_image_menu_item_new_with_mnemonic(_("_Font"));
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
-	gtk_widget_show(mi);
-	gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), mi);
-
-	img = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_INSERT, GTK_ICON_SIZE_MENU);
-	mi = gtk_image_menu_item_new_with_mnemonic(_("_Insert"));
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
-	gtk_widget_show(mi);
-	gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), mi);
-
-	img = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY, GTK_ICON_SIZE_MENU);
-	mi = gtk_image_menu_item_new_with_mnemonic(_("S_mile!"));
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
-	gtk_widget_show(mi);
-	gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), mi);
-}
-
 static void imhtml_toggle_bold(GtkIMHtml *imhtml)
 {
 	GtkTextIter start, end;
--- a/pidgin/gtkimhtmltoolbar.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Tue Jan 08 13:17:59 2008 +0000
@@ -709,10 +709,8 @@
 		smileys = smileys->next;
 	}
 
-	PIDGIN_DIALOG(dialog);
+	dialog = pidgin_create_dialog(_("Smile!"), 0, "smiley_dialog", FALSE);
 
-	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-	gtk_window_set_role(GTK_WINDOW(dialog), "smiley_dialog");
 	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
 
 	if (unique_smileys != NULL) {
@@ -769,18 +767,15 @@
 	}
 
 	g_signal_connect(G_OBJECT(dialog), "key-press-event", (GCallback)smiley_dialog_input_cb, toolbar);
-	gtk_container_add(GTK_CONTAINER(dialog), smiley_table);
+	gtk_container_add(GTK_CONTAINER(pidgin_dialog_get_vbox(GTK_DIALOG(dialog))), smiley_table);
 
 	gtk_widget_show(smiley_table);
 
-	gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
-
 	/* connect signals */
 	g_signal_connect(G_OBJECT(dialog), "delete_event",
 					 G_CALLBACK(close_smiley_dialog), toolbar);
 
 	/* show everything */
-	gtk_window_set_title(GTK_WINDOW(dialog), _("Smile!"));
 	gtk_widget_show_all(dialog);
 	gtk_window_set_transient_for(GTK_WINDOW(dialog),
 			GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar))));
--- a/pidgin/gtkmain.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkmain.c	Tue Jan 08 13:17:59 2008 +0000
@@ -174,7 +174,7 @@
  * be wise to move this code into gtksound.c.
  */
 static void
-clean_pid()
+clean_pid(void)
 {
 	int status;
 	pid_t pid;
@@ -241,7 +241,7 @@
 #endif
 
 static int
-ui_main()
+ui_main(void)
 {
 #ifndef _WIN32
 	GList *icons = NULL;
@@ -359,7 +359,7 @@
 	gtk_main_quit();
 }
 
-static GHashTable *pidgin_ui_get_info()
+static GHashTable *pidgin_ui_get_info(void)
 {
 	if(NULL == ui_info) {
 		ui_info = g_hash_table_new(g_str_hash, g_str_equal);
--- a/pidgin/gtknotify.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtknotify.c	Tue Jan 08 13:17:59 2008 +0000
@@ -332,7 +332,7 @@
 }
 
 static GtkWidget *
-pidgin_get_mail_dialog()
+pidgin_get_mail_dialog(void)
 {
 	if (mail_dialog == NULL) {
 		GtkWidget *dialog = NULL;
@@ -604,7 +604,7 @@
 }
 
 static GtkIMHtmlOptions
-notify_imhtml_options()
+notify_imhtml_options(void)
 {
 	GtkIMHtmlOptions options = 0;
 
--- a/pidgin/gtkpluginpref.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkpluginpref.c	Tue Jan 08 13:17:59 2008 +0000
@@ -93,22 +93,6 @@
 		case PURPLE_PLUGIN_PREF_NONE:
 		default:
 			if (format == PURPLE_STRING_FORMAT_TYPE_NONE)
-				box = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-			else
-				box = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-
-			gtk_widget_show(box);
-			gtk_box_pack_start(GTK_BOX(parent), box, FALSE, FALSE, 0);
-
-			gtk_label = gtk_label_new_with_mnemonic(pref_label);
-			gtk_misc_set_alignment(GTK_MISC(gtk_label), 0, 0.5);
-			gtk_widget_show(gtk_label);
-			gtk_box_pack_start(GTK_BOX(box), gtk_label, FALSE, FALSE, 0);
-
-			if(sg)
-				gtk_size_group_add_widget(sg, gtk_label);
-
-			if (format == PURPLE_STRING_FORMAT_TYPE_NONE)
 			{				
 				entry = gtk_entry_new();
 				gtk_entry_set_text(GTK_ENTRY(entry), purple_prefs_get_string(pref_name));
@@ -123,9 +107,7 @@
 				g_signal_connect(G_OBJECT(entry), "changed",
 								 G_CALLBACK(entry_cb),
 								 (gpointer)pref_name);
-				gtk_label_set_mnemonic_widget(GTK_LABEL(gtk_label), entry);
-				gtk_widget_show(entry);
-				gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
+				pidgin_add_widget_to_vbox(GTK_BOX(parent), pref_label, sg, entry, TRUE, NULL);
 			}
 			else
 			{
@@ -135,6 +117,19 @@
 				GtkWidget *toolbar;
 				GtkWidget *frame;
 
+				box = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+
+				gtk_widget_show(box);
+				gtk_box_pack_start(GTK_BOX(parent), box, FALSE, FALSE, 0);
+
+				gtk_label = gtk_label_new_with_mnemonic(pref_label);
+				gtk_misc_set_alignment(GTK_MISC(gtk_label), 0, 0.5);
+				gtk_widget_show(gtk_label);
+				gtk_box_pack_start(GTK_BOX(box), gtk_label, FALSE, FALSE, 0);
+
+				if(sg)
+					gtk_size_group_add_widget(sg, gtk_label);
+
 				hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 				gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
 				gtk_widget_show(hbox);
--- a/pidgin/gtkprefs.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkprefs.c	Tue Jan 08 13:17:59 2008 +0000
@@ -89,23 +89,12 @@
 pidgin_prefs_labeled_spin_button(GtkWidget *box, const gchar *title,
 		const char *key, int min, int max, GtkSizeGroup *sg)
 {
-	GtkWidget *hbox;
-	GtkWidget *label;
 	GtkWidget *spin;
 	GtkObject *adjust;
 	int val;
 
 	val = purple_prefs_get_int(key);
 
-	hbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 5);
-	gtk_widget_show(hbox);
-
-	label = gtk_label_new_with_mnemonic(title);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_widget_show(label);
-
 	adjust = gtk_adjustment_new(val, min, max, 1, 1, 1);
 	spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0);
 	g_object_set_data(G_OBJECT(spin), "val", (char *)key);
@@ -113,21 +102,11 @@
 		gtk_widget_set_size_request(spin, 50, -1);
 	else
 		gtk_widget_set_size_request(spin, 60, -1);
-	gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
 	g_signal_connect(G_OBJECT(adjust), "value-changed",
 					 G_CALLBACK(update_spin_value), GTK_WIDGET(spin));
 	gtk_widget_show(spin);
 
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), spin);
-
-	if (sg) {
-		gtk_size_group_add_widget(sg, label);
-		gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-	}
-
-	pidgin_set_accessible_label (spin, label);
-
-	return hbox;
+	return pidgin_add_widget_to_vbox(GTK_BOX(box), title, sg, spin, FALSE, NULL);
 }
 
 static void
@@ -141,37 +120,18 @@
 pidgin_prefs_labeled_entry(GtkWidget *page, const gchar *title,
 							 const char *key, GtkSizeGroup *sg)
 {
-	GtkWidget *hbox, *label, *entry;
+	GtkWidget *entry;
 	const gchar *value;
 
 	value = purple_prefs_get_string(key);
 
-	hbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(page), hbox, FALSE, FALSE, 0);
-	gtk_widget_show(hbox);
-
-	label = gtk_label_new_with_mnemonic(title);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_widget_show(label);
-
 	entry = gtk_entry_new();
 	gtk_entry_set_text(GTK_ENTRY(entry), value);
-	gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
 	g_signal_connect(G_OBJECT(entry), "changed",
 					 G_CALLBACK(entry_set), (char*)key);
 	gtk_widget_show(entry);
 
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry);
-
-	if(sg) {
-		gtk_size_group_add_widget(sg, label);
-		gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-	}
-
-	pidgin_set_accessible_label(entry, label);
-
-	return hbox;
+	return pidgin_add_widget_to_vbox(GTK_BOX(page), title, sg, entry, TRUE, NULL);
 }
 
 static void
@@ -205,7 +165,6 @@
 {
 	GtkWidget  *dropdown, *opt, *menu;
 	GtkWidget  *label = NULL;
-	GtkWidget  *hbox;
 	gchar      *text;
 	const char *stored_str = NULL;
 	int         stored_int = 0;
@@ -215,19 +174,6 @@
 
 	g_return_val_if_fail(menuitems != NULL, NULL);
 
-	if (title != NULL) {
-		hbox = gtk_hbox_new(FALSE, 5);
-		/*gtk_container_add (GTK_CONTAINER (box), hbox);*/
-		gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
-		gtk_widget_show(hbox);
-
-		label = gtk_label_new_with_mnemonic(title);
-		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-		gtk_widget_show(label);
-	} else {
-		hbox = box;
-	}
-
 #if 0 /* GTK_CHECK_VERSION(2,4,0) */
 	if(type == PURPLE_PREF_INT)
 		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
@@ -239,11 +185,6 @@
 	menu = gtk_menu_new();
 #endif
 
-	if (label != NULL) {
-		gtk_label_set_mnemonic_widget(GTK_LABEL(label), dropdown);
-		pidgin_set_accessible_relations (dropdown, label);
-	}
-
 	if (type == PURPLE_PREF_INT)
 		stored_int = purple_prefs_get_int(key);
 	else if (type == PURPLE_PREF_STRING)
@@ -293,8 +234,8 @@
 	}
 
 	gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu);
-	gtk_box_pack_start(GTK_BOX(hbox), dropdown, FALSE, FALSE, 0);
-	gtk_widget_show(dropdown);
+
+	pidgin_add_widget_to_vbox(GTK_BOX(box), title, NULL, dropdown, FALSE, &label);
 
 	return label;
 }
@@ -412,7 +353,7 @@
 	gtk_tree_path_free(path);
 }
 
-static GtkTreeRowReference *theme_refresh_theme_list()
+static GtkTreeRowReference *theme_refresh_theme_list(void)
 {
 	GdkPixbuf *pixbuf;
 	GSList *themes;
@@ -676,7 +617,7 @@
 }
 
 static GtkWidget *
-theme_page()
+theme_page(void)
 {
 	GtkWidget *add_button, *remove_button;
 	GtkWidget *hbox_buttons;
@@ -877,7 +818,7 @@
 }
 
 static GtkWidget *
-interface_page()
+interface_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox;
@@ -970,7 +911,7 @@
 #endif
 
 static GtkWidget *
-conv_page()
+conv_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox;
@@ -983,7 +924,6 @@
 
 #if GTK_CHECK_VERSION(2,4,0)
 	GtkWidget *hbox;
-	GtkWidget *label;
 	GtkWidget *font_button;
 	const char *font_name;
 #endif
@@ -1026,19 +966,15 @@
 		fontpref = pidgin_prefs_checkbox(_("Use document font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox);
 	else
 		fontpref = pidgin_prefs_checkbox(_("Use font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox);
-	hbox = gtk_hbox_new(FALSE, 3);
-	label = gtk_label_new_with_mnemonic(_("Conversation _font:"));
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
 	font_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font");
 	font_button = gtk_font_button_new_with_font(font_name ? font_name : NULL);
 	gtk_font_button_set_show_style(GTK_FONT_BUTTON(font_button), TRUE);
-	gtk_box_pack_start(GTK_BOX(hbox), font_button, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Conversation _font:"), NULL, font_button, FALSE, NULL);
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font"))
 		gtk_widget_set_sensitive(hbox, FALSE);
 	g_signal_connect(G_OBJECT(fontpref), "clicked", G_CALLBACK(pidgin_toggle_sensitive), hbox);
 	g_signal_connect(G_OBJECT(font_button), "font-set", G_CALLBACK(pidgin_custom_font_set), NULL);
-	gtk_widget_show_all(hbox);
 #endif
 
 	vbox = pidgin_make_frame(ret, _("Default Formatting"));
@@ -1137,7 +1073,7 @@
 }
 
 static GtkWidget *
-network_page()
+network_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox, *hbox, *entry;
@@ -1411,7 +1347,7 @@
 	return FALSE;
 }
 
-static GList *get_available_browsers()
+static GList *get_available_browsers(void)
 {
 	struct browser {
 		char *name;
@@ -1477,7 +1413,7 @@
 }
 
 static GtkWidget *
-browser_page()
+browser_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox;
@@ -1520,28 +1456,16 @@
 									browser_changed1_cb, hbox);
 	}
 
-	hbox = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-	label = gtk_label_new_with_mnemonic(_("_Manual:\n(%s for URL)"));
-	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
-	gtk_size_group_add_widget(sg, label);
-
 	entry = gtk_entry_new();
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry);
-
 	if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser"), "custom"))
 		gtk_widget_set_sensitive(hbox, FALSE);
 	purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/browsers/browser",
 								browser_changed2_cb, hbox);
-
-	gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
-
 	gtk_entry_set_text(GTK_ENTRY(entry),
 					   purple_prefs_get_path(PIDGIN_PREFS_ROOT "/browsers/command"));
 	g_signal_connect(G_OBJECT(entry), "focus-out-event",
 					 G_CALLBACK(manual_browser_set), NULL);
-	pidgin_set_accessible_label (entry, label);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Manual:\n(%s for URL)"), sg, entry, TRUE, NULL);
 
 	gtk_widget_show_all(ret);
 	g_object_unref(sg);
@@ -1550,7 +1474,7 @@
 #endif /*_WIN32*/
 
 static GtkWidget *
-logging_page()
+logging_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox;
@@ -1778,7 +1702,7 @@
 }
 
 static GtkWidget *
-sound_page()
+sound_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox, *sw, *button;
@@ -1824,33 +1748,20 @@
 	gtk_size_group_add_widget(sg, dd);
 	gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5);
 
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("Sound c_ommand:\n(%s for filename)"));
-	gtk_size_group_add_widget(sg, label);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
 	entry = gtk_entry_new();
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), entry);
-
 	gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE);
 	cmd = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/sound/command");
 	if(cmd)
 		gtk_entry_set_text(GTK_ENTRY(entry), cmd);
-
-	gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
 	g_signal_connect(G_OBJECT(entry), "changed",
 					 G_CALLBACK(sound_cmd_yeah), NULL);
 
+	hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Sound c_ommand:\n(%s for filename)"), sg, entry, TRUE, NULL);
 	purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/sound/method",
 								sound_changed1_cb, hbox);
 	gtk_widget_set_sensitive(hbox,
 			!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"),
 					"custom"));
-
-	pidgin_set_accessible_label (entry, label);
 #endif /* _WIN32 */
 
 	vbox = pidgin_make_frame (ret, _("Sound Options"));
@@ -1864,13 +1775,6 @@
 				NULL);
 
 #ifdef USE_GSTREAMER
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("Volume:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
 	sw = gtk_hscale_new_with_range(0.0, 100.0, 5.0);
 	gtk_range_set_increments(GTK_RANGE(sw), 5.0, 25.0);
 	gtk_range_set_value(GTK_RANGE(sw), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/sound/volume"));
@@ -1880,7 +1784,7 @@
 	g_signal_connect (G_OBJECT (sw), "value-changed",
 			  G_CALLBACK (prefs_sound_volume_changed),
 			  NULL);
-	gtk_box_pack_start(GTK_BOX(hbox), sw, TRUE, TRUE, 0);
+	hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Volume:"), NULL, sw, TRUE, NULL);
 
 	purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/sound/method",
 								sound_changed3_cb, hbox);
@@ -2005,11 +1909,10 @@
 }
 
 static GtkWidget *
-away_page()
+away_page(void)
 {
 	GtkWidget *ret;
 	GtkWidget *vbox;
-	GtkWidget *hbox;
 	GtkWidget *dd;
 	GtkWidget *label;
 	GtkWidget *button;
@@ -2060,22 +1963,13 @@
 	g_signal_connect(G_OBJECT(button), "clicked",
 					 G_CALLBACK(pidgin_toggle_sensitive), select);
 
-	hbox = gtk_hbox_new(FALSE, 0);
-	gtk_container_add(GTK_CONTAINER(vbox), hbox);
-
-	label = gtk_label_new_with_mnemonic(_("Change _status to:"));
-	gtk_size_group_add_widget(sg, label);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+	/* TODO: Show something useful if we don't have any saved statuses. */
+	menu = pidgin_status_menu(purple_savedstatus_get_idleaway(), G_CALLBACK(set_idle_away));
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Change _status to:"), sg, menu, TRUE, &label);
+	g_signal_connect(G_OBJECT(button), "clicked",
+			 G_CALLBACK(pidgin_toggle_sensitive), menu);
 	g_signal_connect(G_OBJECT(button), "clicked",
 					 G_CALLBACK(pidgin_toggle_sensitive), label);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
-	/* TODO: Show something useful if we don't have any saved statuses. */
-	menu = pidgin_status_menu(purple_savedstatus_get_idleaway(), G_CALLBACK(set_idle_away));
-	gtk_box_pack_start(GTK_BOX(hbox), menu, FALSE, FALSE, 0);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(pidgin_toggle_sensitive), menu);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), menu);
 
 	if (!purple_prefs_get_bool("/purple/away/away_when_idle")) {
 		gtk_widget_set_sensitive(GTK_WIDGET(menu), FALSE);
@@ -2089,22 +1983,13 @@
 	button = pidgin_prefs_checkbox(_("Use status from last _exit at startup"),
 		"/purple/savedstatus/startup_current_status", vbox);
 
-	hbox = gtk_hbox_new(FALSE, 0);
-	gtk_container_add(GTK_CONTAINER(vbox), hbox);
-
-	label = gtk_label_new_with_mnemonic(_("Status to a_pply at startup:"));
-	gtk_size_group_add_widget(sg, label);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+	/* TODO: Show something useful if we don't have any saved statuses. */
+	menu = pidgin_status_menu(purple_savedstatus_get_startup(), G_CALLBACK(set_startupstatus));
+	g_signal_connect(G_OBJECT(button), "clicked",
+			 G_CALLBACK(pidgin_toggle_sensitive), menu);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Status to a_pply at startup:"), sg, menu, TRUE, &label);
 	g_signal_connect(G_OBJECT(button), "clicked",
 					 G_CALLBACK(pidgin_toggle_sensitive), label);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
-	/* TODO: Show something useful if we don't have any saved statuses. */
-	menu = pidgin_status_menu(purple_savedstatus_get_startup(), G_CALLBACK(set_startupstatus));
-	gtk_box_pack_start(GTK_BOX(hbox), menu, FALSE, FALSE, 0);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(pidgin_toggle_sensitive), menu);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), menu);
 
 	if (purple_prefs_get_bool("/purple/savedstatus/startup_current_status")) {
 		gtk_widget_set_sensitive(GTK_WIDGET(menu), FALSE);
@@ -2130,7 +2015,7 @@
 #endif
 }
 
-static void prefs_notebook_init() {
+static void prefs_notebook_init(void) {
 	prefs_notebook_add_page(_("Interface"), interface_page(), notebook_page++);
 	prefs_notebook_add_page(_("Conversations"), conv_page(), notebook_page++);
 	prefs_notebook_add_page(_("Smiley Themes"), theme_page(), notebook_page++);
--- a/pidgin/gtkprivacy.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkprivacy.c	Tue Jan 08 13:17:59 2008 +0000
@@ -359,7 +359,6 @@
 privacy_dialog_new(void)
 {
 	PidginPrivacyDialog *dialog;
-	GtkWidget *hbox;
 	GtkWidget *vbox;
 	GtkWidget *button;
 	GtkWidget *dropdown;
@@ -386,22 +385,10 @@
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_widget_show(label);
 
-	/* Hbox for the accounts drop-down and label. */
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-	gtk_widget_show(hbox);
-
-	/* "Set privacy for:" label */
-	label = gtk_label_new(_("Set privacy for:"));
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_widget_show(label);
-
 	/* Accounts drop-down */
 	dropdown = pidgin_account_option_menu_new(NULL, FALSE,
 												G_CALLBACK(select_account_cb), NULL, dialog);
-	gtk_box_pack_start(GTK_BOX(hbox), dropdown, FALSE, FALSE, 0);
-	gtk_widget_show(dropdown);
-	pidgin_set_accessible_label (dropdown, label);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("Set privacy for:"), NULL, dropdown, TRUE, NULL);
 	dialog->account = pidgin_account_option_menu_get_selected(dropdown);
 
 	/* Add the drop-down list with the allow/block types. */
--- a/pidgin/gtkroomlist.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkroomlist.c	Tue Jan 08 13:17:59 2008 +0000
@@ -521,9 +521,7 @@
 	GtkWidget *window;
 	GtkWidget *vbox;
 	GtkWidget *vbox2;
-	GtkWidget *account_hbox;
 	GtkWidget *bbox;
-	GtkWidget *label;
 
 	dialog = g_new0(PidginRoomlistDialog, 1);
 	dialog->account = account;
@@ -542,25 +540,11 @@
 	gtk_widget_show(vbox2);
 
 	/* accounts dropdown list */
-	account_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox2), account_hbox, FALSE, FALSE, 0);
-	gtk_widget_show(account_hbox);
-
-	label = gtk_label_new(NULL);
-	gtk_box_pack_start(GTK_BOX(account_hbox), label, FALSE, FALSE, 0);
-	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Account:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_widget_show(label);
-
 	dialog->account_widget = pidgin_account_option_menu_new(dialog->account, FALSE,
 	                         G_CALLBACK(dialog_select_account_cb), account_filter_func, dialog);
-
 	if (!dialog->account) /* this is normally null, and we normally don't care what the first selected item is */
 		dialog->account = pidgin_account_option_menu_get_selected(dialog->account_widget);
-
-	gtk_box_pack_start(GTK_BOX(account_hbox), dialog->account_widget, TRUE, TRUE, 0);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(dialog->account_widget));
-	gtk_widget_show(dialog->account_widget);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox2), _("_Account:"), NULL, dialog->account_widget, TRUE, NULL);
 
 	/* scrolled window */
 	dialog->sw = gtk_scrolled_window_new(NULL, NULL);
--- a/pidgin/gtksavedstatuses.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Tue Jan 08 13:17:59 2008 +0000
@@ -1092,7 +1092,6 @@
 	GtkWidget *entry;
 	GtkWidget *frame;
 	GtkWidget *hbox;
-	GtkWidget *label;
 	GtkWidget *sw;
 	GtkWidget *text;
 	GtkWidget *toolbar;
@@ -1141,52 +1140,29 @@
 	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
 	/* Title */
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("_Title:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(sg, label);
-
 	entry = gtk_entry_new();
 	dialog->title = GTK_ENTRY(entry);
 	if ((saved_status != NULL)
 			&& !purple_savedstatus_is_transient(saved_status)
 			&& (purple_savedstatus_get_title(saved_status) != NULL))
 		gtk_entry_set_text(GTK_ENTRY(entry), purple_savedstatus_get_title(saved_status));
-	gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
 	g_signal_connect(G_OBJECT(entry), "changed",
 					 G_CALLBACK(editor_title_changed_cb), dialog);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Title:"), sg, entry, TRUE, NULL);
 
 	/* Status type */
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("_Status:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(sg, label);
-
 	if (saved_status != NULL)
 		dropdown = create_status_type_menu(purple_savedstatus_get_type(saved_status));
 	else
 		dropdown = create_status_type_menu(PURPLE_STATUS_AWAY);
 	dialog->type = GTK_OPTION_MENU(dropdown);
-	gtk_box_pack_start(GTK_BOX(hbox), dropdown, TRUE, TRUE, 0);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Status:"), sg, dropdown, TRUE, NULL);
 
 	/* Status message */
-	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
-
-	label = gtk_label_new_with_mnemonic(_("_Message:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(sg, label);
-
 	frame = pidgin_create_imhtml(TRUE, &text, &toolbar, NULL);
 	dialog->message = GTK_IMHTML(text);
-	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
+	hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Message:"), sg, frame, TRUE, NULL);
+	gtk_container_child_set(GTK_CONTAINER(vbox), hbox, "expand", TRUE, "fill", TRUE, NULL);
 	focus_chain = g_list_prepend(focus_chain, dialog->message);
 	gtk_container_set_focus_chain(GTK_CONTAINER(hbox), focus_chain);
 	g_list_free(focus_chain);
--- a/pidgin/gtksession.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtksession.c	Tue Jan 08 13:17:59 2008 +0000
@@ -124,7 +124,7 @@
 	purple_debug(PURPLE_DEBUG_INFO, NULL, "done.\n");
 }
 
-static void ice_init() {
+static void ice_init(void) {
 	IceIOErrorHandler default_handler;
 
 	ice_installed_io_error_handler = IceSetIOErrorHandler(NULL);
--- a/pidgin/gtkstatusbox.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Tue Jan 08 13:17:59 2008 +0000
@@ -119,7 +119,10 @@
 	DATA_COLUMN,
 
 	/**
- 	 * This column stores the GdkPixbuf for the status emblem. Currently only 'saved' is stored
+ 	 * This column stores the GdkPixbuf for the status emblem. Currently only 'saved' is stored.
+	 * In the GtkTreeModel for the dropdown, this is the stock-id (gchararray), and for the
+	 * GtkTreeModel for the cell_view (for the account-specific statusbox), this is the prpl-icon
+	 * (GdkPixbuf) of the account.
  	 */
 	EMBLEM_COLUMN,
 
@@ -606,7 +609,7 @@
 	char aa_color[8];
 	PurpleSavedStatus *saved_status;
 	char *primary, *secondary, *text;
-	GdkPixbuf *pixbuf;
+	GdkPixbuf *pixbuf, *emblem = NULL;
 	GtkTreePath *path;
 	gboolean account_status = FALSE;
 	PurpleAccount *acct = (status_box->token_status_account) ? status_box->token_status_account : status_box->account;
@@ -703,6 +706,7 @@
 		text = g_strdup_printf("%s - <span size=\"smaller\" color=\"%s\">%s</span>",
 				       purple_account_get_username(status_box->account),
 				       aa_color, secondary ? secondary : primary);
+		emblem = pidgin_create_prpl_icon(status_box->account, PIDGIN_PRPL_ICON_SMALL);
 	} else if (secondary != NULL) {
 		text = g_strdup_printf("%s<span size=\"smaller\" color=\"%s\"> - %s</span>",
 				       primary, aa_color, secondary);
@@ -719,10 +723,14 @@
 	gtk_list_store_set(status_box->store, &(status_box->iter),
 			   ICON_COLUMN, pixbuf,
 			   TEXT_COLUMN, text,
+			   EMBLEM_COLUMN, emblem,
+			   EMBLEM_VISIBLE_COLUMN, (emblem != NULL),
 			   -1);
 	if ((status_box->typing == 0) && (!status_box->connecting))
 		g_object_unref(pixbuf);
 	g_free(text);
+	if (emblem)
+		g_object_unref(emblem);
 
 	/* Make sure to activate the only row in the tree view */
 	path = gtk_tree_path_new_from_string("0");
@@ -941,7 +949,7 @@
 
 /* This returns NULL if the active accounts don't have identical
  * statuses and a token account if they do */
-static PurpleAccount* check_active_accounts_for_identical_statuses()
+static PurpleAccount* check_active_accounts_for_identical_statuses(void)
 {
 	PurpleAccount *acct = NULL, *acct2;
 	GList *tmp, *tmp2, *active_accts = purple_accounts_get_all_active();
@@ -1690,7 +1698,7 @@
 	status_box->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
 
 	status_box->store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, 
-					       G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
+					       G_TYPE_STRING, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
 	status_box->dropdown_store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING, 
 							G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
@@ -1775,10 +1783,13 @@
 
 	status_box->icon_rend = gtk_cell_renderer_pixbuf_new();
 	status_box->text_rend = gtk_cell_renderer_text_new();
+	emblem_rend = gtk_cell_renderer_pixbuf_new();
 	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, FALSE);
 	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, TRUE);
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(status_box->cell_view), emblem_rend, FALSE);
 	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->icon_rend, "pixbuf", ICON_COLUMN, NULL);
 	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), status_box->text_rend, "markup", TEXT_COLUMN, NULL);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(status_box->cell_view), emblem_rend, "pixbuf", EMBLEM_COLUMN, "visible", EMBLEM_VISIBLE_COLUMN, NULL);
 #if GTK_CHECK_VERSION(2, 6, 0)
 	g_object_set(status_box->text_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 #endif
--- a/pidgin/gtkthemes.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkthemes.c	Tue Jan 08 13:17:59 2008 +0000
@@ -168,7 +168,7 @@
 }
 
 static void
-pidgin_smiley_themes_remove_non_existing()
+pidgin_smiley_themes_remove_non_existing(void)
 {
 	static struct smiley_theme *theme = NULL;
 	GSList *iter = NULL;
--- a/pidgin/gtkutils.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkutils.c	Tue Jan 08 13:17:59 2008 +0000
@@ -1701,23 +1701,23 @@
 	GdkPixbuf *pixbuf = NULL;
 
 	if (prim == PURPLE_STATUS_UNAVAILABLE)
-        	pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_BUSY,
-                                                 icon_size, "GtkWidget");
-        else if (prim == PURPLE_STATUS_AWAY)
-                pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AWAY,
-                                                 icon_size, "GtkWidget");
-        else if (prim == PURPLE_STATUS_EXTENDED_AWAY)
-                pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_XA,
-                                                 icon_size, "GtkWidget");
-        else if (prim == PURPLE_STATUS_INVISIBLE)
-                pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_INVISIBLE,
-                                                 icon_size, "GtkWidget");
-        else if (prim == PURPLE_STATUS_OFFLINE)
-                pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_OFFLINE,
-                                                 icon_size, "GtkWidget");
-        else
-                pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AVAILABLE,
-                                                 icon_size, "GtkWidget");
+		pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_BUSY,
+				icon_size, "GtkWidget");
+	else if (prim == PURPLE_STATUS_AWAY)
+		pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AWAY,
+				icon_size, "GtkWidget");
+	else if (prim == PURPLE_STATUS_EXTENDED_AWAY)
+		pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_XA,
+				icon_size, "GtkWidget");
+	else if (prim == PURPLE_STATUS_INVISIBLE)
+		pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_INVISIBLE,
+				icon_size, "GtkWidget");
+	else if (prim == PURPLE_STATUS_OFFLINE)
+		pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_OFFLINE,
+				icon_size, "GtkWidget");
+	else
+		pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AVAILABLE,
+				icon_size, "GtkWidget");
 	return pixbuf;
 
 }
@@ -2947,7 +2947,7 @@
 GSList *minidialogs = NULL;
 
 static void *
-pidgin_utils_get_handle()
+pidgin_utils_get_handle(void)
 {
 	static int handle;
 
@@ -3321,6 +3321,40 @@
 	gtk_entry_set_text(GTK_ENTRY(GTK_BIN((widget))->child), (text));
 }
 
+GtkWidget *
+pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label)
+{
+	GtkWidget *hbox;
+	GtkWidget *label = NULL;
+
+	if (widget_label) {
+		hbox = gtk_hbox_new(FALSE, 5);
+		gtk_widget_show(hbox);
+		gtk_box_pack_start(vbox, hbox, FALSE, FALSE, 0);
+
+		label = gtk_label_new_with_mnemonic(widget_label);
+		gtk_widget_show(label);
+		if (sg) {
+			gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+			gtk_size_group_add_widget(sg, label);
+		}
+		gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	} else {
+		hbox = GTK_WIDGET(vbox);
+	}
+
+	gtk_widget_show(widget);
+	gtk_box_pack_start(GTK_BOX(hbox), widget, expand, TRUE, 0);
+	if (label) {
+		gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget);
+		pidgin_set_accessible_label (widget, label);
+	}
+
+	if (p_label)
+		(*p_label) = label;
+	return hbox;
+}
+
 gboolean pidgin_auto_parent_window(GtkWidget *widget)
 {
 #if 0
--- a/pidgin/gtkutils.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/gtkutils.h	Tue Jan 08 13:17:59 2008 +0000
@@ -374,16 +374,20 @@
 gboolean pidgin_screenname_autocomplete_default_filter(const PidginBuddyCompletionEntry *completion_entry, gpointer all_accounts);
 
 /**
+ * Add autocompletion of screenames to an entry.
+ *
  * @deprecated
- * Add autocompletion of screenames to an entry.
- * The usage of this function is deprecated. For new code, use the equivalent:
- * pidgin_setup_screenname_autocomplete_with_filter(entry, optmenu, pidgin_screenname_autocomplete_default_filter, GINT_TO_POINTER(all))
+ *   For new code, use the equivalent:
+ *   #pidgin_setup_screenname_autocomplete_with_filter(@a entry, @a optmenu,
+ *   #pidgin_screenname_autocomplete_default_filter, <tt>GINT_TO_POINTER(@a
+ *   all)</tt>)
  *
  * @param entry     The GtkEntry on which to setup autocomplete.
- * @param optmenu   A menu for accounts, returned by pidgin_account_option_menu_new().
- *                  If @a optmenu is not @c NULL, it'll be updated when a screenname is chosen
- *                  from the autocomplete list.
- * @param all       Whether to include screennames from disconnected accounts. 
+ * @param optmenu   A menu for accounts, returned by
+ *                  pidgin_account_option_menu_new().  If @a optmenu is not @c
+ *                  NULL, it'll be updated when a screenname is chosen from the
+ *                  autocomplete list.
+ * @param all       Whether to include screennames from disconnected accounts.
  */
 void pidgin_setup_screenname_autocomplete(GtkWidget *entry, GtkWidget *optmenu, gboolean all);
 
@@ -506,7 +510,7 @@
 
 /**
  * A valid GtkMenuPositionFunc.  This is used to determine where 
- * to draw context menu's when the menu is activated with the 
+ * to draw context menus when the menu is activated with the 
  * keyboard (shift+F10).  If the menu is activated with the mouse, 
  * then you should just use GTK's built-in position function, 
  * because it does a better job of positioning the menu.
@@ -790,5 +794,20 @@
  */
 gboolean pidgin_auto_parent_window(GtkWidget *window);
 
+/**
+ * Add a labelled widget to a GtkVBox
+ *
+ * @param vbox         The GtkVBox to add the widget to.
+ * @param widget_label The label to give the widget.
+ * @param sg           The GtkSizeGroup to add the label to.
+ * @param widget       The GtkWidget to add
+ * @param expand       Whether to expand the widget horizontally.
+ * @param p_label      Place to store a pointer to the GtkLabel, or NULL if you don't care.
+ *
+ * @return  A GtkHBox already added to the GtkVBox containing the GtkLabel and the GtkWidget.
+ * @since 2.4.0
+ */
+GtkWidget *pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label);
+
 #endif /* _PIDGINUTILS_H_ */
 
--- a/pidgin/pidgintooltip.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/pidgintooltip.c	Tue Jan 08 13:17:59 2008 +0000
@@ -86,7 +86,7 @@
 }
 
 static GtkWidget*
-setup_tooltip_window()
+setup_tooltip_window(void)
 {
 	const char *name;
 	GtkWidget *tipwindow;
--- a/pidgin/plugins/cap/cap.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/cap/cap.c	Tue Jan 08 13:17:59 2008 +0000
@@ -434,26 +434,6 @@
 	stats->last_seen = time(NULL);
 }
 
-static void buddy_idle(PurpleBuddy *buddy, gboolean old_idle, gboolean idle) {
-}
-
-#if 0
-static void blist_node_extended_menu(PurpleBlistNode *node, GList **menu) {
-	PurpleBuddy *buddy;
-	PurpleMenuAction *menu_action;
-	purple_debug_info("cap", "got extended blist menu\n");
-	purple_debug_info("cap", "is buddy: %d\n", PURPLE_BLIST_NODE_IS_BUDDY(node));
-	purple_debug_info("cap", "is contact: %d\n", PURPLE_BLIST_NODE_IS_CONTACT(node));
-	purple_debug_info("cap", "is group: %d\n", PURPLE_BLIST_NODE_IS_GROUP(node));
-	/* Probably only concerned with buddy/contact types. Contacts = meta-buddies (grouped msn/jabber/etc.) */
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-	buddy = (PurpleBuddy *)node;
-	menu_action = purple_menu_action_new(_("Display Statistics"),
-			PURPLE_CALLBACK(display_statistics_action_cb), NULL, NULL);
-	*menu = g_list_append(*menu, menu_action);
-}
-#endif
-
 /* drawing-tooltip */
 static void drawing_tooltip(PurpleBlistNode *node, GString *text, gboolean full) {
 	if(node->type == PURPLE_BLIST_BUDDY_NODE) {
@@ -662,15 +642,6 @@
 	/* result = dbi_conn_queryf(_conn, "insert into cap_message values(\'%s\', \'%s\', %d, now());", sender, receiver, count); */
 }
 
-/* Callbacks */
-void display_statistics_action_cb(PurpleBlistNode *node, gpointer data) {
-	PurpleBuddy *buddy;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-	buddy = (PurpleBuddy *)node;
-	purple_debug_info("cap", "Statistics for %s requested.\n", buddy->name);
-}
-
 /* Purple plugin specific code */
 
 static gboolean plugin_load(PurplePlugin *plugin) {
@@ -714,9 +685,6 @@
 	purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", plugin,
 			PURPLE_CALLBACK(buddy_signed_off), NULL);
 
-	/*purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu", plugin,
-			PURPLE_CALLBACK(blist_node_extended_menu), NULL);*/
-
 	purple_signal_connect(pidgin_blist_get_handle(), "drawing-tooltip", plugin,
 			PURPLE_CALLBACK(drawing_tooltip), NULL);
 
@@ -726,9 +694,6 @@
 	purple_signal_connect(purple_connections_get_handle(), "signed-off", plugin,
 			PURPLE_CALLBACK(signed_off), NULL);
 
-	purple_signal_connect(purple_blist_get_handle(), "buddy-idle-changed", plugin,
-			PURPLE_CALLBACK(buddy_idle), NULL);
-
 	_signals_connected = TRUE;
 }
 
@@ -765,9 +730,6 @@
 	purple_signal_disconnect(purple_blist_get_handle(), "buddy-signed-off", plugin,
 			PURPLE_CALLBACK(buddy_signed_off));
 
-	/*purple_signal_disconnect(purple_blist_get_handle(), "blist-node-extended-menu", plugin,
-			PURPLE_CALLBACK(blist_node_extended_menu));*/
-
 	purple_signal_disconnect(pidgin_blist_get_handle(), "drawing-tooltip", plugin,
 			PURPLE_CALLBACK(drawing_tooltip));
 
@@ -777,9 +739,6 @@
 	purple_signal_disconnect(purple_connections_get_handle(), "signed-off", plugin,
 			PURPLE_CALLBACK(signed_off));
 
-	purple_signal_disconnect(purple_blist_get_handle(), "buddy-idle-changed", plugin,
-			PURPLE_CALLBACK(buddy_idle));
-
 	_signals_connected = FALSE;
 }
 
--- a/pidgin/plugins/cap/cap.h	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/cap/cap.h	Tue Jan 08 13:17:59 2008 +0000
@@ -98,7 +98,6 @@
 static void buddy_signed_on(PurpleBuddy *buddy);
 /* buddy-signed-off */
 static void buddy_signed_off(PurpleBuddy *buddy);
-static void buddy_idle(PurpleBuddy *buddy, gboolean old_idle, gboolean idle);
 /* drawing-tooltip */
 static void drawing_tooltip(PurpleBlistNode *node, GString *text, gboolean full);
 /* signed-on */
@@ -107,21 +106,20 @@
 static void signed_off(PurpleConnection *gc);
 static void reset_all_last_message_times(gpointer key, gpointer value, gpointer user_data);
 static PurpleStatus * get_status_for(PurpleBuddy *buddy);
-static void create_tables();
-static gboolean create_database_connection();
-static void destroy_database_connection();
+static void create_tables(void);
+static gboolean create_database_connection(void);
+static void destroy_database_connection(void);
 static guint word_count(const gchar *string);
 static void insert_status_change(CapStatistics *statistics);
 static void insert_status_change_from_purple_status(CapStatistics *statistics, PurpleStatus *status);
 static void insert_word_count(const char *sender, const char *receiver, guint count);
-void display_statistics_action_cb(PurpleBlistNode *node, gpointer data);
 static gboolean plugin_load(PurplePlugin *plugin);
 static void add_plugin_functionality(PurplePlugin *plugin);
 static void cancel_conversation_timeouts(gpointer key, gpointer value, gpointer user_data);
 static void remove_plugin_functionality(PurplePlugin *plugin);
 static void write_stats_on_unload(gpointer key, gpointer value, gpointer user_data);
 static gboolean plugin_unload(PurplePlugin *plugin);
-static CapPrefsUI * create_cap_prefs_ui();
+static CapPrefsUI * create_cap_prefs_ui(void);
 static void cap_prefs_ui_destroy_cb(GtkObject *object, gpointer user_data);
 static void numeric_spinner_prefs_cb(GtkSpinButton *spinbutton, gpointer user_data);
 static GtkWidget * get_config_frame(PurplePlugin *plugin);
--- a/pidgin/plugins/markerline.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/markerline.c	Tue Jan 08 13:17:59 2008 +0000
@@ -190,13 +190,13 @@
 }
 
 static void
-detach_from_all_windows()
+detach_from_all_windows(void)
 {
 	g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)detach_from_pidgin_window, NULL);
 }
 
 static void
-attach_to_all_windows()
+attach_to_all_windows(void)
 {
 	g_list_foreach(pidgin_conv_windows_get_list(), (GFunc)attach_to_pidgin_window, NULL);
 }
--- a/pidgin/plugins/pidginrc.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/pidginrc.c	Tue Jan 08 13:17:59 2008 +0000
@@ -95,7 +95,7 @@
 */
 
 static GString *
-make_gtkrc_string()
+make_gtkrc_string(void)
 {
 	gint i;
 	gchar *prefbase = NULL;
@@ -185,7 +185,7 @@
 }
 
 static void
-purplerc_make_changes()
+purplerc_make_changes(void)
 {
 	GString *str = make_gtkrc_string();
 #if GTK_CHECK_VERSION(2,4,0)
--- a/pidgin/plugins/spellchk.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/spellchk.c	Tue Jan 08 13:17:59 2008 +0000
@@ -695,7 +695,7 @@
 	return 1;
 }
 
-static void load_conf()
+static void load_conf(void)
 {
 	/* Corrections to change "...", "(c)", "(r)", and "(tm)" to their
 	 * Unicode character equivalents were not added here even though
@@ -1912,7 +1912,7 @@
 	save_list();
 }
 
-static void list_add_new()
+static void list_add_new(void)
 {
 	GtkTreeIter iter;
 	const char *word = gtk_entry_get_text(GTK_ENTRY(bad_entry));
@@ -2015,7 +2015,7 @@
 	gtk_tree_row_reference_free(row_reference);
 }
 
-static void list_delete()
+static void list_delete(void)
 {
 	GtkTreeSelection *sel;
 	GSList *list = NULL;
@@ -2161,14 +2161,13 @@
 get_config_frame(PurplePlugin *plugin)
 {
 	GtkWidget *ret, *vbox, *win;
-	GtkWidget *hbox, *label;
+	GtkWidget *hbox;
 	GtkWidget *button;
 	GtkSizeGroup *sg;
 	GtkSizeGroup *sg2;
 	GtkCellRenderer *renderer;
 	GtkTreeViewColumn *column;
 	GtkWidget *vbox2;
-	GtkWidget *hbox2;
 	GtkWidget *vbox3;
 
 	ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
@@ -2275,37 +2274,15 @@
 	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 	sg2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
-	hbox2 = gtk_hbox_new(FALSE, 2);
-	gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0);
-	gtk_widget_show(hbox2);
-
-	label = gtk_label_new_with_mnemonic(_("You _type:"));
-	gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(sg, label);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
-
 	bad_entry = gtk_entry_new();
 	/* Set a minimum size. Since they're in a size group, the other entry will match up. */
 	gtk_widget_set_size_request(bad_entry, 350, -1);
-	gtk_box_pack_start(GTK_BOX(hbox2), bad_entry, TRUE, TRUE, 0);
 	gtk_size_group_add_widget(sg2, bad_entry);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), bad_entry);
-	gtk_widget_show(bad_entry);
-
-	hbox2 = gtk_hbox_new(FALSE, 2);
-	gtk_box_pack_start(GTK_BOX(vbox2), hbox2, FALSE, FALSE, 0);
-	gtk_widget_show(hbox2);
-
-	label = gtk_label_new_with_mnemonic(_("You _send:"));
-	gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0);
-	gtk_size_group_add_widget(sg, label);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox2), _("You _type:"), sg, bad_entry, FALSE, NULL);
 
 	good_entry = gtk_entry_new();
-	gtk_box_pack_start(GTK_BOX(hbox2), good_entry, TRUE, TRUE, 0);
 	gtk_size_group_add_widget(sg2, good_entry);
-	gtk_label_set_mnemonic_widget(GTK_LABEL(label), good_entry);
-	gtk_widget_show(good_entry);
+	pidgin_add_widget_to_vbox(GTK_BOX(vbox2), _("You _send:"), sg, good_entry, FALSE, NULL);
 
 	/* Created here so it can be passed to whole_words_button_toggled. */
 	case_toggle = gtk_check_button_new_with_mnemonic(_("_Exact case match (uncheck for automatic case handling)"));
--- a/pidgin/plugins/ticker/ticker.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/ticker/ticker.c	Tue Jan 08 13:17:59 2008 +0000
@@ -65,7 +65,7 @@
 	return TRUE; /* don't actually destroy the window */
 }
 
-static void buddy_ticker_create_window() {
+static void buddy_ticker_create_window(void) {
 	if(tickerwindow) {
 		gtk_widget_show(tickerwindow);
 		return;
@@ -215,7 +215,7 @@
 	buddy_ticker_update_contact(c);
 }
 
-static void buddy_ticker_show()
+static void buddy_ticker_show(void)
 {
 	PurpleBuddyList *list = purple_get_blist();
 	PurpleBlistNode *gnode, *cnode, *bnode;
--- a/pidgin/plugins/xmppconsole.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/plugins/xmppconsole.c	Tue Jan 08 13:17:59 2008 +0000
@@ -727,7 +727,7 @@
 }
 
 static void 
-create_console() 
+create_console(PurplePluginAction *action) 
 {
 	GtkWidget *vbox = gtk_vbox_new(FALSE, 6);
 	GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
--- a/pidgin/win32/winpidgin.c	Sun Dec 30 23:52:38 2007 +0000
+++ b/pidgin/win32/winpidgin.c	Tue Jan 08 13:17:59 2008 +0000
@@ -450,23 +450,25 @@
 
 	if ((h = CreateMutex(NULL, FALSE, "pidgin_is_running"))) {
 		DWORD err = GetLastError();
-		if (err == ERROR_ALREADY_EXISTS && fail_if_running) {
-			HWND msg_win;
+		if (err == ERROR_ALREADY_EXISTS) {
+			if (fail_if_running) {
+				HWND msg_win;
 
-			printf("An instance of Pidgin is already running.\n");
+				printf("An instance of Pidgin is already running.\n");
 
-			if((msg_win = FindWindowEx(HWND_MESSAGE, NULL, TEXT("WinpidginMsgWinCls"), NULL)))
-				if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL))
-					return FALSE;
+				if((msg_win = FindWindowEx(HWND_MESSAGE, NULL, TEXT("WinpidginMsgWinCls"), NULL)))
+					if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL))
+						return FALSE;
 
-			/* If we get here, the focus request wasn't successful */
+				/* If we get here, the focus request wasn't successful */
 
-			MessageBox(NULL,
-				"An instance of Pidgin is already running",
-				NULL, MB_OK | MB_TOPMOST);
+				MessageBox(NULL,
+					"An instance of Pidgin is already running",
+					NULL, MB_OK | MB_TOPMOST);
 
-			return FALSE;
-		} else
+				return FALSE;
+			}
+		} else if (err != ERROR_SUCCESS)
 			printf("Error (%u) accessing \"pidgin_is_running\" mutex.\n", (UINT) err);
 	}
 	return TRUE;
--- a/po/POTFILES.in	Sun Dec 30 23:52:38 2007 +0000
+++ b/po/POTFILES.in	Tue Jan 08 13:17:59 2008 +0000
@@ -12,6 +12,7 @@
 finch/gntpounce.c
 finch/gntprefs.c
 finch/gntrequest.c
+finch/gntroomlist.c
 finch/gntsound.c
 finch/gntstatus.c
 finch/gntui.c
--- a/po/check_po.pl	Sun Dec 30 23:52:38 2007 +0000
+++ b/po/check_po.pl	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl -w
 #
 # check_po.pl  -  check po file translations for likely errors
 #
--- a/po/de.po	Sun Dec 30 23:52:38 2007 +0000
+++ b/po/de.po	Tue Jan 08 13:17:59 2008 +0000
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-12-19 10:17+0100\n"
-"PO-Revision-Date: 2007-12-19 10:17+0100\n"
+"POT-Creation-Date: 2008-01-08 11:16+0100\n"
+"PO-Revision-Date: 2008-01-08 11:15+0100\n"
 "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -1022,6 +1022,16 @@
 msgid "Choose Location..."
 msgstr "Wählen Sie einen Ort..."
 
+msgid "Hit 'Enter' to find more rooms of this category."
+msgstr "Drücken Sie 'Enter', um mehr Räume dieser Kategorie zu finden."
+
+msgid "Get"
+msgstr "Holen"
+
+#. Create the window.
+msgid "Room List"
+msgstr "Raumliste"
+
 msgid "Buddy logs in"
 msgstr "Buddy meldet sich an"
 
@@ -1436,19 +1446,6 @@
 msgstr "Ze_rtifikat ansehen..."
 
 #. Prompt the user to authenticate the certificate
-#. TODO: Provide the user with more guidance about why he is
-#. being prompted
-#. vrq will be completed by user_auth
-#, c-format
-msgid ""
-"The certificate presented by \"%s\" claims to be from \"%s\" instead.  This "
-"could mean that you are not connecting to the service you believe you are."
-msgstr ""
-"Das Zertifikat, welches von „%s“ präsentiert wurde, behauptet stattdessen "
-"von „%s“ zu kommen.  Das kann bedeuten, dass Sie tatsächlich nicht mit dem "
-"Dienst verbunden sind, mit dem Sie glauben verbunden zu sein."
-
-#. Prompt the user to authenticate the certificate
 #. vrq will be completed by user_auth
 #, c-format
 msgid ""
@@ -1498,6 +1495,19 @@
 msgid "Invalid certificate authority signature"
 msgstr "Unbekannte Zertifizierungsstellensignatur"
 
+#. Prompt the user to authenticate the certificate
+#. TODO: Provide the user with more guidance about why he is
+#. being prompted
+#. vrq will be completed by user_auth
+#, c-format
+msgid ""
+"The certificate presented by \"%s\" claims to be from \"%s\" instead.  This "
+"could mean that you are not connecting to the service you believe you are."
+msgstr ""
+"Das Zertifikat, welches von „%s“ präsentiert wurde, behauptet stattdessen "
+"von „%s“ zu kommen.  Das kann bedeuten, dass Sie tatsächlich nicht mit dem "
+"Dienst verbunden sind, mit dem Sie glauben verbunden zu sein."
+
 #. Make messages
 #, c-format
 msgid ""
@@ -3285,6 +3295,10 @@
 msgid "nickserv: Send a command to nickserv"
 msgstr "nickserv: Sendet ein Kommando zum Nickserv"
 
+msgid "notice &lt;target&lt;:  Send a notice to a user or channel."
+msgstr ""
+"notice &lt;Ziel&gt;:  Sende eine Notiz an einen Benutzer oder an einen Kanal."
+
 msgid ""
 "op &lt;nick1&gt; [nick2] ...:  Grant channel operator status to someone. You "
 "must be a channel operator to do this."
@@ -3971,8 +3985,8 @@
 msgid "Mood"
 msgstr "Stimmung"
 
-msgid "Current media"
-msgstr "Aktuelles Medium"
+msgid "Now Listening"
+msgstr "Hört gerade"
 
 msgid "Mood Text"
 msgstr "Stimmungstext"
@@ -9632,6 +9646,14 @@
 msgid "Unable to connect to %s: %s"
 msgstr "Verbindung zu %s nicht möglich: %s"
 
+#, c-format
+msgid " - %s"
+msgstr " - %s"
+
+#, c-format
+msgid " (%s)"
+msgstr " (%s)"
+
 #. 10053
 #, c-format
 msgid "Connection interrupted by other software on your computer."
@@ -9640,7 +9662,7 @@
 "unterbrochen."
 
 #. 10054
-#, fuzzy, c-format
+#, c-format
 msgid "Remote host closed connection."
 msgstr "Der entfernte Host hat die Verbindung beendet."
 
@@ -9908,6 +9930,12 @@
 "Sie sind im Moment nicht mit einem Konto angemeldet, welches benutzt werden "
 "kann, um diesen Buddy hinzuzufügen."
 
+#. I don't believe this can happen currently, I think
+#. * everything that calls this function checks for one of the
+#. * above node types first.
+msgid "Unknown node type"
+msgstr "Unbekannter Knotentyp"
+
 #. Buddies menu
 msgid "/_Buddies"
 msgstr "/_Buddys"
@@ -10009,12 +10037,8 @@
 msgstr "/Hilfe/Ü_ber"
 
 #, c-format
-msgid ""
-"\n"
-"<b>Account:</b> %s"
-msgstr ""
-"\n"
-"<b>Konto:</b> %s"
+msgid "<b>Account:</b> %s"
+msgstr "<b>Konto:</b> %s"
 
 #, c-format
 msgid ""
@@ -10045,6 +10069,12 @@
 msgid "Rockin'"
 msgstr "Abgefahren"
 
+msgid "Total Buddies"
+msgstr "Buddy-Anzahl"
+
+msgid "Online Buddies"
+msgstr "Online-Buddys"
+
 #, c-format
 msgid "Idle %dd %dh %02dm"
 msgstr "Untätig %dd %dh %02dm"
@@ -10460,16 +10490,13 @@
 msgid "User is typing..."
 msgstr "Benutzer tippt gerade..."
 
-msgid "User has typed something and stopped"
-msgstr "Benutzer hat etwas getippt und wartet nun"
-
 #, c-format
 msgid ""
 "\n"
-"%s has typed something and stopped"
+"%s has stopped typing"
 msgstr ""
 "\n"
-"%s hat etwas getippt und wartet nun"
+"%s hat aufgehört zu tippen"
 
 #. Build the Send To menu
 msgid "S_end To"
@@ -11108,31 +11135,33 @@
 msgstr ""
 "Farbe zum Darstellen von Hyperlinks, wenn sich die Maus darüber befindet."
 
-#, fuzzy
 msgid "Sent Message Name Color"
-msgstr "Gesendete Nachrichten"
+msgstr "Farbe des Absendernamens für gesendete Nachrichten"
 
 msgid "Color to draw the name of a message you sent."
 msgstr ""
-
-#, fuzzy
+"Farbe, mit der der Name in einer gesendeten Nachricht dargestellt wird."
+
 msgid "Received Message Name Color"
-msgstr "Empfangene Nachrichten"
+msgstr "Farbe des Absendernamens für empfangene Nachrichten"
 
 msgid "Color to draw the name of a message you received."
 msgstr ""
+"Farbe, mit der der Name in einer empfangenen Nachricht dargestellt wird."
 
 msgid "\"Attention\" Name Color"
-msgstr ""
+msgstr "Farbe des Absendernamens für \"Achtung\"-Nachrichten"
 
 msgid "Color to draw the name of a message you received containing your name."
 msgstr ""
+"Farbe, mit der der Name in einer Nachricht dargestellt wird, die Ihren Namen "
+"enthält."
 
 msgid "Action Message Name Color"
-msgstr ""
+msgstr "Farbe des Absendernamens für Aktions-Nachrichten"
 
 msgid "Color to draw the name of an action message."
-msgstr ""
+msgstr "Farbe, mit der der Name in einer Aktions-Nachricht dargestellt wird."
 
 msgid "_Copy E-Mail Address"
 msgstr "Kopiere _E-Mail-Adresse"
@@ -11187,15 +11216,6 @@
 msgid "_Save Image..."
 msgstr "Bild _speichern..."
 
-msgid "_Font"
-msgstr "_Schrift"
-
-msgid "_Insert"
-msgstr "_Einfügen"
-
-msgid "S_mile!"
-msgstr "_Lächeln!"
-
 msgid "Select Font"
 msgstr "Schriftart wählen"
 
@@ -11224,6 +11244,9 @@
 msgid "Insert Link"
 msgstr "Link einfügen"
 
+msgid "_Insert"
+msgstr "_Einfügen"
+
 #, c-format
 msgid "Failed to store image: %s\n"
 msgstr "Speichern des Bildes fehlgeschlagen: %s\n"
@@ -11231,12 +11254,14 @@
 msgid "Insert Image"
 msgstr "Bild einfügen"
 
+msgid "Smile!"
+msgstr "Lächeln!"
+
 msgid "This theme has no available smileys."
 msgstr "Dieses Thema verfügt über keine Smileys."
 
-#. show everything
-msgid "Smile!"
-msgstr "Lächeln!"
+msgid "_Font"
+msgstr "_Schrift"
 
 msgid "Group Items"
 msgstr "Elemente gruppieren"
@@ -12029,7 +12054,6 @@
 msgid "Changes to privacy settings take effect immediately."
 msgstr "Einstellungen bzgl. der Privatsphäre werden sofort wirksam."
 
-#. "Set privacy for:" label
 msgid "Set privacy for:"
 msgstr "Setze Privatsphäre für:"
 
@@ -12093,10 +12117,6 @@
 msgid "Select Folder..."
 msgstr "Ordner auswählen..."
 
-#. Create the window.
-msgid "Room List"
-msgstr "Raumliste"
-
 #. list button
 msgid "_Get List"
 msgstr "_Liste abrufen"
@@ -12287,9 +12307,6 @@
 msgid "none"
 msgstr "keine"
 
-msgid "Display Statistics"
-msgstr "Statistik anzeigen"
-
 msgid "Response Probability:"
 msgstr "Antwortwahrscheinlichkeit:"
 
@@ -12850,9 +12867,8 @@
 msgid "Hyperlink Color"
 msgstr "Hyperlink-Farbe"
 
-#, fuzzy
 msgid "Highlighted Message Name Color"
-msgstr "Hervorgehobene Nachrichten"
+msgstr "Farbe des Absendernamens für hervorgehobene Nachrichten"
 
 msgid "GtkTreeView Horizontal Separation"
 msgstr "GtkTreeview horizontaler Abstand"
@@ -12861,7 +12877,7 @@
 msgstr "Unterhaltungseintrag"
 
 msgid "Request Dialog"
-msgstr "Dialog anfordern"
+msgstr "Anfrage-Dialog"
 
 msgid "Notify Dialog"
 msgstr "Benachrichtigungsdialog"
--- a/po/stats.pl	Sun Dec 30 23:52:38 2007 +0000
+++ b/po/stats.pl	Tue Jan 08 13:17:59 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # Copyright 2003-2005 Nathan Walp <faceprint@faceprint.com>
 #