changeset 20107:d3bd5414eb0f

propagate from branch 'im.pidgin.pidgin' (head 41389df89a4a6a007d41cec33e33043cd41ea159) to branch 'im.pidgin.cpw.resiak.disconnectreason' (head 04389226a6288dedc7867ed0ecabdd64350099b0)
author Will Thompson <will.thompson@collabora.co.uk>
date Mon, 17 Sep 2007 17:51:22 +0000
parents 2d38b90bee15 (current diff) bacfbe346b47 (diff)
children 88b97e07f35f
files libpurple/connection.c libpurple/connection.h pidgin/gtkconn.c
diffstat 189 files changed, 1450 insertions(+), 1117 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon Sep 17 16:54:45 2007 +0000
+++ b/COPYRIGHT	Mon Sep 17 17:51:22 2007 +0000
@@ -246,6 +246,7 @@
 Kevin Miller
 Paul Miller
 Arkadiusz Miskiewicz
+David Mohr
 Andrew Molloy
 Michael Monreal
 Benjamin Moody
--- a/ChangeLog	Mon Sep 17 16:54:45 2007 +0000
+++ b/ChangeLog	Mon Sep 17 17:51:22 2007 +0000
@@ -12,6 +12,9 @@
 	  is listening to some soothing music.
 	* 'Move to' menu in buddy list context menu for moving buddies to
   	   other groups
+	* Move "Smiley" to the top-level of the toolbar
+	* Save Pidgin's display in the command line for session
+	  restoration.  (David Mohr)
 
 Version 2.2.0 (09/13/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.2.0
--- a/finch/finch.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/finch.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @defgroup finch Finch (GNT User Interface)
- *
- * 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
--- a/finch/gntaccount.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntaccount.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntaccount.c GNT Account API
  * @ingroup finch
- *
- * 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
--- a/finch/gntaccount.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntaccount.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntaccount.h GNT Account API
  * @ingroup finch
- *
- * 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
--- a/finch/gntblist.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntblist.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntblist.c GNT BuddyList API
  * @ingroup finch
- *
- * 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
--- a/finch/gntblist.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntblist.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntblist.h GNT BuddyList API
  * @ingroup finch
- *
- * 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
--- a/finch/gntcertmgr.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntcertmgr.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntcertmgr.c GNT Certificate Manager API
  * @ingroup finch
- *
- * 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
--- a/finch/gntcertmgr.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntcertmgr.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntcertmgr.h GNT Certificate Manager API
  * @ingroup finch
- *
- * 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
--- a/finch/gntconn.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntconn.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntconn.c GNT Connection API
  * @ingroup finch
- *
- * 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
--- a/finch/gntconn.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntconn.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntconn.h GNT Connection API
  * @ingroup finch
- *
- * 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
--- a/finch/gntconv.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntconv.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntconv.c GNT Conversation API
  * @ingroup finch
- *
- * 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
--- a/finch/gntconv.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntconv.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntconv.h GNT Conversation API
  * @ingroup finch
- *
- * 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
--- a/finch/gntdebug.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntdebug.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntdebug.c GNT Debug API
  * @ingroup finch
- *
- * 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
--- a/finch/gntdebug.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntdebug.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntdebug.h GNT Debug API
  * @ingroup finch
- *
- * 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
--- a/finch/gntft.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntft.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntft.c GNT File Transfer UI
  * @ingroup finch
- *
- * 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
--- a/finch/gntft.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntft.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntft.h GNT File Transfer UI
  * @ingroup finch
- *
- * 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
--- a/finch/gntidle.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntidle.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntidle.h GNT Idle API
  * @ingroup finch
- *
- * finch
+ */
+
+/* finch
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/finch/gntnotify.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntnotify.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntnotify.c GNT Notify API
  * @ingroup finch
- *
- * 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
@@ -351,14 +352,17 @@
 		gnt_box_add_widget(GNT_BOX(window),
 			gnt_label_new_with_format(secondary, GNT_TEXT_FLAG_NORMAL));
 
-	columns = purple_notify_searchresults_get_columns_count(results);
+	columns = g_list_length(results->columns);
 	tree = gnt_tree_new_with_columns(columns);
 	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
 	gnt_box_add_widget(GNT_BOX(window), tree);
 
-	for (i = 0; i < columns; i++)
-		gnt_tree_set_column_title(GNT_TREE(tree), i, 
-				purple_notify_searchresults_column_get_title(results, i));
+	i = 0;
+	for (iter = results->columns; iter; iter = iter->next)
+	{
+		gnt_tree_set_column_title(GNT_TREE(tree), i, iter->data);
+		i++;
+	}
 
 	box = gnt_hbox_new(TRUE);
 
--- a/finch/gntnotify.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntnotify.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntnotify.h GNT Notify API
  * @ingroup finch
- *
- * 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
--- a/finch/gntplugin.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntplugin.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntplugin.c GNT Plugins API
  * @ingroup finch
- *
- * 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
--- a/finch/gntplugin.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntplugin.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntplugin.h GNT Plugins API
  * @ingroup finch
- *
- * 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
--- a/finch/gntpounce.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntpounce.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntpounce.c GNT Buddy Pounce API
  * @ingroup finch
- *
- * 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
--- a/finch/gntpounce.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntpounce.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntpounce.h GNT Buddy Pounce API
  * @ingroup finch
- *
- * 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
--- a/finch/gntprefs.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntprefs.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntprefs.c GNT Preferences API
  * @ingroup finch
- *
- * 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
--- a/finch/gntprefs.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntprefs.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntprefs.h GNT Preferences API
  * @ingroup finch
- *
- * 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
--- a/finch/gntrequest.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntrequest.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntrequest.c GNT Request API
  * @ingroup finch
- *
- * 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
--- a/finch/gntrequest.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntrequest.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntrequest.h GNT Request API
  * @ingroup finch
- *
- * 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
--- a/finch/gntsound.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntsound.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntsound.c GNT Sound API
  * @ingroup finch
- *
- * 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
--- a/finch/gntsound.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntsound.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntsound.h GNT Sound API
  * @ingroup finch
- *
- * 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
--- a/finch/gntstatus.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntstatus.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntstatus.c GNT Status API
  * @ingroup finch
- *
- * 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
--- a/finch/gntstatus.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/gntstatus.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gntstatus.h GNT Status API
  * @ingroup finch
- *
- * 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
--- a/finch/libgnt/gntentry.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/finch/libgnt/gntentry.c	Mon Sep 17 17:51:22 2007 +0000
@@ -100,6 +100,15 @@
 	return changed;
 }
 
+static int
+max_common_prefix(const char *s, const char *t)
+{
+	const char *f = s;
+	while (*f && *t && *f == *t++)
+		f++;
+	return f - s;
+}
+
 static gboolean
 show_suggest_dropdown(GntEntry *entry)
 {
@@ -110,6 +119,7 @@
 	GList *iter;
 	const char *text = NULL;
 	const char *sgst = NULL;
+	int max = -1;
 
 	if (entry->word)
 	{
@@ -121,14 +131,13 @@
 	else
 		suggest = g_strdup(entry->start);
 	len = strlen(suggest);  /* Don't need to use the utf8-function here */
-	
+
 	if (entry->ddown == NULL)
 	{
 		GntWidget *box = gnt_vbox_new(FALSE);
 		entry->ddown = gnt_tree_new();
 		gnt_tree_set_compare_func(GNT_TREE(entry->ddown), (GCompareFunc)g_utf8_collate);
 		gnt_box_add_widget(GNT_BOX(box), entry->ddown);
-		/* XXX: Connect to the "activate" signal for the dropdown tree */
 
 		GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT);
 
@@ -151,6 +160,10 @@
 					gnt_tree_create_row(GNT_TREE(entry->ddown), text),
 					NULL, NULL);
 			count++;
+			if (max == -1)
+				max = strlen(text) - len;
+			else if (max)
+				max = MIN(max, max_common_prefix(sgst + len, text + len));
 			sgst = text;
 		}
 	}
@@ -163,6 +176,17 @@
 		destroy_suggest(entry);
 		return complete_suggest(entry, sgst);
 	} else {
+		if (max > 0) {
+			GntWidget *ddown = entry->ddown;
+			char *match = g_strndup(sgst + len, max);
+			entry->ddown = NULL;
+			gnt_entry_key_pressed(GNT_WIDGET(entry), match);
+			g_free(match);
+			if (entry->ddown)
+				gnt_widget_destroy(ddown);
+			else
+				entry->ddown = ddown;
+		}
 		gnt_widget_draw(entry->ddown->parent);
 	}
 
--- a/libpurple/account.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/account.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file account.c Account API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/account.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/account.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file account.h Account API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/accountopt.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/accountopt.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file accountopt.c Account Options API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/accountopt.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/accountopt.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file accountopt.h Account Options API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/blist.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/blist.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file blist.h Buddy List API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/buddyicon.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/buddyicon.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file icon.c Buddy Icon API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/buddyicon.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/buddyicon.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file buddyicon.h Buddy Icon API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/cipher.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/cipher.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file cipher.h Purple Cipher API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/circbuffer.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/circbuffer.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file circbuffer.h Buffer Utility Functions
  * @ingroup core
