changeset 29456:89b95d143116

Propagated im.pidgin.pidgin to im.pidgin.cpw.rekkanoryo.icqxstatus and merged the smiley theme changes together.
author Richard Laager <rlaager@wiktel.com>
date Mon, 01 Dec 2008 23:36:00 +0000
parents 6476ee291f16 (diff) 93cb9f54df45 (current diff)
children 5391094529c6
files COPYRIGHT libpurple/protocols/jabber/jabber.c libpurple/protocols/sametime/sametime.c libpurple/request.c pidgin/gtkblist.c pidgin/gtkrequest.c pidgin/gtksavedstatuses.c pidgin/pixmaps/Makefile.am pidgin/pixmaps/emblems/16/mobile.png pidgin/pixmaps/emblems/16/music.png pidgin/pixmaps/emblems/16/scalable/mobile.svg pidgin/pixmaps/emblems/16/scalable/music.svg pidgin/pixmaps/emotes/default/24/default.theme.in pidgin/pixmaps/emotes/default/24/eat.png pidgin/pixmaps/emotes/default/24/in-love.png pidgin/pixmaps/emotes/default/24/love.png pidgin/pixmaps/emotes/default/24/nailbiting.png pidgin/pixmaps/emotes/default/24/shock.png pidgin/pixmaps/emotes/default/24/smile-big.png pidgin/pixmaps/emotes/default/24/smile.png pidgin/pixmaps/emotes/default/24/sweat.png pidgin/pixmaps/emotes/default/24/tremble.png pidgin/pixmaps/emotes/default/24/yawn.png pidgin/pixmaps/emotes/small/16/love.png pidgin/pixmaps/emotes/small/16/shock.png pidgin/pixmaps/emotes/small/16/small.theme.in pidgin/pixmaps/emotes/small/16/smile-big.png pidgin/pixmaps/emotes/small/16/smile.png pidgin/pixmaps/emotes/small/16/yawn.png pidgin/pixmaps/status/48/rtl/login.png pidgin/pixmaps/status/48/rtl/logout.png
diffstat 52 files changed, 320 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Wed Nov 26 22:44:08 2008 +0000
+++ b/COPYRIGHT	Mon Dec 01 23:36:00 2008 +0000
@@ -340,6 +340,7 @@
 Dennis Ristuccia
 Lee Roach
 Eion Robb
+Kahlil Robinson
 Rhett Robinson
 Luciano Miguel Ferreira Rocha
 Andrew Rodland
@@ -351,6 +352,7 @@
 Michael Ruprecht
 Sam S.
 Thanumalayan S.
+Jonathan Sailor
 Elliott Sales de Andrade
 Tomasz Sałaciński <tsalacinski@gmail.com>
 Pradyumna Sampath
--- a/ChangeLog	Wed Nov 26 22:44:08 2008 +0000
+++ b/ChangeLog	Mon Dec 01 23:36:00 2008 +0000
@@ -8,13 +8,33 @@
 	  --with-system-ssl-certs and GnuTLS need to include these in the
 	  system certs directory.
 	* Corrected maximum message lengths for Yahoo!
-	* Fix some problems with Gadu-Gadu buddy icons (Adam Strzelecki)
 	* Enable auto-reply on Zephyr, to emulate 'zaway' (Toby Schaffer)
 	* The Buddy State Notification plugin no longer prints duplicate
 	  notifications when the same buddy is in multiple groups (Florian Quèze)
 	* The Buddy State Notification plugin no longer turns JID's, MSN Passport
 	  ID's, etc. into links (Florian Quèze)
 	* Fix a crash in SIMPLE when a malformed message is received.
+	* purple-remote now has a "getstatusmessage" command to retrieve the text
+	  of the current status message.
+
+	Gadu-Gadu:
+	* Fix some problems with Gadu-Gadu buddy icons (Adam Strzelecki)
+	* Gadu-Gadu now validates that UID's are valid (Adam Strzelecki)
+	* Gadu-Gadu now does proper charset translations where needed (Adam
+	  Strzelecki)
+
+	XMPP:
+	* Fix the namespace URL we look for in PEP reply stanzas to match the URL
+	  used in the 'get' requests (Paul Aurich)
+	* Resources can be set to the local machine's hostname by using
+	  __HOSTNAME__ as the resource string (Jonathan Sailor)
+	* Resources can now be left blank, causing the server to generate a
+	  resource for us where supported (Jonathan Sailor)
+	* Resources now default to no value
+	* Quit trying to get user info for MUC's (Paul Aurich)
+	* Send "client-accepts-full-bind-result" attribute during SASL login.
+	  This will fix Google Talk login failures if the user configures the
+	  wrong domain for his/her account.
 
 	Pidgin:
 	* On GTK+ 2.14 and higher, we're using the gtk-tooltip-delay setting
--- a/Makefile.am	Wed Nov 26 22:44:08 2008 +0000
+++ b/Makefile.am	Mon Dec 01 23:36:00 2008 +0000
@@ -59,7 +59,7 @@
 # Ensure we're working from a tag...
 	test x`mtn automate select t:v$(PACKAGE_VERSION)` = x`mtn automate get_base_revision_id`
 # ... and have no changes in the working copy.
-	test x`mtn diff | grep -v '^#'` = x
+	test "x`mtn diff | grep -v '^#'`" = x
 
 release: version-check distcheck packages
 
--- a/finch/gntdebug.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/gntdebug.c	Mon Dec 01 23:36:00 2008 +0000
@@ -344,6 +344,7 @@
 	REGISTER_G_LOG_HANDLER("GModule");
 	REGISTER_G_LOG_HANDLER("GLib-GObject");
 	REGISTER_G_LOG_HANDLER("GThread");
+	REGISTER_G_LOG_HANDLER("Gnt");
 #ifdef USE_GSTREAMER
 	REGISTER_G_LOG_HANDLER("GStreamer");
 #endif
--- a/finch/libgnt/Makefile.am	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/Makefile.am	Mon Dec 01 23:36:00 2008 +0000
@@ -6,6 +6,8 @@
 
 lib_LTLIBRARIES = libgnt.la
 
+noinst_HEADERS = gntinternal.h
+
 BUILT_SOURCES = gntmarshal.h
 
 libgnt_la_SOURCES = \
--- a/finch/libgnt/gntbindable.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntbindable.c	Mon Dec 01 23:36:00 2008 +0000
@@ -22,6 +22,10 @@
 
 #include <string.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Bindable"
+
 #include "gntbindable.h"
 #include "gntstyle.h"
 #include "gnt.h"