- *
- * Purple is the legal property of its developers, whose names are too numerous
+ */
+
+/* Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
  *
--- a/libpurple/circbuffer.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/circbuffer.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
-/*
+/**
  * @file circbuffer.h Buffer Utility Functions
  * @ingroup core
- *
- * Purple is the legal property of its developers, whose names are too numerous
+ */
+
+/* Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
  *
--- a/libpurple/cmds.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/cmds.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file cmds.c Commands API
  * @ingroup core
- *
- * Copyright (C) 2003-2004 Timothy Ringenbach <omarvo@hotmail.com
+ */
+
+/* Copyright (C) 2003-2004 Timothy Ringenbach <omarvo@hotmail.com
  *
  * 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
--- a/libpurple/cmds.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/cmds.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file cmds.h Commands API
  * @ingroup core
- *
- * Copyright (C) 2003 Timothy Ringenbach <omarvo@hotmail.com>
+ */
+
+/* Copyright (C) 2003 Timothy Ringenbach <omarvo@hotmail.com>
  *
  * 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
--- a/libpurple/connection.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/connection.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file connection.c Connection API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/connection.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/connection.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file connection.h Connection API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/conversation.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/conversation.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file conversation.h Conversation API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/core.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/core.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file core.c Purple Core API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/core.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/core.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @defgroup core libpurple
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dbus-bindings.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/dbus-bindings.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file dbus-bindings.h Purple DBUS Bindings
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dbus-server.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/dbus-server.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file dbus-server.h Purple DBUS Server
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/debug.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/debug.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file debug.c Debug API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/debug.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/debug.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file debug.h Debug API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/desktopitem.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/desktopitem.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file purple-desktop-item.c Functions for managing .desktop files
  * @ingroup core
- *
- * Purple is the legal property of its developers, whose names are too numerous
+ */
+
+/* Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
  *
--- a/libpurple/desktopitem.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/desktopitem.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file desktopitem.h Functions for managing .desktop files
  * @ingroup core
- *
- * Purple is the legal property of its developers, whose names are too numerous
+ */
+
+/* Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
  *
--- a/libpurple/dnsquery.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/dnsquery.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file dnsquery.c DNS query API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dnsquery.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/dnsquery.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file dnsquery.h DNS query API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/dnssrv.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/dnssrv.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file dnssrv.c
- *
- * purple
+ */
+
+/* purple
  *
  * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
  *
--- a/libpurple/dnssrv.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/dnssrv.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,10 +1,11 @@
 /**
  * @file dnssrv.h
- *
- * purple
+ */
+
+/* purple
  *
  * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de>
- *i
+ *
  * 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
--- a/libpurple/eventloop.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/eventloop.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file eventloop.c Purple Event Loop API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/eventloop.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/eventloop.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file eventloop.h Purple Event Loop API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/ft.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/ft.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file ft.c File Transfer API
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/ft.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/ft.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file ft.h File Transfer API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/gaim-compat.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/gaim-compat.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gaim-compat.h Gaim Compat macros
  * @ingroup core
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/idle.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/idle.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file idle.h Idle API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/imgstore.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/imgstore.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file imgstore.h IM Image Store API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/imgstore.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/imgstore.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file imgstore.h IM Image Store API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/internal.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/internal.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file internal.h Internal definitions and includes
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/log.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/log.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file log.c Logging API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/log.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/log.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file log.h Logging API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/nat-pmp.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/nat-pmp.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file nat-pmp.c NAT-PMP Implementation
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/nat-pmp.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/nat-pmp.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file nat-pmp.h NAT-PMP Implementation
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/network.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/network.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file network.c Network Implementation
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/network.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/network.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file network.h Network API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/notify.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/notify.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file notify.c Notification API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/notify.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/notify.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file notify.h Notification API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -292,7 +293,17 @@
 
 /**
  * Returns a number of the rows in the search results object.
- * 
+ *
+ * @deprecated This function will be removed in Pidgin 3.0.0 unless
+ *             there is sufficient demand to keep it.  Using this
+ *             function encourages looping through the results
+ *             inefficiently.  Instead of using this function you
+ *             should iterate through the results using a loop
+ *             similar to this:
+ *                for (l = results->rows; l != NULL; l = l->next)
+ *             If you really need to get the number of rows you
+ *             can use g_list_length(results->rows).
+ *
  * @param results The search results object.
  *
  * @return Number of the result rows.
@@ -302,6 +313,16 @@
 /**
  * Returns a number of the columns in the search results object.
  *
+ * @deprecated This function will be removed in Pidgin 3.0.0 unless
+ *             there is sufficient demand to keep it.  Using this
+ *             function encourages looping through the columns
+ *             inefficiently.  Instead of using this function you
+ *             should iterate through the columns using a loop
+ *             similar to this:
+ *                for (l = results->columns; l != NULL; l = l->next)
+ *             If you really need to get the number of columns you
+ *             can use g_list_length(results->columns).
+ *
  * @param results The search results object.
  *
  * @return Number of the columns.
@@ -311,6 +332,16 @@
 /**
  * Returns a row of the results from the search results object.
  *
+ * @deprecated This function will be removed in Pidgin 3.0.0 unless
+ *             there is sufficient demand to keep it.  Using this
+ *             function encourages looping through the results
+ *             inefficiently.  Instead of using this function you
+ *             should iterate through the results using a loop
+ *             similar to this:
+ *                for (l = results->rows; l != NULL; l = l->next)
+ *             If you really need to get the data for a particular
+ *             row you can use g_list_nth_data(results->rows, row_id).
+ *
  * @param results The search results object.
  * @param row_id  Index of the row to be returned.
  *
@@ -321,7 +352,15 @@
 
 /**
  * Returns a title of the search results object's column.
- * 
+ *
+ * @deprecated This function will be removed in Pidgin 3.0.0 unless
+ *             there is sufficient demand to keep it.  Using this
+ *             function encourages looping through the columns
+ *             inefficiently.  Instead of using this function you
+ *             should iterate through the name of a particular
+ *             column you can use
+ *             g_list_nth_data(results->columns, row_id).
+ *
  * @param results   The search results object.
  * @param column_id Index of the column.
  *
--- a/libpurple/ntlm.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/ntlm.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file ntlm.c
- *
- * purple
+ */
+
+/* purple
  *
  * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
  *
--- a/libpurple/ntlm.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/ntlm.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file ntlm.h
- *
- * purple
+ */
+
+/* purple
  *
  * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de>
  *
--- a/libpurple/plugin.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/plugin.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file plugin.h Plugin API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/pluginpref.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/pluginpref.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file pluginpref.h Plugin Preferences API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/plugins/debug_example.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/plugins/debug_example.c	Mon Sep 17 17:51:22 2007 +0000
@@ -27,6 +27,16 @@
 /* We're including glib.h again for the gboolean type. */
 #include <glib.h>
 
+/* This will prevent compiler errors in some instances and is better explained in the
+ * how-to documents on the wiki */
+#ifndef G_GNUC_NULL_TERMINATED
+# if __GNUC__ >= 4
+#  define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
+# else
+#  define G_GNUC_NULL_TERMINATED
+# endif
+#endif
+
 /* This is the required definition of PURPLE_PLUGINS as required for a plugin,
  * but we protect it with an #ifndef because config.h may define it for us
  * already and this would cause an unneeded compiler warning. */
--- a/libpurple/plugins/helloworld.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/plugins/helloworld.c	Mon Sep 17 17:51:22 2007 +0000
@@ -33,6 +33,16 @@
 
 #include <glib.h>
 
+/* This will prevent compiler errors in some instances and is better explained in the
+ * how-to documents on the wiki */
+#ifndef G_GNUC_NULL_TERMINATED
+# if __GNUC__ >= 4
+#  define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
+# else
+#  define G_GNUC_NULL_TERMINATED
+# endif
+#endif
+
 #include <notify.h>
 #include <plugin.h>
 #include <version.h>
--- a/libpurple/plugins/notify_example.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/plugins/notify_example.c	Mon Sep 17 17:51:22 2007 +0000
@@ -26,6 +26,16 @@
 
 #include <glib.h>
 
+/* This will prevent compiler errors in some instances and is better explained in the
+ * how-to documents on the wiki */
+#ifndef G_GNUC_NULL_TERMINATED
+# if __GNUC__ >= 4
+#  define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
+# else
+#  define G_GNUC_NULL_TERMINATED
+# endif
+#endif
+
 /* This is the required definition of PURPLE_PLUGINS as required for a plugin,
  * but we protect it with an #ifndef because config.h may define it for us
  * already and this would cause an unneeded compiler warning. */
--- a/libpurple/pounce.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/pounce.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file pounce.c Buddy Pounce API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/pounce.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/pounce.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file pounce.h Buddy Pounce API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/prefs.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/prefs.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file prefs.h Prefs API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/privacy.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/privacy.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file privacy.h Privacy API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/protocols/jabber/jabber.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Sep 17 17:51:22 2007 +0000
@@ -141,6 +141,7 @@
 		if(jabber_process_starttls(js, packet))
 			return;
 	} else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) {
+		js->gc->wants_to_die = TRUE;
 		purple_connection_error(js->gc, _("You require encryption, but it is not available on this server."));
 		return;
 	}
--- a/libpurple/protocols/jabber/message.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/protocols/jabber/message.c	Mon Sep 17 17:51:22 2007 +0000
@@ -41,7 +41,10 @@
 	g_free(jm->body);
 	g_free(jm->xhtml);
 	g_free(jm->password);
+	g_free(jm->error);
+	g_free(jm->thread_id);
 	g_list_free(jm->etc);
+	g_list_free(jm->eventitems);
 
 	g_free(jm);
 }
--- a/libpurple/protocols/msn/msn.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Sep 17 17:51:22 2007 +0000
@@ -731,7 +731,7 @@
 	http_method = purple_account_get_bool(account, "http_method", FALSE);
 
 	if (http_method)
-		host = purple_account_get_string(account, "http_method_server", MSN_SERVER);
+		host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER);
 	else
 		host = purple_account_get_string(account, "server", MSN_SERVER);
 	port = purple_account_get_int(account, "port", MSN_PORT);
--- a/libpurple/protocols/myspace/markup.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/protocols/myspace/markup.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,691 +1,698 @@
-/* MySpaceIM Protocol Plugin - markup
- *
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- *
- * 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 "myspace.h"
-
-typedef void (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
-
-/* Internal functions */
-
-static guint msim_point_to_purple_size(MsimSession *session, guint point);
-static guint msim_purple_size_to_point(MsimSession *session, guint size);
-static guint msim_height_to_point(MsimSession *session, guint height);
-static guint msim_point_to_height(MsimSession *session, guint point);
-
-static void msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
-static void html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
-static gchar *msim_convert_xml(MsimSession *, const gchar *raw, MSIM_XMLNODE_CONVERT f);
-static gchar *msim_convert_smileys_to_markup(gchar *before);
-static double msim_round(double round);
-
-
-/* Globals */
-
-/* The names in in emoticon_names (for <i n=whatever>) map to corresponding 
- * entries in emoticon_symbols (for the ASCII representation of the emoticon).
- *
- * Multiple emoticon symbols in Pidgin can map to one name. List the
- * canonical form, as inserted by the "Smile!" dialog, first. For example,
- * :) comes before :-), because although both are recognized as 'happy',
- * the first is inserted by the smiley button (first symbol in theme).
- *
- * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
-static struct MSIM_EMOTICON
-{
-	gchar *name;
-	gchar *symbol;
-} msim_emoticons[] = {
-	/* Unfortunately, this list duplicates much of the file
-	 * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
-	 * that file is part of Pidgin, but we're part of libpurple.
-	 */
-	{ "bigsmile", ":D" },
-	{ "bigsmile", ":-D" },
-	{ "devil", "}:)" },
-	{ "frazzled", ":Z" },
-	{ "geek", "B)" },
-	{ "googles", "%)" },
-	{ "growl", ":E" },
-	{ "laugh", ":))" },		/* Must be before ':)' */
-	{ "happy", ":)" },
-	{ "happy", ":-)" },
-	{ "happi", ":)" },
-	{ "heart", ":X" },
-	{ "mohawk", "-:" },
-	{ "mad", "X(" },
-	{ "messed", "X)" },
-	{ "nerd", "Q)" },
-	{ "oops", ":G" },
-	{ "pirate", "P)" },
-	{ "scared", ":O" },
-	{ "sidefrown", ":{" },
-	{ "sinister", ":B" },
-	{ "smirk", ":," },
-	{ "straight", ":|" },
-	{ "tongue", ":P" },
-	{ "tongue", ":p" },
-	{ "tongy", ":P" },
-	{ "upset", "B|" },
-	{ "wink", ";-)" },
-	{ "wink", ";)" },
-	{ "winc", ";)" },
-	{ "worried", ":[" },
-	{ "kiss", ":x" },
-	{ NULL, NULL }
-};
-
-
-
-/* Indexes of this array + 1 map HTML font size to scale of normal font size. *
- * Based on _point_sizes from libpurple/gtkimhtml.c 
- *                                 1    2  3    4     5      6       7 */
-static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
-
-#define MAX_FONT_SIZE                   7       /* Purple maximum font size */
-#define POINTS_PER_INCH                 72      /* How many pt's in an inch */
-
-/* Text formatting bits for <f s=#> */
-#define MSIM_TEXT_BOLD                  1
-#define MSIM_TEXT_ITALIC                2   
-#define MSIM_TEXT_UNDERLINE             4
-
-/* Default baseline size of purple's fonts, in points. What is size 3 in points. 
- * _font_scale specifies scaling factor relative to this point size. Note this 
- * is only the default; it is configurable in account options. */
-#define MSIM_BASE_FONT_POINT_SIZE       8
-
-/* Default display's DPI. 96 is common but it can differ. Also configurable
- * in account options. */
-#define MSIM_DEFAULT_DPI                96
-
-
-/* round is part of C99, but sometimes is unavailable before then.
- * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
- */
-double msim_round(double value)
-{
-	if (value < 0) {
-		return -(floor(-value + 0.5));
-	} else {
-		return   floor( value + 0.5);
-	}
-}
-
-
-/** Convert typographical font point size to HTML font size. 
- * Based on libpurple/gtkimhtml.c */
-static guint
-msim_point_to_purple_size(MsimSession *session, guint point)
-{
-	guint size, this_point, base;
-	gdouble scale;
-	
-	base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-   
-	for (size = 0; 
-			size < sizeof(_font_scale) / sizeof(_font_scale[0]);
-			++size) {
-		scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
-		this_point = (guint)msim_round(scale * base);
-
-		if (this_point >= point) {
-			purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
-					point, size);
-			return size;
-		}
-	}
-
-	/* No HTML font size was this big; return largest possible. */
-	return this_point;
-}
-
-/** Convert HTML font size to point size. */
-static guint
-msim_purple_size_to_point(MsimSession *session, guint size)
-{
-	gdouble scale;
-	guint point;
-	guint base;
-
-	scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
-
-	base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-
-	point = (guint)msim_round(scale * base);
-
-	purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
-					size, point);
-
-	return point;
-}
-
-/** Convert a msim markup font pixel height to the more usual point size, for incoming messages. */
-static guint 
-msim_height_to_point(MsimSession *session, guint height)
-{
-	guint dpi;
-
-	dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
-
-	return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
-
-	/* See also: libpurple/protocols/bonjour/jabber.c
-	 * _font_size_ichat_to_purple */
-}
-
-/** Convert point size to msim pixel height font size specification, for outgoing messages. */
-static guint
-msim_point_to_height(MsimSession *session, guint point)
-{
-	guint dpi;
-
-	dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
-
-	return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
-}
-
-/** Convert the msim markup <f> (font) tag into HTML. */
-static void 
-msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *face, *height_str, *decor_str;
-	GString *gs_end, *gs_begin;
-	guint decor, height;
-
-	face = xmlnode_get_attrib(root, "f");
-	height_str = xmlnode_get_attrib(root, "h");
-	decor_str = xmlnode_get_attrib(root, "s");
-
-	if (height_str) {
-		height = atol(height_str);
-	} else {
-		height = 12;
-	}
-
-	if (decor_str) {
-		decor = atol(decor_str);
-	} else {
-		decor = 0;
-	}
-
-	gs_begin = g_string_new("");
-	/* TODO: get font size working */
-	if (height && !face) {
-		g_string_printf(gs_begin, "<font size='%d'>", 
-				msim_point_to_purple_size(session, msim_height_to_point(session, height)));
-	} else if (height && face) {
-		g_string_printf(gs_begin, "<font face='%s' size='%d'>", face,  
-				msim_point_to_purple_size(session, msim_height_to_point(session, height)));
-	} else {
-		g_string_printf(gs_begin, "<font>");
-	}
-
-	/* No support for font-size CSS? */
-	/* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face, 
-			msim_height_to_point(height)); */
-
-	gs_end = g_string_new("</font>");
-
-	if (decor & MSIM_TEXT_BOLD) {
-		g_string_append(gs_begin, "<b>");
-		g_string_prepend(gs_end, "</b>");
-	}
-
-	if (decor & MSIM_TEXT_ITALIC) {
-		g_string_append(gs_begin, "<i>");
-		g_string_append(gs_end, "</i>");
-	}
-
-	if (decor & MSIM_TEXT_UNDERLINE) {
-		g_string_append(gs_begin, "<u>");
-		g_string_append(gs_end, "</u>");
-	}
-
-
-	*begin = gs_begin->str;
-	*end = gs_end->str;
-}
-
-/** Convert a msim markup color to a color suitable for libpurple.
-  *
-  * @param msim Either a color name, or an rgb(x,y,z) code.
-  *
-  * @return A new string, either a color name or #rrggbb code. Must g_free(). 
-  */
-static char *
-msim_color_to_purple(const char *msim)
-{
-	guint red, green, blue;
-
-	if (!msim) {
-		return g_strdup("black");
-	}
-
-	if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
-		/* Color name. */
-		return g_strdup(msim);
-	}
-	/* TODO: rgba (alpha). */
-
-	return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
-}
-
-/** Convert the msim markup <a> (anchor) tag into HTML. */
-static void 
-msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *href;
-
-	href = xmlnode_get_attrib(root, "h");
-	if (!href) {
-		href = "";
-	}
-
-	*begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
-	*end = g_strdup("</a>");
-}
-
-/** Convert the msim markup <p> (paragraph) tag into HTML. */
-static void 
-msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	/* Just pass through unchanged. 
-	 *
-	 * Note: attributes currently aren't passed, if there are any. */
-	*begin = g_strdup("<p>");
-	*end = g_strdup("</p>");
-}
-
-/** Convert the msim markup <c> tag (text color) into HTML. TODO: Test */
-static void 
-msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *color;
-	gchar *purple_color;
-
-	color = xmlnode_get_attrib(root, "v");
-	if (!color) {
-		purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr\n");
-		*begin = g_strdup("");
-		*end = g_strdup("");
-		/* TODO: log as unrecognized */
-		return;
-	}
-
-	purple_color = msim_color_to_purple(color);
-
-	*begin = g_strdup_printf("<font color='%s'>", purple_color); 
-
-	g_free(purple_color);
-
-	/* *begin = g_strdup_printf("<span style='color: %s'>", color); */
-	*end = g_strdup("</font>");
-}
-
-/** Convert the msim markup <b> tag (background color) into HTML. TODO: Test */
-static void 
-msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *color;
-	gchar *purple_color;
-
-	color = xmlnode_get_attrib(root, "v");
-	if (!color) {
-		*begin = g_strdup("");
-		*end = g_strdup("");
-		purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr\n");
-		/* TODO: log as unrecognized. */
-		return;
-	}
-
-	purple_color = msim_color_to_purple(color);
-
-	/* TODO: find out how to set background color. */
-	*begin = g_strdup_printf("<span style='background-color: %s'>", 
-			purple_color);
-	g_free(purple_color);
-
-	*end = g_strdup("</p>");
-}
-
-/** Convert the msim markup <i> tag (emoticon image) into HTML. */
-static void 
-msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
-{
-	const gchar *name;
-	guint i;
-	struct MSIM_EMOTICON *emote;
-
-	name = xmlnode_get_attrib(root, "n");
-	if (!name) {
-		purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n\n");
-		*begin = g_strdup("");
-		*end = g_strdup("");
-		/* TODO: log as unrecognized */
-		return;
-	}
-
-	/* Find and use canonical form of smiley symbol. */
-	for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
-		if (g_str_equal(name, emote->name)) {
-			*begin = g_strdup(emote->symbol);
-			*end = g_strdup("");
-			return;
-		}
-	}
-
-	/* Couldn't find it, sorry. Try to degrade gracefully. */
-	*begin = g_strdup_printf("**%s**", name);
-	*end = g_strdup("");
-}
-
-/** Convert an individual msim markup tag to HTML. */
-static void 
-msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin, 
-		gchar **end)
-{
-	if (g_str_equal(root->name, "f")) {
-		msim_markup_f_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "a")) {
-		msim_markup_a_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "p")) {
-		msim_markup_p_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "c")) {
-		msim_markup_c_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "b")) {
-		msim_markup_b_to_html(session, root, begin, end);
-	} else if (g_str_equal(root->name, "i")) {
-		msim_markup_i_to_html(session, root, begin, end);
-	} else {
-		purple_debug_info("msim", "msim_markup_tag_to_html: "
-				"unknown tag name=%s, ignoring", 
-				(root && root->name) ? root->name : "(NULL)");
-		*begin = g_strdup("");
-		*end = g_strdup("");
-	}
-}
-
-/** Convert an individual HTML tag to msim markup. */
-static void 
-html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin, 
-		gchar **end)
-{
-	/* TODO: Coalesce nested tags into one <f> tag!
-	 * Currently, the 's' value will be overwritten when b/i/u is nested
-	 * within another one, and only the inner-most formatting will be 
-	 * applied to the text. */
-	if (!purple_utf8_strcasecmp(root->name, "root")) {
-		*begin = g_strdup("");
-		*end = g_strdup("");
-	} else if (!purple_utf8_strcasecmp(root->name, "b")) {
-		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
-		*end = g_strdup("</f>");
-	} else if (!purple_utf8_strcasecmp(root->name, "i")) {
-		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
-		*end = g_strdup("</f>");
-	} else if (!purple_utf8_strcasecmp(root->name, "u")) {
-		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
-		*end = g_strdup("</f>");
-	} else if (!purple_utf8_strcasecmp(root->name, "a")) {
-		const gchar *href, *link_text;
-
-		href = xmlnode_get_attrib(root, "href");
-
-		if (!href) {
-			href = xmlnode_get_attrib(root, "HREF");
-		}
-
-		link_text = xmlnode_get_data(root);
-
-		if (href) {
-			if (g_str_equal(link_text, href)) {
-				/* Purple gives us: <a href="URL">URL</a>
-				 * Translate to <a h='URL' />
-				 * Displayed as text of URL with link to URL
-				 */
-				*begin = g_strdup_printf("<a h='%s' />", href);
-			} else {
-				/* But if we get: <a href="URL">text</a>
-				 * Translate to: text: <a h='URL' />
-				 *
-				 * Because official client only supports self-closed <a>
-				 * tags; you can't change the link text.
-				 */
-				*begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
-			}
-		} else {
-			*begin = g_strdup("<a />");
-		}
-
-		/* Sorry, kid. MySpace doesn't support you within <a> tags. */
-		xmlnode_free(root->child);
-		root->child = NULL;
-
-		*end = g_strdup("");
-	} else if (!purple_utf8_strcasecmp(root->name, "font")) {
-		const gchar *size;
-		const gchar *face;
-
-		size = xmlnode_get_attrib(root, "size");
-		face = xmlnode_get_attrib(root, "face");
-
-		if (face && size) {
-			*begin = g_strdup_printf("<f f='%s' h='%d'>", face, 
-					msim_point_to_height(session,
-						msim_purple_size_to_point(session, atoi(size))));
-		} else if (face) {
-			*begin = g_strdup_printf("<f f='%s'>", face);
-		} else if (size) {
-			*begin = g_strdup_printf("<f h='%d'>", 
-					 msim_point_to_height(session,
-						 msim_purple_size_to_point(session, atoi(size))));
-		} else {
-			*begin = g_strdup("<f>");
-		}
-
-		*end = g_strdup("</f>");
-
-		/* TODO: color (bg uses <body>), emoticons */
-	} else {
-		*begin = g_strdup_printf("[%s]", root->name);
-		*end = g_strdup_printf("[/%s]", root->name);
-	}
-}
-
-/** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
- *
- * @param f Function to convert tags.
- *
- * @return An HTML string. Caller frees.
- */
-static gchar *
-msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f)
-{
-	xmlnode *node;
-	gchar *begin, *inner, *end;
-	GString *final;
-
-	if (!root || !root->name) {
-		return g_strdup("");
-	}
-
-	purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
-			root->name);
-
-	begin = inner = end = NULL;
-
-	final = g_string_new("");
-
-	f(session, root, &begin, &end);
-	
-	g_string_append(final, begin);
-
-	/* Loop over all child nodes. */
-	for (node = root->child; node != NULL; node = node->next) {
-		switch (node->type) {
-		case XMLNODE_TYPE_ATTRIB:
-			/* Attributes handled above. */
-			break;
-
-		case XMLNODE_TYPE_TAG:
-			/* A tag or tag with attributes. Recursively descend. */
-			inner = msim_convert_xmlnode(session, node, f);
-			g_return_val_if_fail(inner != NULL, NULL);
-
-			purple_debug_info("msim", " ** node name=%s\n", 
-					(node && node->name) ? node->name : "(NULL)");
-			break;
-	
-		case XMLNODE_TYPE_DATA:
-			/* Literal text. */
-			inner = g_new0(char, node->data_sz + 1);
-			strncpy(inner, node->data, node->data_sz);
-			inner[node->data_sz] = 0;
-
-			purple_debug_info("msim", " ** node data=%s\n", 
-					inner ? inner : "(NULL)");
-			break;
-			
-		default:
-			purple_debug_info("msim",
-					"msim_convert_xmlnode: strange node\n");
-			inner = g_strdup("");
-		}
-
-		if (inner) {
-			g_string_append(final, inner);
-		}
-	}
-
-	/* TODO: Note that msim counts each piece of text enclosed by <f> as
-	 * a paragraph and will display each on its own line. You actually have
-	 * to _nest_ <f> tags to intersperse different text in one paragraph!
-	 * Comment out this line below to see. */
-	g_string_append(final, end);
-
-	purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n",
-			(final && final->str) ? final->str : "(NULL)");
-
-	return final->str;
-}
-
-/** Convert XML to something based on MSIM_XMLNODE_CONVERT. */
-static gchar *
-msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
-{
-	xmlnode *root;
-	gchar *str;
-	gchar *enclosed_raw;
-
-	g_return_val_if_fail(raw != NULL, NULL);
-
-	/* Enclose text in one root tag, to try to make it valid XML for parsing. */
-	enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
-
-	root = xmlnode_from_str(enclosed_raw, -1);
-
-	if (!root) {
-		purple_debug_info("msim", "msim_markup_to_html: couldn't parse "
-				"%s as XML, returning raw: %s\n", enclosed_raw, raw);
-		/* TODO: msim_unrecognized */
-		g_free(enclosed_raw);
-		return g_strdup(raw);
-	}
-
-	g_free(enclosed_raw);
-
-	str = msim_convert_xmlnode(session, root, f);
-	g_return_val_if_fail(str != NULL, NULL);
-	purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str);
-
-	xmlnode_free(root);
-
-	return str;
-}
-
-/** Convert plaintext smileys to <i> markup tags.
- *
- * @param before Original text with ASCII smileys. Will be freed.
- * @return A new string with <i> tags, if applicable. Must be g_free()'d.
- */
-static gchar *
-msim_convert_smileys_to_markup(gchar *before)
-{
-	gchar *old, *new, *replacement;
-	guint i;
-	struct MSIM_EMOTICON *emote;
-
-	old = before;
-	new = NULL;
-
-	for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
-		gchar *name, *symbol;
-
-		name = emote->name;
-		symbol = emote->symbol;
-
-		replacement = g_strdup_printf("<i n=\"%s\"/>", name);
-
-		purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
-				symbol ? symbol : "(NULL)", 
-				replacement ? replacement : "(NULL)");
-		new = purple_strreplace(old, symbol, replacement);
-		
-		g_free(replacement);
-		g_free(old);
-
-		old = new;
-	}
-
-	return new;
-}
-	
-
-/** High-level function to convert MySpaceIM markup to Purple (HTML) markup. 
- *
- * @return Purple markup string, must be g_free()'d. */
-gchar *
-msim_markup_to_html(MsimSession *session, const gchar *raw)
-{
-	return msim_convert_xml(session, raw, 
-			(MSIM_XMLNODE_CONVERT)(msim_markup_tag_to_html));
-}
-
-/** High-level function to convert Purple (HTML) to MySpaceIM markup.
- *
- * TODO: consider using purple_markup_html_to_xhtml() to make valid XML.
- *
- * @return HTML markup string, must be g_free()'d. */
-gchar *
-html_to_msim_markup(MsimSession *session, const gchar *raw)
-{
-	gchar *markup;
-
-	markup = msim_convert_xml(session, raw,
-			(MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup));
-	
-	if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
-		/* Frees markup and allocates a new one. */
-		markup = msim_convert_smileys_to_markup(markup);
-	}
-
-	return markup;
-}
-
-
+/* MySpaceIM Protocol Plugin - markup
+ *
+ * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
+ *
+ * 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 "myspace.h"
+
+typedef void (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
+
+/* Internal functions */
+
+static guint msim_point_to_purple_size(MsimSession *session, guint point);
+static guint msim_purple_size_to_point(MsimSession *session, guint size);
+static guint msim_height_to_point(MsimSession *session, guint height);
+static guint msim_point_to_height(MsimSession *session, guint point);
+
+static void msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
+static void html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
+static gchar *msim_convert_xml(MsimSession *, const gchar *raw, MSIM_XMLNODE_CONVERT f);
+static gchar *msim_convert_smileys_to_markup(gchar *before);
+static double msim_round(double round);
+
+
+/* Globals */
+
+/* The names in in emoticon_names (for <i n=whatever>) map to corresponding 
+ * entries in emoticon_symbols (for the ASCII representation of the emoticon).
+ *
+ * Multiple emoticon symbols in Pidgin can map to one name. List the
+ * canonical form, as inserted by the "Smile!" dialog, first. For example,
+ * :) comes before :-), because although both are recognized as 'happy',
+ * the first is inserted by the smiley button (first symbol in theme).
+ *
+ * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
+static struct MSIM_EMOTICON
+{
+	gchar *name;
+	gchar *symbol;
+} msim_emoticons[] = {
+	/* Unfortunately, this list duplicates much of the file
+	 * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
+	 * that file is part of Pidgin, but we're part of libpurple.
+	 */
+	{ "bigsmile", ":D" },
+	{ "bigsmile", ":-D" },
+	{ "devil", "}:)" },
+	{ "frazzled", ":Z" },
+	{ "geek", "B)" },
+	{ "googles", "%)" },
+	{ "growl", ":E" },
+	{ "laugh", ":))" },		/* Must be before ':)' */
+	{ "happy", ":)" },
+	{ "happy", ":-)" },
+	{ "happi", ":)" },
+	{ "heart", ":X" },
+	{ "mohawk", "-:" },
+	{ "mad", "X(" },
+	{ "messed", "X)" },
+	{ "nerd", "Q)" },
+	{ "oops", ":G" },
+	{ "pirate", "P)" },
+	{ "scared", ":O" },
+	{ "sidefrown", ":{" },
+	{ "sinister", ":B" },
+	{ "smirk", ":," },
+	{ "straight", ":|" },
+	{ "tongue", ":P" },
+	{ "tongue", ":p" },
+	{ "tongy", ":P" },
+	{ "upset", "B|" },
+	{ "wink", ";-)" },
+	{ "wink", ";)" },
+	{ "winc", ";)" },
+	{ "worried", ":[" },
+	{ "kiss", ":x" },
+	{ NULL, NULL }
+};
+
+
+
+/* Indexes of this array + 1 map HTML font size to scale of normal font size. *
+ * Based on _point_sizes from libpurple/gtkimhtml.c 
+ *                                 1    2  3    4     5      6       7 */
+static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
+
+#define MAX_FONT_SIZE                   7       /* Purple maximum font size */
+#define POINTS_PER_INCH                 72      /* How many pt's in an inch */
+
+/* Text formatting bits for <f s=#> */
+#define MSIM_TEXT_BOLD                  1
+#define MSIM_TEXT_ITALIC                2   
+#define MSIM_TEXT_UNDERLINE             4
+
+/* Default baseline size of purple's fonts, in points. What is size 3 in points. 
+ * _font_scale specifies scaling factor relative to this point size. Note this 
+ * is only the default; it is configurable in account options. */
+#define MSIM_BASE_FONT_POINT_SIZE       8
+
+/* Default display's DPI. 96 is common but it can differ. Also configurable
+ * in account options. */
+#define MSIM_DEFAULT_DPI                96
+
+
+/* round is part of C99, but sometimes is unavailable before then.
+ * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
+ */
+double msim_round(double value)
+{
+	if (value < 0) {
+		return -(floor(-value + 0.5));
+	} else {
+		return   floor( value + 0.5);
+	}
+}
+
+
+/** Convert typographical font point size to HTML font size. 
+ * Based on libpurple/gtkimhtml.c */
+static guint
+msim_point_to_purple_size(MsimSession *session, guint point)
+{
+	guint size, this_point, base;
+	gdouble scale;
+	
+	base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
+   
+	for (size = 0; 
+			size < sizeof(_font_scale) / sizeof(_font_scale[0]);
+			++size) {
+		scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
+		this_point = (guint)msim_round(scale * base);
+
+		if (this_point >= point) {
+			purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
+					point, size);
+			return size;
+		}
+	}
+
+	/* No HTML font size was this big; return largest possible. */
+	return this_point;
+}
+
+/** Convert HTML font size to point size. */
+static guint
+msim_purple_size_to_point(MsimSession *session, guint size)
+{
+	gdouble scale;
+	guint point;
+	guint base;
+
+	scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
+
+	base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
+
+	point = (guint)msim_round(scale * base);
+
+	purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
+					size, point);
+
+	return point;
+}
+
+/** Convert a msim markup font pixel height to the more usual point size, for incoming messages. */
+static guint 
+msim_height_to_point(MsimSession *session, guint height)
+{
+	guint dpi;
+
+	dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
+
+	return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
+
+	/* See also: libpurple/protocols/bonjour/jabber.c
+	 * _font_size_ichat_to_purple */
+}
+
+/** Convert point size to msim pixel height font size specification, for outgoing messages. */
+static guint
+msim_point_to_height(MsimSession *session, guint point)
+{
+	guint dpi;
+
+	dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
+
+	return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
+}
+
+/** Convert the msim markup <f> (font) tag into HTML. */
+static void 
+msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+{
+	const gchar *face, *height_str, *decor_str;
+	GString *gs_end, *gs_begin;
+	guint decor, height;
+
+	face = xmlnode_get_attrib(root, "f");
+	height_str = xmlnode_get_attrib(root, "h");
+	decor_str = xmlnode_get_attrib(root, "s");
+
+	if (height_str) {
+		height = atol(height_str);
+	} else {
+		height = 12;
+	}
+
+	if (decor_str) {
+		decor = atol(decor_str);
+	} else {
+		decor = 0;
+	}
+
+	gs_begin = g_string_new("");
+	/* TODO: get font size working */
+	if (height && !face) {
+		g_string_printf(gs_begin, "<font size='%d'>", 
+				msim_point_to_purple_size(session, msim_height_to_point(session, height)));
+	} else if (height && face) {
+		g_string_printf(gs_begin, "<font face='%s' size='%d'>", face,  
+				msim_point_to_purple_size(session, msim_height_to_point(session, height)));
+	} else {
+		g_string_printf(gs_begin, "<font>");
+	}
+
+	/* No support for font-size CSS? */
+	/* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face, 
+			msim_height_to_point(height)); */
+
+	gs_end = g_string_new("</font>");
+
+	if (decor & MSIM_TEXT_BOLD) {
+		g_string_append(gs_begin, "<b>");
+		g_string_prepend(gs_end, "</b>");
+	}
+
+	if (decor & MSIM_TEXT_ITALIC) {
+		g_string_append(gs_begin, "<i>");
+		g_string_append(gs_end, "</i>");
+	}
+
+	if (decor & MSIM_TEXT_UNDERLINE) {
+		g_string_append(gs_begin, "<u>");
+		g_string_append(gs_end, "</u>");
+	}
+
+
+	*begin = gs_begin->str;
+	*end = gs_end->str;
+}
+
+/** Convert a msim markup color to a color suitable for libpurple.
+  *
+  * @param msim Either a color name, or an rgb(x,y,z) code.
+  *
+  * @return A new string, either a color name or #rrggbb code. Must g_free(). 
+  */
+static char *
+msim_color_to_purple(const char *msim)
+{
+	guint red, green, blue;
+
+	if (!msim) {
+		return g_strdup("black");
+	}
+
+	if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
+		/* Color name. */
+		return g_strdup(msim);
+	}
+	/* TODO: rgba (alpha). */
+
+	return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
+}
+
+/** Convert the msim markup <a> (anchor) tag into HTML. */
+static void 
+msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+{
+	const gchar *href;
+
+	href = xmlnode_get_attrib(root, "h");
+	if (!href) {
+		href = "";
+	}
+
+	*begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
+	*end = g_strdup("</a>");
+}
+
+/** Convert the msim markup <p> (paragraph) tag into HTML. */
+static void 
+msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+{
+	/* Just pass through unchanged. 
+	 *
+	 * Note: attributes currently aren't passed, if there are any. */
+	*begin = g_strdup("<p>");
+	*end = g_strdup("</p>");
+}
+
+/** Convert the msim markup <c> tag (text color) into HTML. TODO: Test */
+static void 
+msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+{
+	const gchar *color;
+	gchar *purple_color;
+
+	color = xmlnode_get_attrib(root, "v");
+	if (!color) {
+		purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr\n");
+		*begin = g_strdup("");
+		*end = g_strdup("");
+		/* TODO: log as unrecognized */
+		return;
+	}
+
+	purple_color = msim_color_to_purple(color);
+
+	*begin = g_strdup_printf("<font color='%s'>", purple_color); 
+
+	g_free(purple_color);
+
+	/* *begin = g_strdup_printf("<span style='color: %s'>", color); */
+	*end = g_strdup("</font>");
+}
+
+/** Convert the msim markup <b> tag (background color) into HTML. TODO: Test */
+static void 
+msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+{
+	const gchar *color;
+	gchar *purple_color;
+
+	color = xmlnode_get_attrib(root, "v");
+	if (!color) {
+		*begin = g_strdup("");
+		*end = g_strdup("");
+		purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr\n");
+		/* TODO: log as unrecognized. */
+		return;
+	}
+
+	purple_color = msim_color_to_purple(color);
+
+	/* TODO: find out how to set background color. */
+	*begin = g_strdup_printf("<span style='background-color: %s'>", 
+			purple_color);
+	g_free(purple_color);
+
+	*end = g_strdup("</p>");
+}
+
+/** Convert the msim markup <i> tag (emoticon image) into HTML. */
+static void 
+msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+{
+	const gchar *name;
+	guint i;
+	struct MSIM_EMOTICON *emote;
+
+	name = xmlnode_get_attrib(root, "n");
+	if (!name) {
+		purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n\n");
+		*begin = g_strdup("");
+		*end = g_strdup("");
+		/* TODO: log as unrecognized */
+		return;
+	}
+
+	/* Find and use canonical form of smiley symbol. */
+	for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
+		if (g_str_equal(name, emote->name)) {
+			*begin = g_strdup(emote->symbol);
+			*end = g_strdup("");
+			return;
+		}
+	}
+
+	/* Couldn't find it, sorry. Try to degrade gracefully. */
+	*begin = g_strdup_printf("**%s**", name);
+	*end = g_strdup("");
+}
+
+/** Convert an individual msim markup tag to HTML. */
+static void 
+msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin, 
+		gchar **end)
+{
+	if (g_str_equal(root->name, "f")) {
+		msim_markup_f_to_html(session, root, begin, end);
+	} else if (g_str_equal(root->name, "a")) {
+		msim_markup_a_to_html(session, root, begin, end);
+	} else if (g_str_equal(root->name, "p")) {
+		msim_markup_p_to_html(session, root, begin, end);
+	} else if (g_str_equal(root->name, "c")) {
+		msim_markup_c_to_html(session, root, begin, end);
+	} else if (g_str_equal(root->name, "b")) {
+		msim_markup_b_to_html(session, root, begin, end);
+	} else if (g_str_equal(root->name, "i")) {
+		msim_markup_i_to_html(session, root, begin, end);
+	} else {
+		purple_debug_info("msim", "msim_markup_tag_to_html: "
+				"unknown tag name=%s, ignoring", 
+				(root && root->name) ? root->name : "(NULL)");
+		*begin = g_strdup("");
+		*end = g_strdup("");
+	}
+}
+
+/** Convert an individual HTML tag to msim markup. */
+static void 
+html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin, 
+		gchar **end)
+{
+	if (!purple_utf8_strcasecmp(root->name, "root") ||
+	    !purple_utf8_strcasecmp(root->name, "html")) {
+		*begin = g_strdup("");
+		*end = g_strdup("");
+	/* TODO: Coalesce nested tags into one <f> tag!
+	 * Currently, the 's' value will be overwritten when b/i/u is nested
+	 * within another one, and only the inner-most formatting will be 
+	 * applied to the text. */
+	} else if (!purple_utf8_strcasecmp(root->name, "b")) {
+		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
+		*end = g_strdup("</f>");
+	} else if (!purple_utf8_strcasecmp(root->name, "i")) {
+		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
+		*end = g_strdup("</f>");
+	} else if (!purple_utf8_strcasecmp(root->name, "u")) {
+		*begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
+		*end = g_strdup("</f>");
+	} else if (!purple_utf8_strcasecmp(root->name, "a")) {
+		const gchar *href, *link_text;
+
+		href = xmlnode_get_attrib(root, "href");
+
+		if (!href) {
+			href = xmlnode_get_attrib(root, "HREF");
+		}
+
+		link_text = xmlnode_get_data(root);
+
+		if (href) {
+			if (g_str_equal(link_text, href)) {
+				/* Purple gives us: <a href="URL">URL</a>
+				 * Translate to <a h='URL' />
+				 * Displayed as text of URL with link to URL
+				 */
+				*begin = g_strdup_printf("<a h='%s' />", href);
+			} else {
+				/* But if we get: <a href="URL">text</a>
+				 * Translate to: text: <a h='URL' />
+				 *
+				 * Because official client only supports self-closed <a>
+				 * tags; you can't change the link text.
+				 */
+				*begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
+			}
+		} else {
+			*begin = g_strdup("<a />");
+		}
+
+		/* Sorry, kid. MySpace doesn't support you within <a> tags. */
+		xmlnode_free(root->child);
+		root->child = NULL;
+
+		*end = g_strdup("");
+	} else if (!purple_utf8_strcasecmp(root->name, "font")) {
+		const gchar *size;
+		const gchar *face;
+
+		size = xmlnode_get_attrib(root, "size");
+		face = xmlnode_get_attrib(root, "face");
+
+		if (face && size) {
+			*begin = g_strdup_printf("<f f='%s' h='%d'>", face, 
+					msim_point_to_height(session,
+						msim_purple_size_to_point(session, atoi(size))));
+		} else if (face) {
+			*begin = g_strdup_printf("<f f='%s'>", face);
+		} else if (size) {
+			*begin = g_strdup_printf("<f h='%d'>", 
+					 msim_point_to_height(session,
+						 msim_purple_size_to_point(session, atoi(size))));
+		} else {
+			*begin = g_strdup("<f>");
+		}
+
+		*end = g_strdup("</f>");
+
+		/* TODO: color (bg uses <body>), emoticons */
+	} else {
+
+#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS
+		*begin = g_strdup_printf("[%s]", root->name);
+		*end = g_strdup_printf("[/%s]", root->name);
+#else
+		*begin = g_strdup("");
+		*end = g_strdup("");
+#endif
+	}
+}
+
+/** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
+ *
+ * @param f Function to convert tags.
+ *
+ * @return An HTML string. Caller frees.
+ */
+static gchar *
+msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f)
+{
+	xmlnode *node;
+	gchar *begin, *inner, *end;
+	GString *final;
+
+	if (!root || !root->name) {
+		return g_strdup("");
+	}
+
+	purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
+			root->name);
+
+	begin = inner = end = NULL;
+
+	final = g_string_new("");
+
+	f(session, root, &begin, &end);
+	
+	g_string_append(final, begin);
+
+	/* Loop over all child nodes. */
+	for (node = root->child; node != NULL; node = node->next) {
+		switch (node->type) {
+		case XMLNODE_TYPE_ATTRIB:
+			/* Attributes handled above. */
+			break;
+
+		case XMLNODE_TYPE_TAG:
+			/* A tag or tag with attributes. Recursively descend. */
+			inner = msim_convert_xmlnode(session, node, f);
+			g_return_val_if_fail(inner != NULL, NULL);
+
+			purple_debug_info("msim", " ** node name=%s\n", 
+					(node && node->name) ? node->name : "(NULL)");
+			break;
+	
+		case XMLNODE_TYPE_DATA:
+			/* Literal text. */
+			inner = g_new0(char, node->data_sz + 1);
+			strncpy(inner, node->data, node->data_sz);
+			inner[node->data_sz] = 0;
+
+			purple_debug_info("msim", " ** node data=%s\n", 
+					inner ? inner : "(NULL)");
+			break;
+			
+		default:
+			purple_debug_info("msim",
+					"msim_convert_xmlnode: strange node\n");
+			inner = g_strdup("");
+		}
+
+		if (inner) {
+			g_string_append(final, inner);
+		}
+	}
+
+	/* TODO: Note that msim counts each piece of text enclosed by <f> as
+	 * a paragraph and will display each on its own line. You actually have
+	 * to _nest_ <f> tags to intersperse different text in one paragraph!
+	 * Comment out this line below to see. */
+	g_string_append(final, end);
+
+	purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n",
+			(final && final->str) ? final->str : "(NULL)");
+
+	return final->str;
+}
+
+/** Convert XML to something based on MSIM_XMLNODE_CONVERT. */
+static gchar *
+msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
+{
+	xmlnode *root;
+	gchar *str;
+	gchar *enclosed_raw;
+
+	g_return_val_if_fail(raw != NULL, NULL);
+
+	/* Enclose text in one root tag, to try to make it valid XML for parsing. */
+	enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
+
+	root = xmlnode_from_str(enclosed_raw, -1);
+
+	if (!root) {
+		purple_debug_info("msim", "msim_markup_to_html: couldn't parse "
+				"%s as XML, returning raw: %s\n", enclosed_raw, raw);
+		/* TODO: msim_unrecognized */
+		g_free(enclosed_raw);
+		return g_strdup(raw);
+	}
+
+	g_free(enclosed_raw);
+
+	str = msim_convert_xmlnode(session, root, f);
+	g_return_val_if_fail(str != NULL, NULL);
+	purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str);
+
+	xmlnode_free(root);
+
+	return str;
+}
+
+/** Convert plaintext smileys to <i> markup tags.
+ *
+ * @param before Original text with ASCII smileys. Will be freed.
+ * @return A new string with <i> tags, if applicable. Must be g_free()'d.
+ */
+static gchar *
+msim_convert_smileys_to_markup(gchar *before)
+{
+	gchar *old, *new, *replacement;
+	guint i;
+	struct MSIM_EMOTICON *emote;
+
+	old = before;
+	new = NULL;
+
+	for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
+		gchar *name, *symbol;
+
+		name = emote->name;
+		symbol = emote->symbol;
+
+		replacement = g_strdup_printf("<i n=\"%s\"/>", name);
+
+		purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
+				symbol ? symbol : "(NULL)", 
+				replacement ? replacement : "(NULL)");
+		new = purple_strreplace(old, symbol, replacement);
+		
+		g_free(replacement);
+		g_free(old);
+
+		old = new;
+	}
+
+	return new;
+}
+	
+
+/** High-level function to convert MySpaceIM markup to Purple (HTML) markup. 
+ *
+ * @return Purple markup string, must be g_free()'d. */
+gchar *
+msim_markup_to_html(MsimSession *session, const gchar *raw)
+{
+	return msim_convert_xml(session, raw, 
+			(MSIM_XMLNODE_CONVERT)(msim_markup_tag_to_html));
+}
+
+/** High-level function to convert Purple (HTML) to MySpaceIM markup.
+ *
+ * TODO: consider using purple_markup_html_to_xhtml() to make valid XML.
+ *
+ * @return HTML markup string, must be g_free()'d. */
+gchar *
+html_to_msim_markup(MsimSession *session, const gchar *raw)
+{
+	gchar *markup;
+
+	markup = msim_convert_xml(session, raw,
+			(MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup));
+	
+	if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
+		/* Frees markup and allocates a new one. */
+		markup = msim_convert_smileys_to_markup(markup);
+	}
+
+	return markup;
+}
+
+
--- a/libpurple/protocols/myspace/myspace.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/protocols/myspace/myspace.h	Mon Sep 17 17:51:22 2007 +0000
@@ -67,6 +67,9 @@
 /*#define MSIM_DEBUG_LOGIN_CHALLENGE*/
 /*#define MSIM_DEBUG_RXBUF            */
 