@@ -360,7 +364,7 @@
 
 	action = g_hash_table_lookup(klass->actions, name);
 	if (!action) {
-		g_printerr("GntBindable: Invalid action name %s for %s\n",
+		gnt_warning("Invalid action name %s for %s",
 				name, g_type_name(G_OBJECT_CLASS_TYPE(klass)));
 		if (list)
 			g_list_free(list);
--- a/finch/libgnt/gntcolors.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntcolors.c	Mon Dec 01 23:36:00 2008 +0000
@@ -24,6 +24,10 @@
 
 #include <ncurses.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Colors"
+
 #include "gntcolors.h"
 #include "gntstyle.h"
 
@@ -182,7 +186,7 @@
 
 	if (error)
 	{
-		g_printerr("GntColors: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		error = NULL;
 	}
@@ -226,7 +230,7 @@
 
 	if (error)
 	{
-		g_printerr("GntColors: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		return;
 	}
--- a/finch/libgnt/gntentry.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntentry.c	Mon Dec 01 23:36:00 2008 +0000
@@ -365,7 +365,7 @@
 		return TRUE;
 
 	len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor);
-	update_kill_ring(entry, ENTRY_DEL_BWD_CHAR, entry->cursor, -len);
+	update_kill_ring(entry, ENTRY_JAIL, entry->cursor, -len);
 	entry->cursor -= len;
 
 	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor);
@@ -391,7 +391,7 @@
 		return FALSE;
 
 	len = g_utf8_find_next_char(entry->cursor, NULL) - entry->cursor;
-	update_kill_ring(entry, ENTRY_DEL_FWD_CHAR, entry->cursor, len);
+	update_kill_ring(entry, ENTRY_JAIL, entry->cursor, len);
 	memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor - len + 1);
 	entry->end -= len;
 	entry_redraw(GNT_WIDGET(entry));
--- a/finch/libgnt/gntfilesel.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntfilesel.c	Mon Dec 01 23:36:00 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "FileSel"
+
 #include "gntbutton.h"
 #include "gntentry.h"
 #include "gntfilesel.h"
@@ -254,7 +258,7 @@
 		struct stat st;
 
 		if (stat(fp, &st)) {
-			g_printerr("Error stating location %s\n", fp);
+			gnt_warning("Error stating location %s", fp);
 		} else {
 			if (S_ISDIR(st.st_mode)) {
 				file = gnt_file_new_dir(str);
@@ -309,7 +313,7 @@
 		success = local_read_fn(sel->current, &files, err);
 	
 	if (!success || *err) {
-		g_printerr("GntFileSel: error opening location %s (%s)\n",
+		gnt_warning("error opening location %s (%s)",
 			sel->current, *err ? (*err)->message : "reason unknown");
 		return FALSE;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/gntinternal.h	Mon Dec 01 23:36:00 2008 +0000
@@ -0,0 +1,33 @@
+/*
+ * GNT - The GLib Ncurses Toolkit
+ *
+ * GNT is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This library 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
+ */
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "Gnt"
+
+#ifdef __GNUC__
+# ifndef GNT_LOG_DOMAIN
+#  define GNT_LOG_DOMAIN ""
+# endif
+# define gnt_warning(format, args...)  g_warning("(%s) %s: " format, GNT_LOG_DOMAIN, __PRETTY_FUNCTION__, args)
+#else /* __GNUC__ */
+# define gnt_warning g_warning
+#endif
+
--- a/finch/libgnt/gntkeys.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntkeys.c	Mon Dec 01 23:36:00 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Keys"
+
 #include "gntkeys.h"
 
 #include <glib.h>
--- a/finch/libgnt/gntmain.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntmain.c	Mon Dec 01 23:36:00 2008 +0000
@@ -32,6 +32,10 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Main"
+
 #include "gnt.h"
 #include "gntbox.h"
 #include "gntbutton.h"
@@ -319,7 +323,7 @@
 	                                 But irssi does this, so I am going to assume the
 	                                 crashes were caused by some other stuff. */
 
-	g_printerr("gntmain: setting up IO (%d)\n", channel_read_callback);
+	gnt_warning("setting up IO (%d)", channel_read_callback);
 }
 
 static gboolean
--- a/finch/libgnt/gntstyle.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntstyle.c	Mon Dec 01 23:36:00 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Style"
+
 #include "gntstyle.h"
 #include "gntcolors.h"
 #include "gntws.h"
@@ -226,7 +230,7 @@
 		keys = g_key_file_get_keys(gkfile, name, &len, &error);
 		if (error)
 		{
-			g_printerr("GntStyle: %s\n", error->message);
+			gnt_warning("%s", error->message);
 			g_error_free(error);
 			g_free(name);
 			return;
@@ -241,7 +245,7 @@
 
 			if (error)
 			{
-				g_printerr("GntStyle: %s\n", error->message);
+				gnt_warning("%s", error->message);
 				g_error_free(error);
 				error = NULL;
 			}
@@ -249,7 +253,7 @@
 			{
 				const char *keycode = parse_key(key);
 				if (keycode == NULL) {
-					g_printerr("GntStyle: Invalid key-binding %s\n", key);
+					gnt_warning("Invalid key-binding %s", key);
 				} else {
 					gnt_bindable_register_binding(klass, action, keycode, NULL);
 				}
@@ -280,7 +284,7 @@
 		keys = g_key_file_get_keys(gkfile, kname, &len, &error);
 		if (error)
 		{
-			g_printerr("GntStyle: %s\n", error->message);
+			gnt_warning("%s", error->message);
 			g_error_free(error);
 			g_free(kname);
 			return ret;
@@ -295,7 +299,7 @@
 
 			if (error)
 			{
-				g_printerr("GntStyle: %s\n", error->message);
+				gnt_warning("%s", error->message);
 				g_error_free(error);
 				error = NULL;
 			}
@@ -303,7 +307,7 @@
 			{
 				const char *keycode = parse_key(key);
 				if (keycode == NULL) {
-					g_printerr("GntStyle: Invalid key-binding %s\n", key);
+					gnt_warning("Invalid key-binding %s", key);
 				} else {
 					ret = TRUE;
 					g_hash_table_replace(table, g_strdup(keycode), menuid);
@@ -338,7 +342,7 @@
 		keys = g_key_file_get_keys(gkfile, name, &len, &error);
 		if (error)
 		{
-			g_printerr("GntStyle: %s\n", error->message);
+			gnt_warning("%s", error->message);
 			g_error_free(error);
 			g_free(name);
 			return;
@@ -353,7 +357,7 @@
 
 			if (error)
 			{
-				g_printerr("GntStyle: %s\n", error->message);
+				gnt_warning("%s", error->message);
 				g_error_free(error);
 				error = NULL;
 				g_free(key);
@@ -402,7 +406,7 @@
 
 	if (error)
 	{
-		g_printerr("GntStyle: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 	}
 	else
@@ -426,7 +430,7 @@
 	if (!g_key_file_load_from_file(gkfile, filename,
                 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error))
 	{
-		g_printerr("GntStyle: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		return;
 	}
--- a/finch/libgnt/gnttextview.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gnttextview.c	Mon Dec 01 23:36:00 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "TextView"
+
 #include "gntstyle.h"
 #include "gnttextview.h"
 #include "gntutils.h"
@@ -67,6 +71,7 @@
 gnt_text_view_draw(GntWidget *widget)
 {
 	GntTextView *view = GNT_TEXT_VIEW(widget);
+	int n;
 	int i = 0;
 	GList *lines;
 	int rows, scrcol;
@@ -76,10 +81,11 @@
 	wbkgd(widget->window, gnt_color_pair(GNT_COLOR_NORMAL));
 	werase(widget->window);
 
+	n = g_list_length(view->list);
 	if ((view->flags & GNT_TEXT_VIEW_TOP_ALIGN) &&
-			g_list_length(view->list) < widget->priv.height) {
+			n < widget->priv.height) {
 		GList *now = view->list;
-		comp = widget->priv.height - g_list_length(view->list);
+		comp = widget->priv.height - n;
 		view->list = g_list_nth_prev(view->list, comp);
 		if (!view->list) {
 			view->list = g_list_first(now);
@@ -236,6 +242,7 @@
 static char *
 gnt_text_view_get_p(GntTextView *view, int x, int y)
 {
+	int n;
 	int i = 0;
 	GntWidget *wid = GNT_WIDGET(view);
 	GntTextLine *line;
@@ -244,10 +251,11 @@
 	GntTextSegment *seg;
 	gchar *pos;
 
+	n = g_list_length(view->list);
 	y = wid->priv.height - y;
-	if (g_list_length(view->list) < y) {
+	if (n < y) {
 		x = 0;
-		y = g_list_length(view->list) - 1;
+		y = n - 1;
 	}
 
 	lines = g_list_nth(view->list, y - 1);
@@ -776,7 +784,7 @@
 						/* XXX: Make things work if the tagged text spans over several lines. */
 					} else {
 						/* XXX: handle the rest of the conditions */
-						g_printerr("WTF! This needs to be handled properly!!\n");
+						gnt_warning("WTF! This needs to be handled properly!!%s", "");
 					}
 				}
 			}
--- a/finch/libgnt/gntutils.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntutils.c	Mon Dec 01 23:36:00 2008 +0000
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "Utils"
+
 #include "gntbutton.h"
 #include "gntcheckbox.h"
 #include "gntcombobox.h"
@@ -306,7 +310,7 @@
 	xmlFree(content);
 
 	if (widget == NULL) {
-		g_printerr("Invalid widget name %s\n", name);
+		gnt_warning("Invalid widget name %s", name);
 		return NULL;
 	}
 
--- a/finch/libgnt/gntwm.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/finch/libgnt/gntwm.c	Mon Dec 01 23:36:00 2008 +0000
@@ -46,6 +46,10 @@
 #include <string.h>
 #include <time.h>
 
+#include "gntinternal.h"
+#undef GNT_LOG_DOMAIN
+#define GNT_LOG_DOMAIN "WM"
+
 #include "gntwm.h"
 #include "gntstyle.h"
 #include "gntmarshal.h"
@@ -201,7 +205,7 @@
 	GString *text = g_string_new("act: ");
 	if (message)
 		gnt_widget_destroy(message);
-	if (g_list_length(act) == 0)
+	if (!act)
 		return;
 	for (iter = act; iter; iter = iter->next) {
 		GntWS *ws = iter->data;
@@ -325,7 +329,7 @@
 	gsize nk;
 
 	if (!g_key_file_load_from_file(gfile, filename, G_KEY_FILE_NONE, &error)) {
-		g_printerr("GntWM: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		g_free(filename);
 		return;
@@ -333,7 +337,7 @@
 
 	keys = g_key_file_get_keys(gfile, "positions", &nk, &error);
 	if (error) {
-		g_printerr("GntWM: %s\n", error->message);
+		gnt_warning("%s", error->message);
 		g_error_free(error);
 		error = NULL;
 	} else {
@@ -349,7 +353,7 @@
 				p->y = y;
 				g_hash_table_replace(wm->positions, g_strdup(title + 1), p);
 			} else {
-				g_printerr("GntWM: Invalid number of arguments for positioing a window.\n");
+				gnt_warning("Invalid number of arguments (%d) for positioning a window.", l);
 			}
 			g_strfreev(coords);
 		}
@@ -927,6 +931,7 @@
 	GntWidget *tree, *win;
 	GList *iter;
 	GntWM *wm = GNT_WM(bindable);
+	int n;
 	if (wm->_list.window || wm->menu)
 		return TRUE;
 
@@ -950,8 +955,9 @@
 				gnt_tree_create_row(GNT_TREE(tree), action->label), NULL);
 	}
 	g_signal_connect(G_OBJECT(tree), "activate", G_CALLBACK(action_list_activate), wm);
-	gnt_widget_set_size(tree, 0, g_list_length(wm->acts));
-	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - g_list_length(wm->acts));
+	n = g_list_length(wm->acts);
+	gnt_widget_set_size(tree, 0, n);
+	gnt_widget_set_position(win, 0, getmaxy(stdscr) - 3 - n);
 
 	gnt_widget_show(win);
 	return TRUE;
@@ -2093,7 +2099,7 @@
 
 	file = fopen(filename, "wb");
 	if (file == NULL) {
-		g_printerr("GntWM: error opening file to save positions\n");
+		gnt_warning("error opening file (%s) to save positions", filename);
 	} else {
 		fprintf(file, "[positions]\n");
 		g_hash_table_foreach(wm->positions, write_gdi, file);
--- a/libpurple/protocols/gg/buddylist.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/gg/buddylist.c	Mon Dec 01 23:36:00 2008 +0000
@@ -96,9 +96,10 @@
 	PurpleGroup *group;
 	gchar **users_tbl;
 	int i;
+	char *utf8buddylist = charset_convert(buddylist, "CP1250", "UTF-8");
 
 	/* Don't limit the number of records in a buddylist. */
-	users_tbl = g_strsplit(buddylist, "\r\n", -1);
+	users_tbl = g_strsplit(utf8buddylist, "\r\n", -1);
 
 	for (i = 0; users_tbl[i] != NULL; i++) {
 		gchar **data_tbl;
@@ -115,23 +116,22 @@
 			continue;
 		}
 
-		show = charset_convert(data_tbl[F_NICKNAME], "CP1250", "UTF-8");
+		show = data_tbl[F_NICKNAME];
 		name = data_tbl[F_UIN];
-		if ('\0' == *name) {
+		if ('\0' == *name || !atol(name)) {
 			purple_debug_warning("gg",
-				"Something is wrong on line %d of the buddylist. Skipping.\n",
+				"Identifier on line %d of the buddylist is not a number. Skipping.\n",
 				i + 1);
 			continue;
 		}
 
 		if ('\0' == *show) {
-			show = g_strdup(name);
+			show = name;
 		}
 
 		purple_debug_info("gg", "got buddy: name=%s; show=%s\n", name, show);
 
 		if (purple_find_buddy(purple_connection_get_account(gc), name)) {
-			g_free(show);
 			g_strfreev(data_tbl);
 			continue;
 		}
@@ -144,7 +144,7 @@
 			gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
 			if (ggp_array_size(group_tbl) > 0) {
 				g_free(g);
-				g = charset_convert(group_tbl[0], "CP1250", "UTF-8");
+				g = g_strdup(group_tbl[0]);
 			}
 			g_strfreev(group_tbl);
 		}
@@ -160,10 +160,10 @@
 		purple_blist_add_buddy(buddy, NULL, group, NULL);
 		g_free(g);
 
-		g_free(show);
 		g_strfreev(data_tbl);
 	}
 	g_strfreev(users_tbl);
+	g_free(utf8buddylist);
 
 	ggp_buddylist_send(gc);
 }
@@ -234,8 +234,7 @@
 				continue;
 
 			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) {
-				gchar *newdata, *name, *alias, *gname;
-				gchar *cp_alias, *cp_gname;
+				gchar *name, *alias, *gname;
 
 				if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
 					continue;
@@ -248,25 +247,20 @@
 				alias = buddy->alias ? buddy->alias : buddy->name;
 				gname = group->name;
 
-				cp_gname = charset_convert(gname, "UTF-8", "CP1250");
-				cp_alias = charset_convert(alias, "UTF-8", "CP1250");
-				newdata = g_strdup_printf(
-						"%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
-						cp_alias, cp_alias, cp_alias, cp_alias,
-						"", cp_gname, name, "", "");
+				ptr = buddylist;
+				buddylist = g_strdup_printf(
+						"%s%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
+						ptr, alias, alias, alias, alias,
+						"", gname, name, "", "");
 
-				ptr = buddylist;
-				buddylist = g_strconcat(ptr, newdata, NULL);
-
-				g_free(newdata);
 				g_free(ptr);
-				g_free(cp_gname);
-				g_free(cp_alias);
 			}
 		}
 	}
 
-	return buddylist;
+	ptr = charset_convert(buddylist, "UTF-8", "CP1250");
+	g_free(buddylist);
+	return ptr;
 }
 /* }}} */
 
--- a/libpurple/protocols/jabber/auth.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/auth.c	Mon Dec 01 23:36:00 2008 +0000
@@ -397,6 +397,10 @@
 		auth = xmlnode_new("auth");
 		xmlnode_set_namespace(auth, "urn:ietf:params:xml:ns:xmpp-sasl");
 		xmlnode_set_attrib(auth, "mechanism", js->current_mech);
+		
+		xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
+		xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
+
 		if (clientout) {
 			if (coutlen == 0) {
 				xmlnode_insert_data(auth, "=", -1);
--- a/libpurple/protocols/jabber/buddy.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Mon Dec 01 23:36:00 2008 +0000
@@ -115,14 +115,18 @@
 						break;
 					case JABBER_BUDDY_STATE_AWAY:
 					case JABBER_BUDDY_STATE_DND:
-					case JABBER_BUDDY_STATE_UNAVAILABLE:
-						/* This resource is away/dnd/unavailable. Prefer to one which is extended away or unknown. */
-						if ((jbr->state == JABBER_BUDDY_STATE_XA) || 
+						/* This resource is away/dnd. Prefer to one which is extended away, unavailable, or unknown. */
+						if ((jbr->state == JABBER_BUDDY_STATE_XA) || (jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) ||
 							(jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
 							jbr = l->data;
 						break;
 					case JABBER_BUDDY_STATE_XA:
-						/* This resource is extended away. That's better than unknown. */
+						/* This resource is extended away. That's better than unavailable or unknown. */
+						if ((jbr->state == JABBER_BUDDY_STATE_UNAVAILABLE) || (jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
+							jbr = l->data;
+						break;
+					case JABBER_BUDDY_STATE_UNAVAILABLE:
+						/* This resource is unavailable. That's better than unknown. */
 						if ((jbr->state == JABBER_BUDDY_STATE_UNKNOWN) || (jbr->state == JABBER_BUDDY_STATE_ERROR))
 							jbr = l->data;
 						break;
@@ -966,7 +970,7 @@
 		}
 #endif
 	} else {
-		gboolean multiple_resources = jbi->jb->resources && (g_list_length(jbi->jb->resources) > 1);
+		gboolean multiple_resources = jbi->jb->resources && jbi->jb->resources->next;
 
 		for(resources = jbi->jb->resources; resources; resources = resources->next) {
 			char *purdy = NULL;
@@ -1798,12 +1802,21 @@
 void jabber_buddy_get_info(PurpleConnection *gc, const char *who)
 {
 	JabberStream *js = gc->proto_data;
-	char *bare_jid = jabber_get_bare_jid(who);
+	JabberID *jid = jabber_id_new(who);
+
+	if (!jid)
+		return;
 
-	if(bare_jid) {
+	if (jabber_chat_find(js, jid->node, jid->domain)) {
+		/* For a conversation, include the resource (indicates the user). */
+		jabber_buddy_get_info_for_jid(js, who);
+	} else {
+		char *bare_jid = jabber_get_bare_jid(who);
 		jabber_buddy_get_info_for_jid(js, bare_jid);
 		g_free(bare_jid);
 	}
+
+	jabber_id_free(jid);
 }
 
 static void jabber_buddy_set_invisibility(JabberStream *js, const char *who,
--- a/libpurple/protocols/jabber/jabber.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Dec 01 23:36:00 2008 +0000
@@ -146,10 +146,37 @@
 	jabber_session_init(js);
 }
 
+static char *jabber_prep_resource(char *input) {
+	char hostname[256]; /* current hostname */
+
+	/* Empty resource == don't send any */
+	if (*input == '\0')
+		return NULL;
+
+	if (strstr(input, "__HOSTNAME__") == NULL)
+		return input;
+
+	/* Replace __HOSTNAME__ with hostname */
+	if (gethostname(hostname, sizeof(hostname) - 1)) {
+		purple_debug_warning("jabber", "gethostname: %s\n", g_strerror(errno));
+		/* according to glibc doc, the only time an error is returned
+		   is if the hostname is longer than the buffer, in which case
+		   glibc 2.2+ would still fill the buffer with partial
+		   hostname, so maybe we want to detect that and use it
+		   instead
+		*/
+		strcpy(hostname, "localhost");
+	}
+	hostname[sizeof(hostname) - 1] = '\0';
+
+	return purple_strreplace(input, "__HOSTNAME__", hostname);
+}
+
 static void jabber_stream_features_parse(JabberStream *js, xmlnode *packet)
 {
 	if(xmlnode_get_child(packet, "starttls")) {
 		if(jabber_process_starttls(js, packet))
+	
 			return;
 	} else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) {
 		purple_connection_error_reason (js->gc,
@@ -164,11 +191,17 @@
 		jabber_auth_start(js, packet);
 	} else if(xmlnode_get_child(packet, "bind")) {
 		xmlnode *bind, *resource;
+		char *requested_resource;
 		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
 		bind = xmlnode_new_child(iq->node, "bind");
 		xmlnode_set_namespace(bind, "urn:ietf:params:xml:ns:xmpp-bind");
-		resource = xmlnode_new_child(bind, "resource");
-		xmlnode_insert_data(resource, js->user->resource, -1);
+		requested_resource = jabber_prep_resource(js->user->resource);
+
+		if (requested_resource != NULL) {
+			resource = xmlnode_new_child(bind, "resource");
+			xmlnode_insert_data(resource, requested_resource, -1);
+			free(requested_resource);
+		}
 
 		jabber_iq_set_callback(iq, jabber_bind_result_cb, NULL);
 
@@ -679,19 +712,6 @@
 		return;
 	}
 	
-	if(!js->user->resource) {
-		char *me;
-		js->user->resource = g_strdup("Home");
-		if(!js->user->node) {
-			js->user->node = js->user->domain;
-			js->user->domain = g_strdup("jabber.org");
-		}
-		me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain,
-				js->user->resource);
-		purple_account_set_username(account, me);
-		g_free(me);
-	}
-
 	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
 		my_jb->subscription |= JABBER_SUB_BOTH;
 
@@ -1159,19 +1179,6 @@
 
 	js->write_buffer = purple_circ_buffer_new(512);
 
-	if(!js->user->resource) {
-		char *me;
-		js->user->resource = g_strdup("Home");
-		if(!js->user->node) {
-			js->user->node = js->user->domain;
-			js->user->domain = g_strdup("jabber.org");
-		}
-		me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain,
-				js->user->resource);
-		purple_account_set_username(account, me);
-		g_free(me);
-	}
-
 	if((my_jb = jabber_buddy_find(js, purple_account_get_username(account), TRUE)))
 		my_jb->subscription |= JABBER_SUB_BOTH;
 
--- a/libpurple/protocols/jabber/libxmpp.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Dec 01 23:36:00 2008 +0000
@@ -209,7 +209,7 @@
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 	
-	split = purple_account_user_split_new(_("Resource"), "Home", '/');
+	split = purple_account_user_split_new(_("Resource"), NULL, '/');
 	purple_account_user_split_set_reverse(split, FALSE);
 	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 	
--- a/libpurple/protocols/jabber/pep.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/pep.c	Mon Dec 01 23:36:00 2008 +0000
@@ -54,7 +54,7 @@
 
 static void do_pep_iq_request_item_callback(JabberStream *js, xmlnode *packet, gpointer data) {
 	const char *from = xmlnode_get_attrib(packet,"from");
-	xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub#event");
+	xmlnode *pubsub = xmlnode_get_child_with_namespace(packet,"pubsub","http://jabber.org/protocol/pubsub");
 	xmlnode *items = NULL;
 	JabberPEPHandler *cb = data;
 	
--- a/libpurple/protocols/jabber/presence.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/presence.c	Mon Dec 01 23:36:00 2008 +0000
@@ -513,7 +513,7 @@
 		} else if(!strcmp(y->name, "delay") && !strcmp(xmlns, "urn:xmpp:delay")) {
 			/* XXX: compare the time.  jabber:x:delay can happen on presence packets that aren't really and truly delayed */
 			delayed = TRUE;
-		} else if(!strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) {
+		} else if(xmlns && !strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) {
 			caps = y; /* store for later, when creating buddy resource */
 		} else if(!strcmp(y->name, "x")) {
 			const char *xmlns = xmlnode_get_namespace(y);
--- a/libpurple/protocols/jabber/si.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/jabber/si.c	Mon Dec 01 23:36:00 2008 +0000
@@ -1085,7 +1085,7 @@
 
 			purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg);
 			g_free(msg);
-		} else if(g_list_length(jb->resources) == 1) {
+		} else if(!jb->resources->next) {
 			/* only 1 resource online (probably our most common case)
 			 * so no need to ask who to send to */
 			jbr = jb->resources->data;
--- a/libpurple/protocols/myspace/README	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/myspace/README	Mon Dec 01 23:36:00 2008 +0000
@@ -10,9 +10,6 @@
 
 For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM
 
-Windows installation: Unzip the archive to C:\Program Files\Pidgin
-Unix/source installation: run "make install"
-
 Usage:
 
 Login using your _email address_ you use to login to myspace.com. You can't
--- a/libpurple/protocols/myspace/message.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/myspace/message.c	Mon Dec 01 23:36:00 2008 +0000
@@ -613,6 +613,7 @@
 		const gchar *sep, 
 		const gchar *begin, const gchar *end)
 {
+	int num_items;
 	gchar **strings;
 	gchar **strings_tmp;
 	gchar *joined;
@@ -621,8 +622,10 @@
 
 	g_return_val_if_fail(msg != NULL, NULL);
 
+	num_items = g_list_length(msg);
+
 	/* Add one for NULL terminator for g_strjoinv(). */
-	strings = (gchar **)g_new0(gchar *, g_list_length(msg) + 1);
+	strings = (gchar **)g_new0(gchar *, num_items + 1);
 
 	strings_tmp = strings;
 	g_list_foreach(msg, gf, &strings_tmp);
@@ -632,7 +635,7 @@
 	g_free(joined);
 
 	/* Clean up. */
-	for (i = 0; i < g_list_length(msg); ++i) {
+	for (i = 0; i < num_items; ++i) {
 		g_free(strings[i]);
 	}
 
--- a/libpurple/protocols/qq/qq_network.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.c	Mon Dec 01 23:36:00 2008 +0000
@@ -126,8 +126,8 @@
 	/* get new server */
 	index  = rand() % count;
 	it = g_list_nth(qd->servers, index);
-    qd->curr_server = it->data;		/* do not free server_name */
-    if (qd->curr_server == NULL || strlen(qd->curr_server) <= 0 ) {
+	qd->curr_server = it->data;		/* do not free server_name */
+	if (qd->curr_server == NULL || strlen(qd->curr_server) <= 0 ) {
 		purple_debug_info("QQ", "Server name at %d is empty\n", index);
 		return FALSE;
 	}
--- a/libpurple/protocols/sametime/sametime.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Mon Dec 01 23:36:00 2008 +0000
@@ -4415,7 +4415,7 @@
     res = results->data;
 
   if(!code && res && res->matches) {
-    if(g_list_length(res->matches) == 1) {
+    if(!res->matches->next) {
       struct mwResolveMatch *match = res->matches->data;
       
       /* only one? that might be the right one! */
--- a/libpurple/protocols/yahoo/yahoochat.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Mon Dec 01 23:36:00 2008 +0000
@@ -513,12 +513,12 @@
 
 	c = purple_find_chat(gc, YAHOO_CHAT_ID);
 
-	if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) && members &&
-	   ((g_list_length(members) > 1) ||
+	if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) &&
+	    members && (members->next ||
 	     !g_ascii_strcasecmp(members->data, purple_connection_get_display_name(gc)))) {
-		int i;
+		GList *l;
 		GList *flags = NULL;
-		for (i = 0; i < g_list_length(members); i++)
+		for (l = members; l; l = l->next)
 			flags = g_list_append(flags, GINT_TO_POINTER(PURPLE_CBFLAGS_NONE));
 		if (c && purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) {
 			/* this might be a hack, but oh well, it should nicely */
--- a/libpurple/purple-remote	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/purple-remote	Mon Dec 01 23:36:00 2008 +0000
@@ -172,6 +172,10 @@
         status_id = purple.PurplePrimitiveGetIdFromType(status_type)
         return status_id
 
+    elif command == "getstatusmessage":
+        current = purple.PurpleSavedstatusGetCurrent()
+        return purple.PurpleSavedstatusGetMessage(current)
+
     elif command == "getinfo":
         account = findaccount(accountname, protocol)
         connection = cpurple.PurpleAccountGetConnection(account)
--- a/libpurple/request.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/request.c	Mon Dec 01 23:36:00 2008 +0000
@@ -916,7 +916,7 @@
 	purple_request_field_list_clear_selected(field);
 
 	if (!purple_request_field_list_get_multi_select(field) &&
-		g_list_length(items) > 1)
+		items && items->next)
 	{
 		purple_debug_warning("request",
 						   "More than one item added to non-multi-select "
--- a/libpurple/roomlist.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/libpurple/roomlist.c	Mon Dec 01 23:36:00 2008 +0000
@@ -265,6 +265,11 @@
 	g_return_if_fail(room != NULL);
 	g_return_if_fail(list->fields != NULL);
 
+	/* If this is the first call for this room, grab the first field in
+	 * the Roomlist's fields.  Otherwise, grab the field that is one
+	 * more than the number of fields already present for the room.
+         * (This works because g_list_nth_data() is zero-indexed and
+         * g_list_length() is one-indexed.) */
 	if (!room->fields)
 		f = list->fields->data;
 	else
--- a/pidgin/Makefile.am	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/Makefile.am	Mon Dec 01 23:36:00 2008 +0000
@@ -5,7 +5,6 @@
 		Makefile.mingw \
 		pidgin.pc.in \
 		pidgin-uninstalled.pc.in \
-		pidginstock-artwork.c \
 		win32/IdleTracker/Makefile.mingw \
 		win32/IdleTracker/idletrack.c \
 		win32/IdleTracker/idletrack.h \
--- a/pidgin/gtkblist.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/gtkblist.c	Mon Dec 01 23:36:00 2008 +0000
@@ -3320,6 +3320,7 @@
 	if (PURPLE_BLIST_NODE_IS_CHAT(node))
 	{
 		PurpleChat *chat;
+		GList *connections;
 		GList *cur;
 		struct proto_chat_entry *pce;
 		char *name, *value;
@@ -3330,7 +3331,8 @@
 		prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-		if (g_list_length(purple_connections_get_all()) > 1)
+		connections = purple_connections_get_all();
+		if (connections && connections->next)
 		{
 			tmp = g_markup_escape_text(chat->account->username, -1);
 			g_string_append_printf(str, _("<b>Account:</b> %s"), tmp);
@@ -3400,6 +3402,7 @@
 		PurpleBuddy *b;
 		PurplePresence *presence;
 		PurpleNotifyUserInfo *user_info;
+		GList *connections;
 		char *tmp;
 		time_t idle_secs, signon;
 
@@ -3421,7 +3424,8 @@
 		user_info = purple_notify_user_info_new();
 
 		/* Account */
-		if (full && g_list_length(purple_connections_get_all()) > 1)
+		connections = purple_connections_get_all();
+		if (full && connections && connections->next)
 		{
 			tmp = g_markup_escape_text(purple_account_get_username(
 									   purple_buddy_get_account(b)), -1);
--- a/pidgin/gtkconv.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/gtkconv.c	Mon Dec 01 23:36:00 2008 +0000
@@ -2759,26 +2759,16 @@
 {
 	PidginConversation *gtkconv = (PidginConversation *)user_data;
 	PurpleConversation *conv = gtkconv->active_conv;
-	FILE *fp;
 	PurpleBuddyIcon *icon;
 	const void *data;
 	size_t len;
 
-	if ((fp = g_fopen(filename, "wb")) == NULL) {
-		purple_notify_error(gtkconv, NULL, _("Unable to open file."), NULL);
-		return;
-	}
-
 	icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv));
 	data = purple_buddy_icon_get_data(icon, &len);
 
-	if ((len <= 0) || (data == NULL) || (fwrite(data, 1, len, fp) != len)) {
+	if ((len <= 0) || (data == NULL) || !purple_util_write_data_to_file_absolute(filename, data, len)) {
 		purple_notify_error(gtkconv, NULL, _("Unable to save icon file to disk."), NULL);
-		fclose(fp);
-		g_unlink(filename);
-		return;
-	}
-	fclose(fp);
+	}
 }
 
 static void
--- a/pidgin/gtknotify.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/gtknotify.c	Mon Dec 01 23:36:00 2008 +0000
@@ -730,7 +730,6 @@
 	GtkListStore *model = data->model;
 	GtkTreeIter iter;
 	GdkPixbuf *pixbuf;
-	guint col_num;
 	GList *row, *column;
 	guint n;
 
@@ -738,9 +737,6 @@
 
 	pixbuf = pidgin_create_prpl_icon(purple_connection_get_account(gc), 0.5);
 
-	/* +1 is for the automagically created Status column. */
-	col_num = g_list_length(results->columns) + 1;
-
 	for (row = results->rows; row != NULL; row = row->next) {
 
 		gtk_list_store_append(model, &iter);
@@ -776,6 +772,7 @@
 	guint col_num;
 	GList *columniter;
 	guint i;
+	GList *l;
 
 	GtkWidget *vbox;
 	GtkWidget *label;
@@ -869,8 +866,8 @@
 		i++;
 	}
 
-	for (i = 0; i < g_list_length(results->buttons); i++) {
-		PurpleNotifySearchButton *b = g_list_nth_data(results->buttons, i);
+	for (l = results->buttons; l; l = l->next) {
+		PurpleNotifySearchButton *b = l->data;
 		GtkWidget *button = NULL;
 		switch (b->type) {
 			case PURPLE_NOTIFY_BUTTON_LABELED:
--- a/pidgin/gtkrequest.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/gtkrequest.c	Mon Dec 01 23:36:00 2008 +0000
@@ -853,12 +853,11 @@
 create_choice_field(PurpleRequestField *field)
 {
 	GtkWidget *widget;
-	GList *labels;
+	GList *labels = purple_request_field_choice_get_labels(field);
+	int num_labels = g_list_length(labels);
 	GList *l;
 
-	labels = purple_request_field_choice_get_labels(field);
-
-	if (g_list_length(labels) > 5)
+	if (num_labels > 5)
 	{
 		GtkWidget *menu;
 		GtkWidget *item;
@@ -892,7 +891,7 @@
 		GtkWidget *radio;
 		gint i;
 
-		if (g_list_length(labels) == 2)
+		if (num_labels == 2)
 			box = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 		else
 			box = gtk_vbox_new(FALSE, 0);
--- a/pidgin/gtksavedstatuses.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/gtksavedstatuses.c	Mon Dec 01 23:36:00 2008 +0000
@@ -331,7 +331,8 @@
 	}
 	g_list_free(sel_paths);
 
-	if (g_list_length(sel_titles) == 1) {
+	g_return_if_fail(sel_titles != NULL);
+	if (!sel_titles->next) {
 		title = g_strdup_printf(_("Are you sure you want to delete %s?"),
 				(const gchar *)sel_titles->data);
 		handle = purple_savedstatus_find(sel_titles->data);
--- a/pidgin/pidginstock.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/pidginstock.c	Mon Dec 01 23:36:00 2008 +0000
@@ -175,7 +175,6 @@
 	{ PIDGIN_STOCK_ANIMATION_TYPING4,  "animations", "typing4.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_ANIMATION_TYPING5,  "animations", "typing5.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 
-	{ PIDGIN_STOCK_TOOLBAR_ACCOUNTS, "toolbar", "accounts.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_BGCOLOR, "toolbar", "change-bgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_BLOCK, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_FGCOLOR, "toolbar", "change-fgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
@@ -189,7 +188,6 @@
 	{ PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_PENDING, "tray", "tray-new-im.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_PLUGINS, "toolbar", "plugins.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TOOLBAR_TYPING, "toolbar", "typing.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_UNBLOCK, "toolbar", "unblock.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, "toolbar", "select-avatar.png", FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_SEND_FILE, "toolbar", "send-file.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
--- a/pidgin/pixmaps/Makefile.am	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/pixmaps/Makefile.am	Mon Dec 01 23:36:00 2008 +0000
@@ -344,6 +344,8 @@
 
 STATUS_11_RTL = \
 		status/11/rtl/extended-away.png
+		status/11/rtl/log-in.png
+		status/11/rtl/log-out.png
 
 STATUS_16 = \
 		status/16/available.png \
@@ -402,6 +404,7 @@
 		status/48/busy.png \
 		status/48/chat.png \
 		status/48/extended-away.png \
+		status/48/invisible.png \
 		status/48/log-in.png \
 		status/48/log-out.png \
 		status/48/offline.png \
@@ -409,8 +412,8 @@
 
 STATUS_48_RTL = \
 		status/48/rtl/extended-away.png \
-		status/48/rtl/login.png \
-		status/48/rtl/logout.png
+		status/48/rtl/log-in.png \
+		status/48/rtl/log-out.png
 
 TOOLBAR_11 = \
 		toolbar/11/message-new.png
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in	Mon Dec 01 23:36:00 2008 +0000
@@ -10,7 +10,7 @@
 excited.png         :-D     :-d     :D      :d
 sad.png             :-(     :(
 wink.png            ;-)     ;)
-tongue.png          :P      :-P     :-p     :p
+tongue.png          :P      :p      :-P     :-p
 shocked.png         =-O     =-o
 kiss.png            :-*
 glasses-cool.png    8-)
@@ -23,20 +23,21 @@
 foot-in-mouth.png   :-!
 shout.png           >:o     >:O
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)     8-|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 
 [XMPP]
-# Following XEP-0038 + our default set, in default set order
-happy.png           :)      :-)
-excited.png         :-D     :-d     :D      :d
+# Following XEP-0038 + GTalk + our default set, in default set order
+# The GTalk strings come from ticket #3307.
+happy.png           :)      :-)     =)
+excited.png         :-D     :-d     :D      :d      =D      =d
 sad.png             :-(     :(
-wink.png            ;-)     ;)
-tongue.png          :P      :-P     :-p     :p
-shocked.png         =-O     =-o
+wink.png            ;-)     ;)      ;^)
+tongue.png          :P      :p      :-P     :-p
+shocked.png         =-O     =-o     :-O     :-o
 kiss.png            :kiss:  :-*
-glasses-cool.png    8-)
+glasses-cool.png    8-)     B-)
 embarrassed.png     :-[
 crying.png          :'-(    :'(
 thinking.png        :-/     :-\\
@@ -46,8 +47,8 @@
 foot-in-mouth.png   :-!
 shout.png           >:o     >:O
 
-# Following XEP-0038
-angry.png           >:-(    >:(
+# Following XEP-0038 + GTalk
+angry.png           >:-(    >:(     X-(    x-(
 good.png            :yes:
 bad.png             :no:
 stop.png            :wait:
@@ -56,7 +57,7 @@
 mail.png            :email:
 lamp.png            :jabber:
 cake.png            :cake:
-in_love.png         :heart: :love:
+in_love.png         :heart: :love:  <3
 love-over.png       :brokenheart:
 musical-note.png    :music:
 beer.png            :beer:
@@ -66,10 +67,14 @@
 sun.png             :sun:
 star.png            :star:
 
+# Others
+neutral.png         :|      :-|
+victory.png         \\m/
+
 # Hidden icons from the default set.
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)     8-|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 
 # Following AIM 6.1
@@ -77,7 +82,7 @@
 happy.png           :-)     :)
 wink.png            ;-)     ;)
 sad.png             :-(     :(
-tongue.png          :-P     :P      :-p    :p
+tongue.png          :P      :p      :-P     :-p
 shocked.png         =-O
 kiss.png            :-*
 shout.png           >:o
@@ -91,21 +96,21 @@
 shut-mouth.png      :-X
 glasses-cool.png    8-)
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 
 # Following Windows Live Messenger 8.1
 [MSN]
 happy.png           :)      :-)
-excited.png         :D      :d :-D :-d
+excited.png         :D      :d      :-D     :-d
 wink.png            ;)      ;-)
-shocked.png         :-O     :-o :O :o
-tongue.png          :P      :p :-P :-p
+shocked.png         :-O     :-o     :O      :o
+tongue.png          :-P     :P      :-p     :p
 glasses-cool.png    (H)     (h)
 angry.png           :@      :-@
 embarrassed.png     :$      :-$
-confused.png        :S      :s :-S :-s
+confused.png        :S      :s      :-S     :-s
 sad.png             :(      :-(
 crying.png          :'(
 neutral.png         :|      :-|
@@ -174,8 +179,8 @@
 sleepy.png          |-) 
 bunny.png           ('.')
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 # Hidden MSN emotes
 cigarette.png      	(ci)    (CI)
@@ -280,8 +285,8 @@
 girl.png            /<00>    /nv       /woman
 boy.png             /<11>    /nan      /man
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 
 # Following ICQ 6.0
@@ -317,8 +322,8 @@
 glasses-cool.png    8-)
 amorous.png         *IN\ LOVE*
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 
 # Following Yahoo! Messenger 8.1
@@ -378,8 +383,8 @@
 cowboy.png          <):)
 desire.png          8->
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
 # Hidden Yahoo emotes
 alien.png           =:)     >-)
@@ -432,7 +437,7 @@
 glasses-nerdy.png   Q)
 doh.png		    :G
 pirate.png	    P)
-shock.png	    :O
+shocked.png	    :O
 sidefrown.png	    :{
 sinister.png	    :B
 smirk.png	    :,
@@ -443,6 +448,6 @@
 sad.png		    :[
 kiss.png            :x
 ! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)  :(|)
-! cyclops.png       O-) o-)
+! monkey.png        :-(|)   :(|)    8-|)
+! cyclops.png       O-)     o-)
 
--- a/pidgin/pixmaps/emotes/small/16/small.theme.in	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/pixmaps/emotes/small/16/small.theme.in	Mon Dec 01 23:36:00 2008 +0000
@@ -10,7 +10,7 @@
 excited.png         :-D     :-d     :D      :d
 sad.png             :-(     :(
 wink.png            ;-)     ;)
-tongue.png          :P      :-P     :-p     :p
+tongue.png          :P      :p      :-P     :-p
 shocked.png         =-O     =-o
 kiss.png            :-*
 embarrassed.png     :-[
@@ -20,27 +20,31 @@
 
 
 [XMPP]
-# Following XEP-0038 + our default set, in default set order
-happy.png           :)      :-)
-excited.png         :-D     :-d     :D      :d
+# Following XEP-0038 + GTalk + our default set, in default set order
+# The GTalk strings come from ticket #3307.
+happy.png           :)      :-)     =)
+excited.png         :-D     :-d     :D      :d      =D      =d
 sad.png             :-(     :(
-wink.png            ;-)     ;)
-tongue.png          :P      :-P     :-p     :p
-shocked.png         =-O     =-o
+wink.png            ;-)     ;)      ;^)
+tongue.png          :P      :p      :-P     :-p
+shocked.png         =-O     =-o     :-O     :-o
 kiss.png            :kiss:  :-*
 embarrassed.png     :-[
 crying.png          :'-(    :'(
 thinking.png        :-/     :-\\
 angel.png           O:-)    o:-)
 
-# Following XEP-0038
-angry.png           >:-(    >:(
+# Following XEP-0038 + GTalk
+angry.png           >:-(    >:(     X-(    x-(
 phone.png           :telephone:
-in_love.png         :heart: :love:
+in_love.png         :heart: :love:  <3
 musical-note.png    :music:
 beer.png            :beer:
 coffee.png          :coffee:
 
+# Others
+neutral.png         :|      :-|
+
 # Hidden icons from the default set.
 
 
@@ -49,7 +53,7 @@
 happy.png           :-)     :)
 wink.png            ;-)     ;)
 sad.png             :-(     :(
-tongue.png          :-P     :P      :-p    :p
+tongue.png          :P      :p      :-P     :-p
 shocked.png         =-O
 kiss.png            :-*
 excited.png         :-D     :D
@@ -62,13 +66,13 @@
 # Following Windows Live Messenger 8.1
 [MSN]
 happy.png           :)      :-)
-excited.png         :D      :d :-D :-d
+excited.png         :D      :d      :-D     :-d
 wink.png            ;)      ;-)
-shocked.png         :-O     :-o :O :o
-tongue.png          :P      :p :-P :-p
+shocked.png         :-O     :-o     :O      :o
+tongue.png          :-P     :P      :-p     :p
 angry.png           :@      :-@
 embarrassed.png     :$      :-$
-confused.png        :S      :s :-S :-s
+confused.png        :S      :s      :-S     :-s
 sad.png             :(      :-(
 crying.png          :'(
 neutral.png         :|      :-|
@@ -134,6 +138,7 @@
 shocked.png         =-O
 wink.png            ;-)     ;)
 tongue.png          :-P     :P      :-p     :p
+music.png           [:-}
 sleeping.png        *TIRED*
 crying.png          :'(    :'-(
 sick.png            :-!
@@ -190,9 +195,8 @@
 excited.png  	    :D      :-D
 devil.png	    }:)
 confused.png	    :Z
-smile.png	    :)      :-)
 amorous.png	    :X