+/* Encode unknown HTML tags in messages in [], instead of ignoring */
+#define MSIM_MARKUP_SHOW_UNKNOWN_TAGS 
+
 /* Define to cause init_plugin() to run some tests and print
  * the results to the Purple debug log, then exit. Useful to 
  * run with 'pidgin -d' to see the output. Don't define if
--- a/libpurple/proxy.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/proxy.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file proxy.c Proxy API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/proxy.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/proxy.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file proxy.h Proxy API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/prpl.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/prpl.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file prpl.h Protocol Plugin functions
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/request.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/request.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file request.c Request API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/request.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/request.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file request.h Request API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/roomlist.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/roomlist.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file roomlist.c Room List API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/roomlist.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/roomlist.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file roomlist.h Room List API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/savedstatuses.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/savedstatuses.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file savedstatuses.c Saved Status API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/savedstatuses.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/savedstatuses.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file savedstatuses.h Saved Status API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/server.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/server.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file server.h Server API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/signals.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/signals.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file signals.c Signal API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/signals.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/signals.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file signals.h Signal API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/sound.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/sound.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file sound.h Sound API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/sslconn.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/sslconn.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file sslconn.c SSL API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/sslconn.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/sslconn.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file sslconn.h SSL API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/status.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/status.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file status.c Status API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/stringref.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/stringref.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file stringref.c Reference-counted immutable strings
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/stringref.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/stringref.h	Mon Sep 17 17:51:22 2007 +0000
@@ -3,8 +3,9 @@
 /**
  * @file stringref.h Reference-counted immutable strings
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/stun.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/stun.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file stun.c STUN (RFC3489) Implementation
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * STUN implementation inspired by jstun [http://jstun.javawi.de/]
  *
--- a/libpurple/stun.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/stun.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file stun.h STUN API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/upnp.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/upnp.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file upnp.c UPnP Implementation
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/upnp.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/upnp.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file upnp.h Universal Plug N Play API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/util.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/util.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file util.h Utility Functions
  * @ingroup core
- *
- * Purple is the legal property of its developers, whose names are too numerous
+ */
+
+/* Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
  *
@@ -67,7 +68,7 @@
 };
 
 static char *custom_user_dir = NULL;
-static char *home_dir = NULL;
+static char *user_dir = NULL;
 
 PurpleMenuAction *
 purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data,
@@ -2463,10 +2464,10 @@
 {
 	if (custom_user_dir != NULL)
 		return custom_user_dir;
-	else if (!home_dir)
-		home_dir = g_build_filename(purple_home_dir(), ".purple", NULL);
-
-	return home_dir;
+	else if (!user_dir)
+		user_dir = g_build_filename(purple_home_dir(), ".purple", NULL);
+
+	return user_dir;
 }
 
 void purple_util_set_user_dir(const char *dir)
--- a/libpurple/util.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/util.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file util.h Utility Functions
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/value.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/value.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file value.c Value wrapper API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/value.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/value.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file value.h Value wrapper API
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/version.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/version.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file version.c Version Functions
  * @ingroup core
- *
- * Purple is the legal property of its developers, whose names are too numerous
+ */
+
+/* Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
  * source distribution.
  *
--- a/libpurple/whiteboard.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/whiteboard.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file whiteboard.h The PurpleWhiteboard core object
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/xmlnode.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/xmlnode.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file xmlnode.c XML DOM functions
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/libpurple/xmlnode.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/libpurple/xmlnode.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file xmlnode.h XML DOM functions
  * @ingroup core
- *
- * purple
+ */
+
+/* purple
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkaccount.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkaccount.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkaccount.c GTK+ Account Editor UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkaccount.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkaccount.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkaccount.h GTK+ Account Editor UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkblist.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkblist.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkblist.c GTK+ BuddyList API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -87,6 +88,8 @@
 	GtkWidget *group_combo;
 	GtkWidget *entries_box;
 	GtkSizeGroup *sg;
+	GtkWidget *autojoin;
+	GtkWidget *persistent;
 
 	GList *entries;
 
@@ -317,8 +320,8 @@
 
 static void gtk_blist_menu_move_to_cb(GtkWidget *w, PurpleBlistNode *node)
 {
-	PurpleBlistNode *group = g_object_get_data(w, "groupnode");
-	purple_blist_add_contact(node, group, NULL);
+	PurpleGroup *group = g_object_get_data(G_OBJECT(w), "groupnode");
+	purple_blist_add_contact((PurpleContact *)node, group, NULL);
 
 }
 
@@ -471,9 +474,9 @@
 		if (node == contact)
 			continue;
 
-		purple_blist_merge_contact(node, contact);
-	}
-	
+		purple_blist_merge_contact((PurpleContact *)node, contact);
+	}
+
 	/* And show the expanded contact, so the people know what's going on */
 	pidgin_blist_expand_contact_cb(NULL, contact);
 	g_list_free(merges);
@@ -487,14 +490,13 @@
 	GList *merges = NULL;
 	int i = 0;
 	char *a = g_utf8_casefold(alias, -1);
-	char *msg;
 
 	for (contact = group->child; contact; contact = contact->next) {
 		char *node_alias;
 		if (contact->type != PURPLE_BLIST_CONTACT_NODE)
 			continue;
-		
-		node_alias = g_utf8_casefold(purple_contact_get_alias(contact), -1);
+
+		node_alias = g_utf8_casefold(purple_contact_get_alias((PurpleContact *)contact), -1);
 		if (node_alias && !g_utf8_collate(node_alias, a)) {
 			merges = g_list_append(merges, contact);
 			i++;
@@ -506,8 +508,8 @@
 		for (buddy = contact->child; buddy; buddy = buddy->next) {
 			if (buddy->type != PURPLE_BLIST_BUDDY_NODE)
 				continue;
-	
-			node_alias = g_utf8_casefold(purple_buddy_get_alias(buddy), -1);
+
+			node_alias = g_utf8_casefold(purple_buddy_get_alias((PurpleBuddy *)buddy), -1);
 			if (node_alias && !g_utf8_collate(node_alias, a)) {
 				merges = g_list_append(merges, buddy);
 				i++;
@@ -517,11 +519,15 @@
 	}
 	g_free(a);
 	
-	msg = g_strdup_printf(ngettext("You can't merge one contact. That doesn't make any sense. You should never see this message ever", "You currently have %d contacts named %s. Would you like to merge them?", i), i, alias);
 	if (i > 1)
+	{
+		char *msg = g_strdup_printf(ngettext("You currently have %d contact named %s. Would you like to merge them?", "You currently have %d contacts named %s. Would you like to merge them?", i), i, alias);
 		purple_request_action(NULL, NULL, msg, _("Merging these contacts will cause them to share a single entry on the buddy list and use a single conversation window. "
 							 "You can separate them again by choosing 'Expand' from the contact's context menu"), 0, NULL, NULL, NULL,
 				      merges, 2, _("_Merge"), PURPLE_CALLBACK(gtk_blist_do_personize), _("_Cancel"), PURPLE_CALLBACK(g_list_free));
+		g_free(msg);
+	} else
+		g_list_free(merges);
 }
 
 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1,
@@ -1264,14 +1270,14 @@
 	gtk_widget_show(menuitem);
 
 	submenu = gtk_menu_new();
-	gtk_menu_item_set_submenu(menuitem, submenu);
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
 
 	for (group = purple_blist_get_root(); group; group = group->next) {
 		if (group->type != PURPLE_BLIST_GROUP_NODE)
 			continue;
 		if (group == node->parent)
 			continue;
-		menuitem = pidgin_new_item_from_stock(submenu, purple_group_get_name(group), NULL,
+		menuitem = pidgin_new_item_from_stock(submenu, purple_group_get_name((PurpleGroup *)group), NULL,
 						      G_CALLBACK(gtk_blist_menu_move_to_cb), node, 0, 0, NULL);
 		g_object_set_data(G_OBJECT(menuitem), "groupnode", group);
 	}
@@ -1330,7 +1336,7 @@
 	pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
 
 	if (!contact_expanded)
-		pidgin_append_blist_node_move_to_menu(menu, contact);
+		pidgin_append_blist_node_move_to_menu(menu, (PurpleBlistNode *)contact);
 
 	if (((PurpleBlistNode*)buddy)->parent && ((PurpleBlistNode*)buddy)->parent->child->next && 
               !sub && !contact_expanded) {
@@ -5897,6 +5903,12 @@
 		purple_blist_add_chat(chat, group, NULL);
 	}
 
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin)))
+		purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", TRUE);
+
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent)))
+		purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", TRUE);
+
 	gtk_widget_destroy(data->window);
 	g_free(data->default_chat_name);
 	g_list_free(data->entries);