-shock.png	    :O
+shocked.png	    :O
 neutral.png	    :|
 tongue.png	    :P      :p
 wink.png	    ;-)     ;)
Binary file pidgin/pixmaps/status/11/rtl/log-in.png has changed
Binary file pidgin/pixmaps/status/11/rtl/log-out.png has changed
Binary file pidgin/pixmaps/status/48/invisible.png has changed
Binary file pidgin/pixmaps/status/48/log-in.png has changed
Binary file pidgin/pixmaps/status/48/log-out.png has changed
Binary file pidgin/pixmaps/status/48/rtl/log-in.png has changed
Binary file pidgin/pixmaps/status/48/rtl/log-out.png has changed
Binary file pidgin/pixmaps/status/48/rtl/login.png has changed
Binary file pidgin/pixmaps/status/48/rtl/logout.png has changed
--- a/pidgin/plugins/history.c	Wed Nov 26 22:44:08 2008 +0000
+++ b/pidgin/plugins/history.c	Mon Dec 01 23:36:00 2008 +0000
@@ -47,10 +47,11 @@
 
 	convtype = purple_conversation_get_type(c);
 	gtkconv = PIDGIN_CONVERSATION(c);
-	if (gtkconv == NULL)
-		return;
+	g_return_if_fail(gtkconv != NULL);
 
-	if (convtype == PURPLE_CONV_TYPE_IM && g_list_length(gtkconv->convs) < 2)
+	/* An IM which is the first active conversation. */
+	g_return_if_fail(gtkconv->convs != NULL);
+	if (convtype == PURPLE_CONV_TYPE_IM && !gtkconv->convs->next)
 	{
 		GSList *buddies;
 		GSList *cur;