@@ -6191,6 +6203,11 @@
 	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);
+	
+	data->autojoin = gtk_check_button_new_with_mnemonic(_("Autojoin when account becomes online."));
+	data->persistent = gtk_check_button_new_with_mnemonic(_("Hide chat when the window is closed."));
+	gtk_box_pack_start(GTK_BOX(vbox), data->autojoin, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), data->persistent, FALSE, FALSE, 0);
 
 	g_signal_connect(G_OBJECT(data->window), "response",
 					 G_CALLBACK(add_chat_resp_cb), data);
--- a/pidgin/gtkblist.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkblist.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkblist.h GTK+ Buddy List API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkcellrendererexpander.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkcellrendererexpander.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkcellrendererexpander.c GTK+ Cell Renderer Expander
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -269,7 +270,9 @@
 			    cell_area->x + cell->xpad + (width / 2),
 			    cell_area->y + cell->ypad + (height / 2),
 			    cell->is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED);
-	gtk_paint_hline (widget->style, window, state, NULL, widget, NULL, 0, widget->allocation.width, cell_area->y + cell_area->height);
+	if (cell->is_expanded)
+		gtk_paint_hline (widget->style, window, state, NULL, widget, NULL, 0, 
+				 widget->allocation.width, cell_area->y + cell_area->height);
 }
 
 static gboolean pidgin_cell_renderer_expander_activate(GtkCellRenderer *r,
--- a/pidgin/gtkcellrendererprogress.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkcellrendererprogress.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkcellrendererprogress.c GTK+ Cell Renderer Progress
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkcertmgr.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkcertmgr.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkcertmgr.c GTK+ Certificate Manager API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkconn.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkconn.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkconn.c GTK+ Connection API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -53,7 +54,7 @@
  * The key is a pointer to the PurpleAccount and the
  * value is a pointer to a PidginAutoRecon.
  */
-static GHashTable *hash = NULL;
+static GHashTable *auto_reconns = NULL;
 
 static void
 pidgin_connection_connect_progress(PurpleConnection *gc,
@@ -80,7 +81,7 @@
 		pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
 					   (purple_connections_get_connecting() != NULL));
 
-	g_hash_table_remove(hash, account);
+	g_hash_table_remove(auto_reconns, account);
 
 	pidgin_blist_update_account_error_state(account, NULL);
 }
@@ -120,7 +121,7 @@
 
 	purple_debug_info("autorecon", "do_signon called\n");
 	g_return_val_if_fail(account != NULL, FALSE);
-	info = g_hash_table_lookup(hash, account);
+	info = g_hash_table_lookup(auto_reconns, account);
 
 	if (info)
 		info->timeout = 0;
@@ -145,13 +146,13 @@
 	PidginAutoRecon *info;
 
 	account = purple_connection_get_account(gc);
-	info = g_hash_table_lookup(hash, account);
+	info = g_hash_table_lookup(auto_reconns, account);
 
 	pidgin_blist_update_account_error_state(account, text);
 	if (!purple_connection_reason_is_fatal (reason)) {
 		if (info == NULL) {
 			info = g_new0(PidginAutoRecon, 1);
-			g_hash_table_insert(hash, account, info);
+			g_hash_table_insert(auto_reconns, account, info);
 			info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX);
 		} else {
 			info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
@@ -162,7 +163,7 @@
 	} else {
 		char *p, *s, *n=NULL ;
 		if (info != NULL)
-			g_hash_table_remove(hash, account);
+			g_hash_table_remove(auto_reconns, account);
 
 		if (purple_account_get_alias(account))
 		{
@@ -206,7 +207,7 @@
 
 	while (list) {
 		PurpleAccount *account = (PurpleAccount*)list->data;
-		g_hash_table_remove(hash, account);
+		g_hash_table_remove(auto_reconns, account);
 		if (purple_account_is_disconnected(account))
 			do_signon(account);
 		list = list->next;
@@ -267,7 +268,7 @@
 static void
 account_removed_cb(PurpleAccount *account, gpointer user_data)
 {
-	g_hash_table_remove(hash, account);
+	g_hash_table_remove(auto_reconns, account);
 
 	pidgin_blist_update_account_error_state(account, NULL);
 }
@@ -288,7 +289,7 @@
 void
 pidgin_connection_init(void)
 {
-	hash = g_hash_table_new_full(
+	auto_reconns = g_hash_table_new_full(
 							g_direct_hash, g_direct_equal,
 							NULL, free_auto_recon);
 
@@ -302,5 +303,5 @@
 {
 	purple_signals_disconnect_by_handle(pidgin_connection_get_handle());
 
-	g_hash_table_destroy(hash);
+	g_hash_table_destroy(auto_reconns);
 }
--- a/pidgin/gtkconn.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkconn.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file gtkconn.h GTK+ Connection API
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkconv.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkconv.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkconv.c GTK+ Conversation API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -219,7 +220,7 @@
 }
 
 static gboolean
-close_conv_cb(GtkWidget *w, GdkEventButton *event, PidginConversation *gtkconv)
+close_conv_cb(GtkWidget *w, GdkEventButton *dontuse, PidginConversation *gtkconv)
 {
 	/* We are going to destroy the conversations immediately only if the 'close immediately'
 	 * preference is selected. Otherwise, close the conversation after a reasonable timeout
@@ -1912,6 +1913,7 @@
 				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
 						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
 						curconv - 1);
+				return TRUE;
 				break;
 
 			case GDK_period:
@@ -1922,6 +1924,7 @@
 #else
 						(curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children));
 #endif
+				return TRUE;
 				break;
 
 		} /* End of switch */
@@ -8833,15 +8836,10 @@
 
 	if (win->gtkconvs) {
 		while (win->gtkconvs) {
-			GList *nextgtk = win->gtkconvs->next;
-			PidginConversation *gtkconv = win->gtkconvs->data;
-			GList *nextcore = gtkconv->convs->next;
-			PurpleConversation *conv = gtkconv->convs->data;
-			purple_conversation_destroy(conv);
-			if (!nextgtk && !nextcore)
-			/* we'll end up invoking ourselves when we destroy our last child */
-			/* so don't destroy ourselves right now */
-				return;
+			gboolean last = (win->gtkconvs->next == NULL);
+			close_conv_cb(NULL, NULL, win->gtkconvs->data);
+			if (last)
+				break;
 		}
 		return;
 	}
--- a/pidgin/gtkconv.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkconv.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkconv.h GTK+ Conversation API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkconvwin.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkconvwin.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkconvwin.h GTK+ Conversation Window API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdebug.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkdebug.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkdebug.c GTK+ Debug API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdebug.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkdebug.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkdebug.h GTK+ Debug API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdialogs.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkdialogs.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkdialogs.c GTK+ Dialogs
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdialogs.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkdialogs.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @defgroup pidgin Pidgin (GTK+ User Interface)
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdnd-hints.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkdnd-hints.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkdnd-hints.c GTK+ Drag-and-Drop arrow hints
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkdnd-hints.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkdnd-hints.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkdnd-hints.h GTK+ Drag-and-Drop arrow hints
  * @ingroup pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
+ */
+
+/* Pidgin 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.
  *
--- a/pidgin/gtkeventloop.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkeventloop.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtk_eventloop.c Purple Event Loop API (gtk implementation)
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkeventloop.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkeventloop.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkeventloop.h Pidgin GTK+ Event Loop Implementation
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkft.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkft.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkft.c GTK+ File Transfer UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkft.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkft.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkft.h GTK+ File Transfer UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkgaim-compat.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkgaim-compat.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file gtkgaim-compat.h Gtk Gaim Compat macros
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkidle.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkidle.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkidle.h GTK+ Idle API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkimhtml.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkimhtml.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkimhtml.c GTK+ IMHtml
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkimhtml.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkimhtml.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkimhtml.h GTK+ IM/HTML rendering component
  * @ingroup pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
+ */
+
+/* Pidgin 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.
  *
--- a/pidgin/gtkimhtmltoolbar.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkimhtmltoolbar.c GTK+ IMHtml Toolbar
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -1162,6 +1163,7 @@
 	GtkWidget *label;
 	GtkWidget *insert_button;
 	GtkWidget *font_button;
+	GtkWidget *smiley_button;
 	GtkWidget *font_menu;
 	GtkWidget *insert_menu;
 	GtkWidget *menuitem;
@@ -1263,12 +1265,6 @@
 	insert_menu = gtk_menu_new();
 	g_object_set_data(G_OBJECT(toolbar), "insert_menu", insert_menu);
 
-	menuitem = gtk_menu_item_new_with_mnemonic(_("_Smiley"));
-	g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->smiley);
-	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem);
-	g_signal_connect(G_OBJECT(toolbar->smiley), "notify::sensitive",
-			G_CALLBACK(button_sensitiveness_changed), menuitem);
-
 	menuitem = gtk_menu_item_new_with_mnemonic(_("_Image"));
 	g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), toolbar->image);
 	gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem);
@@ -1290,6 +1286,24 @@
 	g_signal_connect(G_OBJECT(insert_button), "activate", G_CALLBACK(pidgin_menu_clicked), insert_menu);
 	g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button);
 	toolbar->sml = NULL;
+	
+	/* Sep */
+	sep = gtk_vseparator_new();
+	gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0);
+	gtk_widget_show_all(sep);
+
+	/* Smiley */
+	smiley_button = gtk_button_new();
+	gtk_button_set_relief(GTK_BUTTON(smiley_button), GTK_RELIEF_NONE);
+	bbox = gtk_hbox_new(FALSE, 3);
+	gtk_container_add(GTK_CONTAINER(smiley_button), bbox);
+	image = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
+	gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0);
+	label = gtk_label_new_with_mnemonic(_("_Smiley"));
+	gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(box), smiley_button, FALSE, FALSE, 0);
+	g_signal_connect_swapped(G_OBJECT(smiley_button), "clicked", G_CALLBACK(gtk_button_clicked), toolbar->smiley);
+	gtk_widget_show_all(smiley_button);
 
 	gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0);
 	g_object_set_data(G_OBJECT(hbox), "lean-view", box);
--- a/pidgin/gtklog.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtklog.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtklog.c GTK+ Log viewer
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtklog.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtklog.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtklog.h GTK+ Log viewer
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkmain.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkmain.c	Mon Sep 17 17:51:22 2007 +0000
@@ -394,6 +394,9 @@
 		       "  -n, --nologin       don't automatically login\n"
 		       "  -l, --login[=NAME]  automatically login (optional argument NAME specifies\n"
 		       "                      account(s) to use, separated by commas)\n"
+#ifndef WIN32
+		       "  --display=DISPLAY   X display to use\n"
+#endif
 		       "  -v, --version       display the current version and exit\n"), PIDGIN_NAME, VERSION, name);
 	}
 
@@ -481,6 +484,7 @@
 		{"nologin",  no_argument,       NULL, 'n'},
 		{"session",  required_argument, NULL, 's'},
 		{"version",  no_argument,       NULL, 'v'},
+		{"display",  required_argument, NULL, 'D'},
 		{0, 0, 0, 0}
 	};
 
@@ -626,6 +630,9 @@
 		case 'm':   /* do not ensure single instance. */
 			opt_si = FALSE;
 			break;
+		case 'D':   /* --display */
+			/* handled by gtk_init_check below */
+			break;
 		case '?':	/* show terse help */
 		default:
 			show_usage(argv[0], TRUE);
--- a/pidgin/gtkmenutray.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkmenutray.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkmenutray.h GTK+ Tray menu item
  * @ingroup pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
+ */
+
+/* Pidgin 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.
  *
--- a/pidgin/gtknickcolors.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtknickcolors.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtknickcolors.h GTK+ Conversation API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  * Pidgin 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.
--- a/pidgin/gtknotify.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtknotify.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtknotify.c GTK+ Notification API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -660,30 +661,30 @@
 	GtkTreeIter iter;
 	GdkPixbuf *pixbuf;
 	guint col_num;
-	guint i;
-	guint j;
+	GList *row, *column;
+	guint n;
 
 	gtk_list_store_clear(data->model);
 
 	pixbuf = pidgin_create_prpl_icon(purple_connection_get_account(gc), 0.5);
 
 	/* +1 is for the automagically created Status column. */
-	col_num = purple_notify_searchresults_get_columns_count(results) + 1;
+	col_num = g_list_length(results->columns) + 1;
 
-	for (i = 0; i < purple_notify_searchresults_get_rows_count(results); i++) {
-		GList *row = purple_notify_searchresults_row_get(results, i);
+	for (row = results->rows; row != NULL; row = row->next) {
 
 		gtk_list_store_append(model, &iter);
 		gtk_list_store_set(model, &iter, 0, pixbuf, -1);
 
-		for (j = 1; j < col_num; j++) {
+		n = 1;
+		for (column = row->data; column != NULL; column = column->next) {
 			GValue v;
-			char *data = g_list_nth_data(row, j - 1);
 
 			v.g_type = 0;
 			g_value_init(&v, G_TYPE_STRING);
-			g_value_set_string(&v, data);
-			gtk_list_store_set_value(model, &iter, j, &v);
+			g_value_set_string(&v, column->data);
+			gtk_list_store_set_value(model, &iter, n, &v);
+			n++;
 		}
 	}
 
@@ -703,6 +704,7 @@
 	GtkListStore *model;
 	GtkCellRenderer *renderer;
 	guint col_num;
+	GList *column;
 	guint i;
 
 	GtkWidget *vbox;
@@ -750,7 +752,7 @@
 	g_free(label_text);
 
 	/* +1 is for the automagically created Status column. */
-	col_num = purple_notify_searchresults_get_columns_count(results) + 1;
+	col_num = g_list_length(results->columns) + 1;
 
 	/* Setup the list model */
 	col_types = g_new0(GType, col_num);
@@ -785,12 +787,13 @@
 	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
 					-1, "", renderer, "pixbuf", 0, NULL);
 
-	for (i = 1; i < col_num; i++) {
+	i = 1;
+	for (column = results->columns; column != NULL; column = column->next) {
 		renderer = gtk_cell_renderer_text_new();
 
 		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1,
-				purple_notify_searchresults_column_get_title(results, i-1),
-				renderer, "text", i, NULL);
+				column->data, renderer, "text", i, NULL);
+		i++;
 	}
 
 	for (i = 0; i < g_list_length(results->buttons); i++) {
--- a/pidgin/gtknotify.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtknotify.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtknotify.h GTK+ Notification API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkplugin.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkplugin.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkplugin.c GTK+ Plugins support
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkplugin.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkplugin.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkplugin.h GTK+ Plugin API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpluginpref.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkpluginpref.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkpluginpref.c GTK+ Plugin preferences
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpluginpref.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkpluginpref.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkpluginpref.h GTK+ Plugin Preferences
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpounce.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkpounce.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkpounce.c GTK+ Buddy Pounce API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkpounce.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkpounce.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkpounce.h GTK+ Buddy Pounce API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprefs.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkprefs.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkprefs.c GTK+ Preferences
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprefs.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkprefs.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkprefs.h GTK+ Preferences
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprivacy.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkprivacy.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkprivacy.c GTK+ Privacy UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkprivacy.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkprivacy.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkprivacy.h GTK+ Privacy UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkrequest.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkrequest.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkrequest.c GTK+ Request API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -998,7 +999,6 @@
 
 	/* Create the tree view */
 	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
-	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
 	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
 
 	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
--- a/pidgin/gtkrequest.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkrequest.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkrequest.h GTK+ Request API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkroomlist.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkroomlist.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkroomlist.c GTK+ Room List UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkroomlist.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkroomlist.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkroomlist.h GTK+ Room List UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksavedstatuses.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtksavedstatus.c GTK+ Saved Status Editor UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksavedstatuses.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtksavedstatuses.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtksavedstatuses.h GTK+ Saved Status Editor UI
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkscrollbook.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkscrollbook.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkscrollbook.c GTK+ Scrolling notebook widget 
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkscrollbook.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkscrollbook.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkscrollbook  GTK+ Scrolling notebook Widget
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksession.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtksession.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtksession.c X Windows session management API
  * @ingroup pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
+ */
+
+/* Pidgin 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.
  *
@@ -35,6 +36,7 @@
 #include <gdk/gdkx.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <gdk/gdk.h>
 
 #define ERROR_LENGTH 512
 
@@ -140,7 +142,7 @@
 /* my magic utility function */
 
 static gchar **session_make_command(gchar *client_id, gchar *config_dir) {
-	gint i = 2;
+	gint i = 4;
 	gint j = 0;
 	gchar **ret;
 
@@ -160,6 +162,9 @@
 		ret[j++] = g_strdup(config_dir);
 	}
 
+	ret[j++] = g_strdup("--display");
+	ret[j++] = g_strdup((gchar *)gdk_display_get_name(gdk_display_get_default()));
+
 	ret[j++] = NULL;
 
 	return ret;
--- a/pidgin/gtksession.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtksession.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtksession.h X Windows session management API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksound.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtksound.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtksound.c GTK+ Sound
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtksound.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtksound.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtksound.h GTK+ Sound API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkstatusbox.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkstatusbox.c GTK+ Status Selection Widget
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkstatusbox.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkstatusbox.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /*
  * @file gtkstatusbox.c GTK+ Status Selection Widget
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkthemes.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkthemes.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkthemes.h GTK+ Smiley Theme API
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkutils.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkutils.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkutils.c GTK+ utility functions
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkutils.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkutils.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file gtkutils.h GTK+ utility functions
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/gtkwhiteboard.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/gtkwhiteboard.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,7 +1,8 @@
 /**
  * @file gtkwhiteboard.h The PidginWhiteboard frontend object
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/pidgin.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/pidgin.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file pidgin.h UI definitions and includes
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -26,12 +27,12 @@
 #ifndef _PIDGIN_H_
 #define _PIDGIN_H_
 
+#include <gtk/gtk.h>
+
 #ifdef GDK_WINDOWING_X11
 # include <gdk/gdkx.h>
 #endif
 
-#include <gtk/gtk.h>
-
 #ifdef _WIN32
 # include "gtkwin32dep.h"
 #endif
--- a/pidgin/pidginstock.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/pidginstock.c	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file pidginstock.c GTK+ Stock resources
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/pidginstock.h	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/pidginstock.h	Mon Sep 17 17:51:22 2007 +0000
@@ -1,8 +1,9 @@
 /**
  * @file pidginstock.h GTK+ Stock resources
  * @ingroup pidgin
- *
- * pidgin
+ */
+
+/* pidgin
  *
  * Pidgin is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
--- a/pidgin/plugins/history.c	Mon Sep 17 16:54:45 2007 +0000
+++ b/pidgin/plugins/history.c	Mon Sep 17 17:51:22 2007 +0000
@@ -45,6 +45,9 @@
 
 	convtype = purple_conversation_get_type(c);
 	gtkconv = PIDGIN_CONVERSATION(c);
+	if (gtkconv == NULL)
+		return;
+
 	if (convtype == PURPLE_CONV_TYPE_IM && g_list_length(gtkconv->convs) < 2)
 	{
 		GSList *buddies;
@@ -163,6 +166,7 @@
 	purple_signal_connect(purple_conversations_get_handle(),
 						"conversation-created",
 						plugin, PURPLE_CALLBACK(historize), NULL);
+	/* XXX: Do we want to listen to pidgin's "conversation-displayed" signal? */
 
 	purple_prefs_connect_callback(plugin, "/purple/logging/log_ims",
 								history_prefs_cb, plugin);