changeset 29613:e3206d6da6c7

propagate from branch 'im.pidgin.pidgin' (head bc551a0f3f61b07c37e8677925b1aeae91e849be) to branch 'im.pidgin.pidgin.next.minor' (head 6d87b28fb7d202e9e5cf6700c99d9f140fdcd245)
author John Bailey <rekkanoryo@rekkanoryo.org>
date Sat, 31 Oct 2009 17:52:54 +0000
parents a78a44f0cdcd (current diff) 96f0f6af5da2 (diff)
children 583d842a25ff 62e4159afc84
files ChangeLog libpurple/account.c libpurple/protocols/jabber/JEPS libpurple/protocols/jabber/google.c libpurple/protocols/jabber/jabber.c libpurple/protocols/yahoo/libymsg.c pidgin/gtkblist.c pidgin/gtkcelllayout.c pidgin/gtkcelllayout.h pidgin/gtkcellrendererprogress.c pidgin/gtkcellrendererprogress.h pidgin/gtkcellview.c pidgin/gtkcellview.h pidgin/gtkcellviewmenuitem.c pidgin/gtkcellviewmenuitem.h pidgin/gtkconv.c pidgin/gtkexpander.c pidgin/gtkexpander.h pidgin/gtkimhtml.c pidgin/gtkpounce.c pidgin/gtkprefs.c pidgin/gtkstatusbox.c pidgin/pidgincombobox.c pidgin/pidgincombobox.h
diffstat 35 files changed, 654 insertions(+), 527 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Oct 31 17:49:11 2009 +0000
+++ b/ChangeLog	Sat Oct 31 17:52:54 2009 +0000
@@ -22,10 +22,14 @@
 	  to announce the list of loaded plugins (in both Finch and Pidgin).
 	* Fix building the GnuTLS plugin with older versions of GnuTLS.
 	* Fix DNS TXT query resolution.
+	* Always rejoin open chats after an account reconnects.
 
 	MSN:
 	* Don't forget display names for buddies.
 	* Fix a random crash that might occur when idle.
+	* Fix more FQY 240 connection errors.
+	* Fix a crash that could occur when adding a buddy.
+	* Fix an occasional crash when sending message to an offline user.
 
 	XMPP:
 	* Users connecting to Google Talk now have an "Initiate Chat" context menu
@@ -52,6 +56,8 @@
 	* The userlist in a multiuser chat can be styled via gtkrc by using the
 	  widget name "pidgin_conv_userlist". (Heiko Schmitt)
 	* Add a hold button to the media window.
+	* Tooltips for custom smileys should work now.
+	* Users with unread messages are again bolded in the Buddy List.
 
 version 2.6.3 (10/16/2009):
 	General:
--- a/autogen.sh	Sat Oct 31 17:49:11 2009 +0000
+++ b/autogen.sh	Sat Oct 31 17:52:54 2009 +0000
@@ -83,7 +83,7 @@
 
 	OUTPUT=`mktemp autogen-XXXXXX`
 
-	printf "%s" "running ${CMD} ${@}... "
+	printf "running %s %s... " ${CMD} "$*"
 	${CMD} ${@} >${OUTPUT} 2>&1
 
 	if [ $? != 0 ] ; then
@@ -99,9 +99,17 @@
 	fi
 }
 
+cleanup () {
+	rm -f autogen-??????
+	echo
+	exit 2
+}
+
 ###############################################################################
 # We really start here, yes, very sneaky!
 ###############################################################################
+trap cleanup 2
+
 FIGLET=`which figlet 2> /dev/null`
 if [ x"${FIGLET}" != x"" ] ; then
 	${FIGLET} -f small ${PACKAGE}
@@ -143,7 +151,7 @@
 run_or_die ${INTLTOOLIZE} ${INTLTOOLIZE_FLAGS:-"-c -f --automake"}
 # This call to sed is needed to work around an annoying bug in intltool 0.40.6
 # See http://developer.pidgin.im/ticket/9520 for details
-run_or_die ${SED} "s:'\^\$\$lang\$\$':\^\$\$lang\$\$:g" -i po/Makefile.in.in
+run_or_die ${SED} -i.bak -e "s:'\^\$\$lang\$\$':\^\$\$lang\$\$:g" po/Makefile.in.in
 run_or_die ${ACLOCAL} ${ACLOCAL_FLAGS:-"-I m4macros"}
 run_or_die ${AUTOHEADER} ${AUTOHEADER_FLAGS}
 run_or_die ${AUTOMAKE} ${AUTOMAKE_FLAGS:-"-a -c --gnu"}
--- a/finch/gntconn.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/finch/gntconn.c	Sat Oct 31 17:52:54 2009 +0000
@@ -107,7 +107,6 @@
 {
 	FinchAutoRecon *info;
 	PurpleAccount *account = purple_connection_get_account(gc);
-	GList *list;
 
 	if (!purple_connection_error_is_fatal(reason)) {
 		info = g_hash_table_lookup(hash, account);
@@ -144,21 +143,6 @@
 		g_free(secondary);
 		purple_account_set_enabled(account, FINCH_UI, FALSE);
 	}
-
-	/* If we have any open chats, we probably want to rejoin when we get back online. */
-	list = purple_get_chats();
-	while (list) {
-		PurpleConversation *conv = list->data;
-		list = list->next;
-		if (purple_conversation_get_account(conv) != account ||
-				purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))
-			continue;
-		purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE));
-		purple_conversation_write(conv, NULL, _("The account has disconnected and you are no "
-					"longer in this chat. You will be automatically rejoined in the chat when "
-					"the account reconnects."),
-				PURPLE_MESSAGE_SYSTEM, time(NULL));
-	}
 }
 
 static void
--- a/finch/gntconv.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/finch/gntconv.c	Sat Oct 31 17:52:54 2009 +0000
@@ -367,6 +367,28 @@
 	}
 }
 
+static void
+account_signing_off(PurpleConnection *gc)
+{
+	GList *list = purple_get_chats();
+	PurpleAccount *account = purple_connection_get_account(gc);
+
+	/* We are about to sign off. See which chats we are currently in, and mark
+	 * them for rejoin on reconnect. */
+	while (list) {
+		PurpleConversation *conv = list->data;
+		if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) &&
+				purple_conversation_get_account(conv) == account) {
+			purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE));
+			purple_conversation_write(conv, NULL, _("The account has disconnected and you are no "
+						"longer in this chat. You will be automatically rejoined in the chat when "
+						"the account reconnects."),
+					PURPLE_MESSAGE_SYSTEM, time(NULL));
+		}
+		list = list->next;
+	}
+}
+
 static gpointer
 finch_conv_get_handle(void)
 {
@@ -642,8 +664,25 @@
 create_conv_from_userlist(GntWidget *widget, FinchConv *fc)
 {
 	PurpleAccount *account = purple_conversation_get_account(fc->active_conv);
-	char *name = gnt_tree_get_selection_data(GNT_TREE(widget));
-	purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
+	PurpleConnection *gc = purple_account_get_connection(account);
+	PurplePluginProtocolInfo *prpl_info = NULL;
+	char *name, *realname;
+
+	if (!gc) {
+		purple_conversation_write(fc->active_conv, NULL, _("You are not connected."),
+				PURPLE_MESSAGE_SYSTEM, time(NULL));
+		return;
+	}
+
+	name = gnt_tree_get_selection_data(GNT_TREE(widget));
+
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_cb_real_name))
+		realname = prpl_info->get_cb_real_name(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(fc->active_conv)), name);
+	else
+		realname = NULL;
+	purple_conversation_new(PURPLE_CONV_TYPE_IM, account, realname ? realname : name);
+	g_free(realname);
 }
 
 static void
@@ -1433,6 +1472,8 @@
 					PURPLE_CALLBACK(account_signed_on_off), NULL);
 	purple_signal_connect(purple_connections_get_handle(), "signed-off", finch_conv_get_handle(),
 					PURPLE_CALLBACK(account_signed_on_off), NULL);
+	purple_signal_connect(purple_connections_get_handle(), "signing-off", finch_conv_get_handle(),
+					PURPLE_CALLBACK(account_signing_off), NULL);
 }
 
 void finch_conversation_uninit()
--- a/finch/libgnt/gntentry.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/finch/libgnt/gntentry.c	Sat Oct 31 17:52:54 2009 +0000
@@ -1044,8 +1044,11 @@
 		snprintf(entry->start, len + 1, "%s", text);
 	entry->end = entry->start + len;
 
-	entry->scroll = entry->start + scroll;
-	entry->cursor = entry->end - cursor;
+	if ((entry->scroll = entry->start + scroll) > entry->end)
+		entry->scroll = entry->end;
+
+	if ((entry->cursor = entry->end - cursor) > entry->end)
+		entry->cursor = entry->end;
 
 	if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(entry), GNT_WIDGET_MAPPED))
 		entry_redraw(GNT_WIDGET(entry));
--- a/finch/libgnt/gnttextview.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/finch/libgnt/gnttextview.c	Sat Oct 31 17:52:54 2009 +0000
@@ -67,6 +67,12 @@
 
 static void reset_text_view(GntTextView *view);
 
+static gboolean
+text_view_contains(GntTextView *view, const char *str)
+{
+	return (str >= view->string->str && str < view->string->str + view->string->len);
+}
+
 static void
 gnt_text_view_draw(GntWidget *widget)
 {
@@ -109,7 +115,7 @@
 			char back = *end;
 			chtype fl = seg->flags;
 			*end = '\0';
-			if (select_start < view->string->str + seg->start && select_end > view->string->str + seg->end) {
+			if (select_start && select_start < view->string->str + seg->start && select_end > view->string->str + seg->end) {
 				fl |= A_REVERSE;
 				wattrset(widget->window, fl);
 				wprintw(widget->window, "%s", (view->string->str + seg->start));
@@ -326,9 +332,10 @@
 		select_start = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y);
 		g_timeout_add(500, too_slow, NULL);
 	} else if (event == GNT_MOUSE_UP) {
-		if (select_start) {
+		GntTextView *view = GNT_TEXT_VIEW(widget);
+		if (text_view_contains(view, select_start)) {
 			GString *clip;
-			select_end = gnt_text_view_get_p(GNT_TEXT_VIEW(widget), x - widget->priv.x, y - widget->priv.y);
+			select_end = gnt_text_view_get_p(view, x - widget->priv.x, y - widget->priv.y);
 			if (select_end < select_start) {
 				gchar *t = select_start;
 				select_start = select_end;
@@ -336,7 +343,7 @@
 			}
 			if (select_start == select_end) {
 				if (double_click) {
-					clip = select_word_text(GNT_TEXT_VIEW(widget), select_start);
+					clip = select_word_text(view, select_start);
 					double_click = FALSE;
 				} else {
 					double_click = TRUE;
--- a/libpurple/Makefile.am	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/Makefile.am	Sat Oct 31 17:52:54 2009 +0000
@@ -32,7 +32,7 @@
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = purple.pc
 
-SUBDIRS = $(GCONF_DIR) plugins protocols tests . example
+SUBDIRS = $(GCONF_DIR) plugins protocols . tests example
 
 purple_coresources = \
 	account.c \
--- a/libpurple/account.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/account.c	Sat Oct 31 17:52:54 2009 +0000
@@ -1050,6 +1050,16 @@
 	if(account->system_log)
 		purple_log_free(account->system_log);
 
+	while (account->deny) {
+		g_free(account->deny->data);
+		account->deny = g_slist_delete_link(account->deny, account->deny);
+	}
+
+	while (account->permit) {
+		g_free(account->permit->data);
+		account->permit = g_slist_delete_link(account->permit, account->permit);
+	}
+
 	priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
 	PURPLE_DBUS_UNREGISTER_POINTER(priv->current_error);
 	if (priv->current_error) {
--- a/libpurple/cipher.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/cipher.c	Sat Oct 31 17:52:54 2009 +0000
@@ -50,10 +50,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
-#include <glib.h>
-#include <string.h>
-#include <stdio.h>
-
 #include "internal.h"
 #include "cipher.h"
 #include "dbus-maybe.h"
--- a/libpurple/plugins/perl/perl-handlers.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/plugins/perl/perl-handlers.c	Sat Oct 31 17:52:54 2009 +0000
@@ -649,6 +649,7 @@
 static void
 destroy_cmd_handler(PurplePerlCmdHandler *handler)
 {
+	purple_cmd_unregister(handler->id);
 	cmd_handlers = g_slist_remove(cmd_handlers, handler);
 
 	if (handler->callback != NULL)
@@ -705,7 +706,6 @@
 		return;
 	}
 
-	purple_cmd_unregister(id);
 	destroy_cmd_handler(handler);
 }
 
--- a/libpurple/protocols/jabber/JEPS	Sat Oct 31 17:49:11 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-0045: IN PROGRESS
-	Multi-User Chat
-0047: IN PROGRESS
-	In-Band Bytestreams
-0060: NEED
-	Pub-Sub
-0071: AWAITING FINAL SPEC
-	XHTML-IM
-0073: NEED
-	Basic IM Protocol Suite
-0080: NEED (Do we?)
-	Geographic Location Information
-0084: NEED
-	User Avatars in Jabber
-0085: NEED
-	Chat State Notifications
-0089: WATCH
-	Generic Alerts
-0093: NEED
-	Roster Item Exchange
-0100: NEED
-	Gateway Interaction (Transports)
-0115: WATCH
-	Client Capabilities
-0117: NEED
-	Intermediate IM Protocol Suite
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/jabber/XEPS	Sat Oct 31 17:52:54 2009 +0000
@@ -0,0 +1,4 @@
+0060: NEED
+	Pub-Sub
+0080: NEED (Do we?)
+	Geographic Location Information
--- a/libpurple/protocols/jabber/caps.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/jabber/caps.c	Sat Oct 31 17:52:54 2009 +0000
@@ -975,7 +975,7 @@
 	g_free(js->caps_hash);
 	js->caps_hash = jabber_caps_calculate_hash(&info, "sha1");
 	g_list_free(info.identities);
-	g_list_free(features);
+	g_list_free(info.features);
 }
 
 const gchar* jabber_caps_get_own_hash(JabberStream *js)
--- a/libpurple/protocols/jabber/chat.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/jabber/chat.c	Sat Oct 31 17:52:54 2009 +0000
@@ -692,11 +692,11 @@
 }
 
 
-void jabber_chat_change_nick(JabberChat *chat, const char *nick)
+gboolean jabber_chat_change_nick(JabberChat *chat, const char *nick)
 {
 	xmlnode *presence;
 	char *full_jid;
-	PurplePresence *gpresence;
+	PurpleAccount *account;
 	PurpleStatus *status;
 	JabberBuddyState state;
 	char *msg;
@@ -706,11 +706,11 @@
 		purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), "",
 				_("Nick changing not supported in non-MUC chatrooms"),
 				PURPLE_MESSAGE_SYSTEM, time(NULL));
-		return;
+		return FALSE;
 	}
 
-	gpresence = purple_account_get_presence(chat->js->gc->account);
-	status = purple_presence_get_active_status(gpresence);
+	account = purple_connection_get_account(chat->js->gc);
+	status = purple_account_get_active_status(account);
 
 	purple_status_to_jabber(status, &state, &msg, &priority);
 
@@ -722,6 +722,8 @@
 
 	jabber_send(chat->js, presence);
 	xmlnode_free(presence);
+
+	return TRUE;
 }
 
 void jabber_chat_part(JabberChat *chat, const char *msg)
--- a/libpurple/protocols/jabber/chat.h	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/jabber/chat.h	Sat Oct 31 17:52:54 2009 +0000
@@ -89,7 +89,7 @@
 void jabber_chat_register(JabberChat *chat);
 void jabber_chat_change_topic(JabberChat *chat, const char *topic);
 void jabber_chat_set_topic(PurpleConnection *gc, int id, const char *topic);
-void jabber_chat_change_nick(JabberChat *chat, const char *nick);
+gboolean jabber_chat_change_nick(JabberChat *chat, const char *nick);
 void jabber_chat_part(JabberChat *chat, const char *msg);
 void jabber_chat_track_handle(JabberChat *chat, const char *handle,
 		const char *jid, const char *affiliation, const char *role);
--- a/libpurple/protocols/jabber/google.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/jabber/google.c	Sat Oct 31 17:52:54 2009 +0000
@@ -994,8 +994,9 @@
 
 	const char *grt = xmlnode_get_attrib_with_namespace(item, "t", "google:roster");
 	const char *subscription = xmlnode_get_attrib(item, "subscription");
+	const char *ask = xmlnode_get_attrib(item, "ask");
 
-	if (!subscription || !strcmp(subscription, "none")) {
+	if ((!subscription || !strcmp(subscription, "none")) && !ask) {
 		/* The Google Talk servers will automatically add people from your Gmail address book
 		 * with subscription=none. If we see someone with subscription=none, ignore them.
 		 */
--- a/libpurple/protocols/jabber/jabber.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sat Oct 31 17:52:54 2009 +0000
@@ -1825,7 +1825,7 @@
 		JabberFeature *feature = jabber_features->data;
 		g_free(feature->namespace);
 		g_free(feature);
-		jabber_features = g_list_remove_link(jabber_features, jabber_features);
+		jabber_features = g_list_delete_link(jabber_features, jabber_features);
 	}
 }
 
@@ -1862,7 +1862,7 @@
 		g_free(id->lang);
 		g_free(id->name);
 		g_free(id);
-		jabber_identities = g_list_remove_link(jabber_identities, jabber_identities);
+		jabber_identities = g_list_delete_link(jabber_identities, jabber_identities);
 	}
 }
 
@@ -2606,8 +2606,15 @@
 	if(!chat || !args || !args[0])
 		return PURPLE_CMD_RET_FAILED;
 
-	jabber_chat_change_nick(chat, args[0]);
-	return PURPLE_CMD_RET_OK;
+	if (!jabber_resourceprep_validate(args[0])) {
+		*error = g_strdup(_("Invalid nickname"));
+		return PURPLE_CMD_RET_FAILED;
+	}
+
+	if (jabber_chat_change_nick(chat, args[0]))
+		return PURPLE_CMD_RET_OK;
+	else
+		return PURPLE_CMD_RET_FAILED;
 }
 
 static PurpleCmdRet jabber_cmd_chat_part(PurpleConversation *conv,
--- a/libpurple/protocols/jabber/roster.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/jabber/roster.c	Sat Oct 31 17:52:54 2009 +0000
@@ -72,7 +72,7 @@
 		const char *alias, GSList *groups)
 {
 	GSList *buddies, *l;
-	GSList *pool = NULL;
+	PurpleAccount *account = purple_connection_get_account(js->gc);
 
 	buddies = purple_find_buddies(js->gc->account, jid);
 
@@ -117,25 +117,14 @@
 			groups = g_slist_delete_link(groups, l);
 		} else {
 			/* This buddy isn't in the group on the server anymore */
-			pool = g_slist_prepend(pool, b);
+			purple_debug_info("jabber", "jabber_roster_parse(): Removing %s "
+			                  "from group '%s' on the local list\n",
+			                  purple_buddy_get_name(b),
+			                  purple_group_get_name(g));
+			purple_blist_remove_buddy(b);
 		}
 	}
 
-	if (pool) {
-		GString *tmp = g_string_new(NULL);
-		GSList *list = pool;
-		for ( ; list; list = list->next) {
-			tmp = g_string_append(tmp,
-					purple_group_get_name(purple_buddy_get_group(list->data)));
-			if (list->next)
-				tmp = g_string_append(tmp, ", ");
-		}
-
-		purple_debug_info("jabber", "jabber_roster_parse(): Removing %s from "
-		                  "groups: %s\n", jid, tmp->str);
-		g_string_free(tmp, TRUE);
-	}
-
 	if (groups) {
 		char *tmp = roster_groups_join(groups);
 		purple_debug_info("jabber", "jabber_roster_parse(): Adding %s to "
@@ -145,17 +134,7 @@
 
 	while(groups) {
 		PurpleGroup *g = purple_find_group(groups->data);
-		PurpleBuddy *b = NULL;
-
-		/* If there are buddies we would otherwise delete, move them to
-		 * the new group (instead of deleting them below)
-		 */
-		if (pool) {
-			b = pool->data;
-			pool = g_slist_delete_link(pool, pool);
-		} else {
-			b = purple_buddy_new(js->gc->account, jid, alias);
-		}
+		PurpleBuddy *b = purple_buddy_new(account, jid, alias);
 
 		if(!g) {
 			g = purple_group_new(groups->data);
@@ -169,14 +148,6 @@
 		groups = g_slist_delete_link(groups, groups);
 	}
 
-	/* Remove this person from all the groups they're no longer in on the
-	 * server */
-	while (pool) {
-		PurpleBuddy *b = pool->data;
-		purple_blist_remove_buddy(b);
-		pool = g_slist_delete_link(pool, pool);
-	}
-
 	g_slist_free(buddies);
 }
 
--- a/libpurple/protocols/msn/contact.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/msn/contact.c	Sat Oct 31 17:52:54 2009 +0000
@@ -362,7 +362,7 @@
 	char *display_text;
 
 	passport = xmlnode_get_data(xmlnode_get_child(member, node));
-	if (!purple_email_is_valid(passport)) {
+	if (!msn_email_is_valid(passport)) {
 		g_free(passport);
 		return;
 	}
@@ -765,7 +765,7 @@
 		if (passport == NULL)
 			continue;
 
-		if (!purple_email_is_valid(passport))
+		if (!msn_email_is_valid(passport))
 			continue;
 
 		if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
@@ -1232,8 +1232,13 @@
 	if (user->invite_message) {
 		char *tmp;
 		body = g_markup_escape_text(user->invite_message, -1);
-		tmp = g_markup_escape_text(purple_connection_get_display_name(session->account->gc), -1);
+
+		/* Ignore the cast, we treat it as const anyway. */
+		tmp = (char *)purple_connection_get_display_name(session->account->gc);
+		tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup("");
+
 		invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp);
+
 		g_free(body);
 		g_free(tmp);
 
--- a/libpurple/protocols/msn/msn.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/msn/msn.c	Sat Oct 31 17:52:54 2009 +0000
@@ -118,6 +118,29 @@
 	return buf;
 }
 
+gboolean
+msn_email_is_valid(const char *passport)
+{
+	if (purple_email_is_valid(passport)) {
+		/* Special characters aren't allowed in domains, so only go to '@' */
+		while (*passport != '@') {
+			if (*passport == '/')
+				return FALSE;
+			else if (*passport == '?')
+				return FALSE;
+			else if (*passport == '=')
+				return FALSE;
+			/* MSN also doesn't like colons, but that's checked already */
+
+			passport++;
+		}
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 static gboolean
 msn_send_attention(PurpleConnection *gc, const char *username, guint type)
 {
@@ -1511,7 +1534,7 @@
 
 	bname = purple_buddy_get_name(buddy);
 
-	if (!purple_email_is_valid(bname)) {
+	if (!msn_email_is_valid(bname)) {
 		gchar *buf;
 		buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid.  Usernames must be valid email addresses."), bname);
 		if (!purple_conv_present_error(bname, purple_connection_get_account(gc), buf))
--- a/libpurple/protocols/msn/msn.h	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/msn/msn.h	Sat Oct 31 17:52:54 2009 +0000
@@ -133,6 +133,7 @@
 	((MSN_CLIENT_ID_VERSION    << 24) | \
 	 (MSN_CLIENT_ID_CAPABILITIES))
 
+gboolean msn_email_is_valid(const char *passport);
 void msn_act_id(PurpleConnection *gc, const char *entry);
 void msn_send_privacy(PurpleConnection *gc);
 void msn_send_im_message(MsnSession *session, MsnMessage *msg);
--- a/libpurple/protocols/msn/notification.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/msn/notification.c	Sat Oct 31 17:52:54 2009 +0000
@@ -670,7 +670,7 @@
 			                     "User %s is on both Allow and Block list; "
 			                     "removing from Allow list.\n",
 			                     user->passport);
-			msn_userlist_rem_buddy_from_list(session->userlist, user->passport, MSN_LIST_AL);
+			msn_user_unset_op(user, MSN_LIST_AL_OP);
 		}
 
 		if (user->networkid != MSN_NETWORK_UNKNOWN) {
@@ -840,17 +840,48 @@
 	MsnSession *session;
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	char *adl = g_strndup(payload, len);
-	char *reason = g_strdup_printf(_("Unknown error (%d): %s"),
-		GPOINTER_TO_INT(cmd->payload_cbdata), adl);
-	g_free(adl);
+	int error = GPOINTER_TO_INT(cmd->payload_cbdata);
 
 	session = cmdproc->session;
 	account = session->account;
 	gc = purple_account_get_connection(account);
 
-	purple_notify_error(gc, NULL, _("Unable to add user"), reason);
-	g_free(reason);
+	if (error == 241) {
+		/* khc: some googling suggests that error 241 means the buddy is somehow
+		   in the local list, but not the server list, and that we should add
+		   those buddies to the addressbook. For now I will just notify the user
+		   about the raw payload, because I am lazy */
+		xmlnode *adl = xmlnode_from_str(payload, len);
+		GString *emails = g_string_new(NULL);
+
+		xmlnode *domain = xmlnode_get_child(adl, "d");
+		while (domain) {
+			const char *domain_str = xmlnode_get_attrib(domain, "n");
+			xmlnode *contact = xmlnode_get_child(domain, "c");
+			while (contact) {
+				g_string_append_printf(emails, "%s@%s\n",
+					xmlnode_get_attrib(contact, "n"), domain_str);
+				contact = xmlnode_get_next_twin(contact);
+			}
+			domain = xmlnode_get_next_twin(domain);
+		}
+
+		purple_notify_error(gc, NULL,
+			_("The following users are missing from your addressbook"),
+			emails->str);
+		g_string_free(emails, TRUE);
+		xmlnode_free(adl);
+	}
+	else
+	{
+		char *adl = g_strndup(payload, len);
+		char *reason = g_strdup_printf(_("Unknown error (%d): %s"),
+			error, adl);
+		g_free(adl);
+
+		purple_notify_error(gc, NULL, _("Unable to add user"), reason);
+		g_free(reason);
+	}
 }
 
 static void
@@ -878,50 +909,49 @@
 }
 
 static void
-adl_241_error_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-	size_t len)
+rml_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
 {
-	/* khc: some googling suggests that error 241 means the buddy is somehow
-	   in the local list, but not the server list, and that we should add
-	   those buddies to the addressbook. For now I will just notify the user
-	   about the raw payload, because I am lazy */
 	MsnSession *session;
 	PurpleAccount *account;
 	PurpleConnection *gc;
-	xmlnode *adl;
-	xmlnode *domain;
-	GString *emails;
+	char *adl, *reason;
+	int error = GPOINTER_TO_INT(cmd->payload_cbdata);
 
 	session = cmdproc->session;
 	account = session->account;
 	gc = purple_account_get_connection(account);
 
-	adl = xmlnode_from_str(payload, len);
-	emails = g_string_new(NULL);
+	adl = g_strndup(payload, len);
+	reason = g_strdup_printf(_("Unknown error (%d): %s"),
+		error, adl);
+	g_free(adl);
 
-	domain = xmlnode_get_child(adl, "d");
-	while (domain) {
-		const char *domain_str = xmlnode_get_attrib(domain, "n");
-		xmlnode *contact = xmlnode_get_child(domain, "c");
-		while (contact) {
-			g_string_append_printf(emails, "%s@%s\n",
-				xmlnode_get_attrib(contact, "n"), domain_str);
-			contact = xmlnode_get_next_twin(contact);
-		}
-		domain = xmlnode_get_next_twin(domain);
-	}
-
-	purple_notify_error(gc, NULL,
-		_("The following users are missing from your addressbook"), emails->str);
-	g_string_free(emails, TRUE);
-	xmlnode_free(adl);
+	purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
+	g_free(reason);
 }
 
 static void
-adl_241_error_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+rml_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
 {
-	cmdproc->last_cmd->payload_cb = adl_241_error_cmd_post;
-	cmd->payload_len = atoi(cmd->params[1]);
+	MsnSession *session;
+	PurpleAccount *account;
+	PurpleConnection *gc;
+	MsnCommand *cmd = cmdproc->last_cmd;
+
+	session = cmdproc->session;
+	account = session->account;
+	gc = purple_account_get_connection(account);
+
+	purple_debug_error("msn", "RML error\n");
+	if (cmd->param_count > 1) {
+		cmd->payload_cb = rml_error_parse;
+		cmd->payload_len = atoi(cmd->params[1]);
+		cmd->payload_cbdata = GINT_TO_POINTER(error);
+	} else {
+		char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
+		purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
+		g_free(reason);
+	}
 }
 
 static void
@@ -1068,7 +1098,17 @@
 		/* Where'd this come from? */
 		return;
 
-	if (cmd->param_count == 7) {
+	if (cmd->param_count == 8) {
+		/* Yahoo! Buddy, looks like */
+		networkid = atoi(cmd->params[3]);
+		friendly = g_strdup(purple_url_decode(cmd->params[4]));
+		clientid = strtoul(cmd->params[5], NULL, 10);
+
+		/* cmd->params[7] seems to be a URL to a Yahoo! icon:
+				https://sec.yimg.com/i/us/nt/b/purpley.1.0.png
+		   ... and it's purple, HAH!
+		*/
+	} else if (cmd->param_count == 7) {
 		/* MSNP14+ with Display Picture object */
 		networkid = atoi(cmd->params[3]);
 		friendly = g_strdup(purple_url_decode(cmd->params[4]));
@@ -2095,9 +2135,8 @@
 
 	msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
 
-	msn_table_add_cmd(cbs_table, NULL, "241", adl_241_error_cmd);
-
 	msn_table_add_error(cbs_table, "ADL", adl_error);
+	msn_table_add_error(cbs_table, "RML", rml_error);
 	msn_table_add_error(cbs_table, "FQY", fqy_error);
 	msn_table_add_error(cbs_table, "USR", usr_error);
 
--- a/libpurple/protocols/msn/oim.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/msn/oim.c	Sat Oct 31 17:52:54 2009 +0000
@@ -153,7 +153,7 @@
 	gpointer cb_data;
 } MsnOimRequestData;
 
-static void msn_oim_request_helper(MsnOimRequestData *data);
+static gboolean msn_oim_request_helper(MsnOimRequestData *data);
 
 static void
 msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
@@ -202,7 +202,7 @@
 	g_free(data);
 }
 
-static void
+static gboolean
 msn_oim_request_helper(MsnOimRequestData *data)
 {
 	MsnSession *session = data->oim->session;
@@ -224,13 +224,13 @@
 		const char *msn_p;
 
 		token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
-		g_return_if_fail(token != NULL);
+		g_return_val_if_fail(token != NULL, FALSE);
 
 		msn_t = g_hash_table_lookup(token, "t");
 		msn_p = g_hash_table_lookup(token, "p");
 
-		g_return_if_fail(msn_t != NULL);
-		g_return_if_fail(msn_p != NULL);
+		g_return_val_if_fail(msn_t != NULL, FALSE);
+		g_return_val_if_fail(msn_p != NULL, FALSE);
 
 		passport = xmlnode_get_child(data->body, "Header/PassportCookie");
 		xml_t = xmlnode_get_child(passport, "t");
@@ -248,6 +248,8 @@
 		msn_soap_message_new(data->action, xmlnode_copy(data->body)),
 		data->host, data->url, FALSE,
 		msn_oim_request_cb, data);
+
+	return FALSE;
 }
 
 
--- a/libpurple/protocols/msn/userlist.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/msn/userlist.c	Sat Oct 31 17:52:54 2009 +0000
@@ -539,7 +539,7 @@
 
 	purple_debug_info("msn", "Add user: %s to group: %s\n", who, new_group_name);
 
-	if (!purple_email_is_valid(who))
+	if (!msn_email_is_valid(who))
 	{
 		/* only notify the user about problems adding to the friends list
 		 * maybe we should do something else for other lists, but it probably
--- a/libpurple/protocols/yahoo/libymsg.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/protocols/yahoo/libymsg.c	Sat Oct 31 17:52:54 2009 +0000
@@ -154,6 +154,7 @@
 	gboolean unicode = FALSE;
 	char *message = NULL;
 	YahooFederation fed = YAHOO_FEDERATION_NONE;
+	char *fedname = NULL;
 
 	if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
 		if (!purple_account_get_remember_password(account))
@@ -194,18 +195,20 @@
 						break;
 					if (p->key == 241) {
 						fed = strtol(p->value, NULL, 10);
+						g_free(fedname);
 						switch (fed) {
 							case YAHOO_FEDERATION_MSN:
-								name = g_strconcat("msn/", name, NULL);
+								name = fedname = g_strconcat("msn/", name, NULL);
 								break;
 							case YAHOO_FEDERATION_OCS:
-								name = g_strconcat("ocs/", name, NULL);
+								name = fedname = g_strconcat("ocs/", name, NULL);
 								break;
 							case YAHOO_FEDERATION_IBM:
-								name = g_strconcat("ibm/", name, NULL);
+								name = fedname = g_strconcat("ibm/", name, NULL);
 								break;
 							case YAHOO_FEDERATION_NONE:
 							default:
+								fedname = NULL;
 								break;
 						}
 						break;
@@ -390,6 +393,7 @@
 			yahoo_update_status(gc, name, f);
 	}
 
+	g_free(fedname);
 }
 
 static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group)
@@ -879,6 +883,7 @@
 	char *id;
 	char *msg;
 	YahooFederation fed;
+	char *fed_from;
 };
 
 static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt)
@@ -950,9 +955,6 @@
 	GSList *l = pkt->hash;
 	GSList *list = NULL;
 	struct _yahoo_im *im = NULL;
-	const char *imv = NULL;
-	gint val_11 = 0;
-	char *fed_from = NULL;
 
 	account = purple_connection_get_account(gc);
 
@@ -963,10 +965,11 @@
 			if (pair->key == 4 || pair->key == 1) {
 				im = g_new0(struct _yahoo_im, 1);
 				list = g_slist_append(list, im);
-				im->from = fed_from = pair->value;
+				im->from = pair->value;
 				im->time = time(NULL);
 				im->utf8 = TRUE;
 				im->fed = YAHOO_FEDERATION_NONE;
+				im->fed_from = g_strdup(im->from);
 			}
 			if (im && pair->key == 5)
 				im->active_id = pair->value;
@@ -985,32 +988,75 @@
 			}
 			if (im && pair->key == 241) {
 				im->fed = strtol(pair->value, NULL, 10);
+				g_free(im->fed_from);
 				switch (im->fed) {
 					case YAHOO_FEDERATION_MSN:
-						fed_from = g_strconcat("msn/",im->from, NULL);
+						im->fed_from = g_strconcat("msn/",im->from, NULL);
 						break;
 					case YAHOO_FEDERATION_OCS:
-						fed_from = g_strconcat("ocs/",im->from, NULL);
+						im->fed_from = g_strconcat("ocs/",im->from, NULL);
 						break;
 					case YAHOO_FEDERATION_IBM:
-						fed_from = g_strconcat("ibm/",im->from, NULL);
+						im->fed_from = g_strconcat("ibm/",im->from, NULL);
 						break;
 					case YAHOO_FEDERATION_NONE:
 					default:
+						im->fed_from = g_strdup(im->from);
 						break;
 				}
-				purple_debug_info("yahoo", "Message from federated (%d) buddy %s.\n", im->fed, fed_from);
+				purple_debug_info("yahoo", "Message from federated (%d) buddy %s.\n", im->fed, im->fed_from);
 					
 			}
 			/* peer session id */
-			if (pair->key == 11) {
-				if (im)
-					val_11 = strtol(pair->value, NULL, 10);
+			if (im && (pair->key == 11)) {
+				/* disconnect the peer if connected through p2p and sends wrong value for session id */
+				if( (im->fed == YAHOO_FEDERATION_NONE) && (pkt_type == YAHOO_PKT_TYPE_P2P) 
+						&& (yd->session_id != strtol(pair->value, NULL, 10)) )
+				{
+					purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->fed_from);
+					/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+					g_hash_table_remove(yd->peers, im->fed_from);
+					g_free(im->fed_from);
+					g_free(im);
+					return; /* Not sure whether we should process remaining IMs in this packet */
+				}
 			}
 			/* IMV key */
-			if (pair->key == 63)
+			if (im && pair->key == 63)
 			{
-				imv = pair->value;
+				/* Check for the Doodle IMV, no IMvironment for federated buddies */
+				if (im->from != NULL && im->fed == YAHOO_FEDERATION_NONE)
+				{
+					g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(pair->value));
+
+					if (strstr(pair->value, "doodle;") != NULL)
+					{
+						PurpleWhiteboard *wb;
+
+						if (!purple_privacy_check(account, im->from)) {
+							purple_debug_info("yahoo", "Doodle request from %s dropped.\n",
+												im->from);
+							g_free(im->fed_from);
+							g_free(im);
+							return;
+						}
+						/* I'm not sure the following ever happens -DAA */
+						wb = purple_whiteboard_get_session(account, im->from);
+
+						/* If a Doodle session doesn't exist between this user */
+						if(wb == NULL)
+						{
+							doodle_session *ds;
+							wb = purple_whiteboard_create(account, im->from,
+											DOODLE_STATE_REQUESTED);
+							ds = wb->proto_data;
+							ds->imv_key = g_strdup(pair->value);
+
+							yahoo_doodle_command_send_request(gc, im->from, pair->value);
+							yahoo_doodle_command_send_ready(gc, im->from, pair->value);
+						}
+					}
+				}
 			}
 			if (pair->key == 429)
 				if (im)
@@ -1022,63 +1068,19 @@
 		                  _("Your Yahoo! message did not get sent."), NULL);
 	}
 
-	/* disconnect the peer if connected through p2p and sends wrong value for session id */
-	if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) {
-		purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im ? fed_from : "(im was null)");
-		/* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-		if (im) {
-			g_hash_table_remove(yd->peers, fed_from);
-			g_free(im);
-		}
-		return;
-	}
-
-	/* TODO: It seems that this check should be per IM, not global */
-	/* Check for the Doodle IMV */
-	/* no doodle with federated buddies -- assumption???  */
-	if (im != NULL && imv!= NULL && im->from != NULL)
-	{
-		g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(imv));
-
-		if (strstr(imv, "doodle;") != NULL)
-		{
-			PurpleWhiteboard *wb;
-
-			if (!purple_privacy_check(account, im->from)) {
-				purple_debug_info("yahoo", "Doodle request from %s dropped.\n", im->from);
-				return;
-			}
-
-			/* I'm not sure the following ever happens -DAA */
-
-			wb = purple_whiteboard_get_session(account, im->from);
-
-			/* If a Doodle session doesn't exist between this user */
-			if(wb == NULL)
-			{
-				doodle_session *ds;
-				wb = purple_whiteboard_create(account, im->from, DOODLE_STATE_REQUESTED);
-				ds = wb->proto_data;
-				ds->imv_key = g_strdup(imv);
-
-				yahoo_doodle_command_send_request(gc, im->from, imv);
-				yahoo_doodle_command_send_ready(gc, im->from, imv);
-			}
-		}
-	}
-
 	for (l = list; l; l = l->next) {
 		YahooFriend *f;
 		char *m, *m2;
 		im = l->data;
 
-		if (!fed_from || !im->msg) {
+		if (!im->fed_from || !im->msg) {
+			g_free(im->fed_from);
 			g_free(im);
 			continue;
 		}
 
-		if (!purple_privacy_check(account, fed_from)) {
-			purple_debug_info("yahoo", "Message from %s dropped.\n", fed_from);
+		if (!purple_privacy_check(account, im->fed_from)) {
+			purple_debug_info("yahoo", "Message from %s dropped.\n", im->fed_from);
 			return;
 		}
 
@@ -1116,10 +1118,11 @@
 		if (!strcmp(m, "<ding>")) {
 			char *username;
 
-			username = g_markup_escape_text(fed_from, -1);
+			username = g_markup_escape_text(im->fed_from, -1);
 			purple_prpl_got_attention(gc, username, YAHOO_BUZZ);
 			g_free(username);
 			g_free(m);
+			g_free(im->fed_from);
 			g_free(im);
 			continue;
 		}
@@ -1127,7 +1130,7 @@
 		m2 = yahoo_codes_to_html(m);
 		g_free(m);
 
-		serv_got_im(gc, fed_from, m2, 0, im->time);
+		serv_got_im(gc, im->fed_from, m2, 0, im->time);
 		g_free(m2);
 
 		/* Official clients don't share buddy images with federated buddies */
@@ -1140,9 +1143,7 @@
 			}
 		}
 
-		if(im->fed != YAHOO_FEDERATION_NONE)
-			g_free(fed_from);
-
+		g_free(im->fed_from);
 		g_free(im);
 	}
 
--- a/libpurple/server.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/server.c	Sat Oct 31 17:52:54 2009 +0000
@@ -786,14 +786,14 @@
 	struct chat_invite_data *cid;
 	int plugin_return;
 
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(who != NULL);
+
 	account = purple_connection_get_account(gc);
-	if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->set_permit_deny == NULL) {
-		/* protocol does not support privacy, handle it ourselves */
-		if (!purple_privacy_check(account, who)) {
-			purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked",
-					account, who, name, message, data);
-			return;
-		}
+	if (!purple_privacy_check(account, who)) {
+		purple_signal_emit(purple_conversations_get_handle(), "chat-invite-blocked",
+				account, who, name, message, data);
+		return;
 	}
 
 	cid = g_new0(struct chat_invite_data, 1);
--- a/libpurple/theme-loader.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/libpurple/theme-loader.c	Sat Oct 31 17:52:54 2009 +0000
@@ -100,6 +100,7 @@
 	PurpleThemeLoaderPrivate *priv = PURPLE_THEME_LOADER_GET_PRIVATE(loader);
 
 	g_free(priv->type);
+	g_free(priv);
 
 	parent_class->finalize(obj);
 }
--- a/pidgin/gtkblist.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkblist.c	Sat Oct 31 17:52:54 2009 +0000
@@ -4108,6 +4108,12 @@
 		}
 	}
 
+	if (hidden_conv) {
+		char *tmp = nametext;
+		nametext = g_strdup_printf("<b>%s</b>", tmp);
+		g_free(tmp);
+	}
+
 	/* Put it all together */
 	if ((!aliased || biglist) && (statustext || idletime)) {
 		/* using <span size='smaller'> breaks the status, so it must be seperated into <small><span>*/
--- a/pidgin/gtkconn.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkconn.c	Sat Oct 31 17:52:54 2009 +0000
@@ -142,7 +142,6 @@
 {
 	PurpleAccount *account = NULL;
 	PidginAutoRecon *info;
-	GList *list;
 
 	account = purple_connection_get_account(gc);
 	info = g_hash_table_lookup(auto_reconns, account);
@@ -164,17 +163,6 @@
 
 		purple_account_set_enabled(account, PIDGIN_UI, FALSE);
 	}
-
-	/* If we have any open chats, we probably want to rejoin when we get back online. */
-	list = purple_get_chats();
-	while (list) {
-		PurpleConversation *conv = list->data;
-		list = list->next;
-		if (conv->account != account ||
-				purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))
-			continue;
-		purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE));
-	}
 }
 
 static void pidgin_connection_network_connected (void)
--- a/pidgin/gtkconv.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkconv.c	Sat Oct 31 17:52:54 2009 +0000
@@ -4256,7 +4256,7 @@
 		/* Users */
 		for (; l != NULL; l = l->next) {
 			tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial,
-									  &matches, TRUE, ((PurpleConvChatBuddy *)l->data)->name);
+									  &matches, FALSE, ((PurpleConvChatBuddy *)l->data)->name);
 		}
 
 
@@ -7534,6 +7534,28 @@
 	}
 }
 
+static void
+account_signing_off(PurpleConnection *gc)
+{
+	GList *list = purple_get_chats();
+	PurpleAccount *account = purple_connection_get_account(gc);
+
+	/* We are about to sign off. See which chats we are currently in, and mark
+	 * them for rejoin on reconnect. */
+	while (list) {
+		PurpleConversation *conv = list->data;
+		if (!purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) &&
+				purple_conversation_get_account(conv) == account) {
+			purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE));
+			purple_conversation_write(conv, NULL, _("The account has disconnected and you are no "
+						"longer in this chat. You will be automatically rejoined in the chat when "
+						"the account reconnects."),
+					PURPLE_MESSAGE_SYSTEM, time(NULL));
+		}
+		list = list->next;
+	}
+}
+
 static gboolean
 update_buddy_status_timeout(PurpleBuddy *buddy)
 {
@@ -8028,6 +8050,8 @@
 	purple_signal_connect(purple_connections_get_handle(), "signed-off", handle,
 						G_CALLBACK(account_signed_off_cb),
 						GINT_TO_POINTER(PURPLE_CONV_ACCOUNT_OFFLINE));
+	purple_signal_connect(purple_connections_get_handle(), "signing-off", handle,
+						G_CALLBACK(account_signing_off), NULL);
 
 	purple_signal_connect(purple_conversations_get_handle(), "received-im-msg",
 						handle, G_CALLBACK(received_im_msg_cb), NULL);
--- a/pidgin/gtkimhtml.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkimhtml.c	Sat Oct 31 17:52:54 2009 +0000
@@ -4929,7 +4929,7 @@
 		                                     It will be destroyed when 'anchor' is destroyed. */
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", text, g_free);
-		g_object_set_data(G_OBJECT(anchor), "gtkimhtml_tiptext", text);
+		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_tiptext", g_strdup(text), g_free);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free);
 
 		/* This catches the expose events generated by animated
@@ -4951,7 +4951,8 @@
 			gtk_container_add(GTK_CONTAINER(ebox), img);
 			gtk_widget_show(img);
 			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", text, g_free);
-			g_object_set_data(G_OBJECT(anchor), "gtkimhtml_tiptext", text);
+			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_tiptext",
+				g_strdup(text), g_free);
 			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free);
 			gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor);
 		}
--- a/pidgin/gtkpounce.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkpounce.c	Sat Oct 31 17:52:54 2009 +0000
@@ -1442,7 +1442,7 @@
 		 * Here we place the protocol name in the pounce dialog to lessen
 		 * confusion about what protocol a pounce is for.
 		 */
-		tmp = g_strdup_printf(
+		tmp = g_strdup(
 				   (events & PURPLE_POUNCE_TYPING) ?
 				   _("Started typing") :
 				   (events & PURPLE_POUNCE_TYPED) ?
--- a/pidgin/gtkprefs.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkprefs.c	Sat Oct 31 17:52:54 2009 +0000
@@ -624,7 +624,8 @@
 		_("The default Pidgin status icon theme"));
 	gtk_list_store_set(prefs_status_icon_themes, &iter, 0, pixbuf, 1, tmp, 2, "", -1);
 	g_free(tmp);
-	g_object_unref(G_OBJECT(pixbuf));
+	if (pixbuf)
+		g_object_unref(G_OBJECT(pixbuf));
 
 	purple_theme_manager_for_each_theme(prefs_themes_sort);
 	pref_sound_generate_markup();
--- a/pidgin/gtkstatusbox.c	Sat Oct 31 17:49:11 2009 +0000
+++ b/pidgin/gtkstatusbox.c	Sat Oct 31 17:52:54 2009 +0000
@@ -79,8 +79,8 @@
 
 static void pidgin_status_box_pulse_typing(PidginStatusBox *status_box);
 static void pidgin_status_box_refresh(PidginStatusBox *status_box);
-static void status_menu_refresh_iter(PidginStatusBox *status_box);
-static void pidgin_status_box_regenerate(PidginStatusBox *status_box);
+static void status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed);
+static void pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed);
 static void pidgin_status_box_changed(PidginStatusBox *box);
 static void pidgin_status_box_size_request (GtkWidget *widget, GtkRequisition *requisition);
 static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
@@ -304,7 +304,7 @@
 	if (status_box->account == account)
 		update_to_reflect_account_status(status_box, account, newstatus);
 	else if (status_box->token_status_account == account)
-		status_menu_refresh_iter(status_box);
+		status_menu_refresh_iter(status_box, TRUE);
 }
 
 static gboolean
@@ -312,6 +312,7 @@
 {
 	if (event->button == 3) {
 		GtkWidget *menu_item;
+		const char *path;
 
 		if (box->icon_box_menu)
 			gtk_widget_destroy(box->icon_box_menu);
@@ -325,7 +326,8 @@
 		menu_item = pidgin_new_item_from_stock(box->icon_box_menu, _("Remove"), GTK_STOCK_REMOVE,
 						     G_CALLBACK(remove_buddy_icon_cb),
 						     box, 0, 0, NULL);
-		if (purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon") == NULL)
+		if (!(path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"))
+				|| !*path)
 			gtk_widget_set_sensitive(menu_item, FALSE);
 
 		gtk_menu_popup(GTK_MENU(box->icon_box_menu), NULL, NULL, NULL, NULL,
@@ -559,7 +561,7 @@
 		else
 			statusbox->token_status_account = check_active_accounts_for_identical_statuses();
 
-		pidgin_status_box_regenerate(statusbox);
+		pidgin_status_box_regenerate(statusbox, TRUE);
 
 		break;
 	default:
@@ -821,7 +823,7 @@
  * keyboard signals instead of the changed signal?
  */
 static void
-status_menu_refresh_iter(PidginStatusBox *status_box)
+status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed)
 {
 	PurpleSavedStatus *saved_status;
 	PurpleStatusPrimitive primitive;
@@ -912,18 +914,15 @@
 	} else
 		status_box->active_row = NULL;
 
-	message = purple_savedstatus_get_message(saved_status);
-	if (!purple_savedstatus_is_transient(saved_status) || !message || !*message)
-	{
-		status_box->imhtml_visible = FALSE;
-		gtk_widget_hide_all(status_box->vbox);
-	}
-	else
-	{
-		status_box->imhtml_visible = TRUE;
-		gtk_widget_show_all(status_box->vbox);
+	if (status_changed) {
+		message = purple_savedstatus_get_message(saved_status);
 
 		/*
+		 * If we are going to hide the imhtml, don't retain the
+		 * message because showing the old message later is
+		 * confusing. If we are going to set the message to a pre-set,
+		 * then we need to do this anyway
+		 *
 		 * Suppress the "changed" signal because the status
 		 * was changed programmatically.
 		 */
@@ -931,12 +930,24 @@
 
 		gtk_imhtml_clear(GTK_IMHTML(status_box->imhtml));
 		gtk_imhtml_clear_formatting(GTK_IMHTML(status_box->imhtml));
-		gtk_imhtml_append_text(GTK_IMHTML(status_box->imhtml), message, 0);
+
+		if (!purple_savedstatus_is_transient(saved_status) || !message || !*message)
+		{
+			status_box->imhtml_visible = FALSE;
+			gtk_widget_hide_all(status_box->vbox);
+		}
+		else
+		{
+			status_box->imhtml_visible = TRUE;
+			gtk_widget_show_all(status_box->vbox);
+
+			gtk_imhtml_append_text(GTK_IMHTML(status_box->imhtml), message, 0);
+		}
+
 		gtk_widget_set_sensitive(GTK_WIDGET(status_box->imhtml), TRUE);
+		update_size(status_box);
 	}
 
-	update_size(status_box);
-
 	/* Stop suppressing the "changed" signal. */
 	gtk_widget_set_sensitive(GTK_WIDGET(status_box), TRUE);
 }
@@ -996,50 +1007,50 @@
  * statuses and a token account if they do */
 static PurpleAccount* check_active_accounts_for_identical_statuses(void)
 {
-	PurpleAccount *acct = NULL, *acct2;
-	GList *tmp, *tmp2, *active_accts = purple_accounts_get_all_active();
-	GList *s, *s1, *s2;
-
-	for (tmp = active_accts; tmp; tmp = tmp->next) {
-		acct = tmp->data;
-		s = purple_account_get_status_types(acct);
-		for (tmp2 = tmp->next; tmp2; tmp2 = tmp2->next) {
-			acct2 = tmp2->data;
-
-			/* Only actually look at the statuses if the accounts use the same prpl */
-			if (strcmp(purple_account_get_protocol_id(acct), purple_account_get_protocol_id(acct2))) {
-				acct = NULL;
-				break;
-			}
-
-			s2 = purple_account_get_status_types(acct2);
-
-			s1 = s;
-			while (s1 && s2) {
-				PurpleStatusType *st1 = s1->data, *st2 = s2->data;
-				/* TODO: Are these enough to consider the statuses identical? */
-				if (purple_status_type_get_primitive(st1) != purple_status_type_get_primitive(st2)
-						|| strcmp(purple_status_type_get_id(st1), purple_status_type_get_id(st2))
-						|| strcmp(purple_status_type_get_name(st1), purple_status_type_get_name(st2))) {
-					acct = NULL;
-					break;
-				}
-
-				s1 = s1->next;
-				s2 = s2->next;
-			}
-
-			if (s1 != s2) {/* Will both be NULL if matched */
-				acct = NULL;
+	GList *iter, *active_accts = purple_accounts_get_all_active();
+	PurpleAccount *acct1 = NULL;
+	const char *prpl1 = NULL;
+
+	if (active_accts) {
+		acct1 = active_accts->data;
+		prpl1 = purple_account_get_protocol_id(acct1);
+	} else {
+		/* there's no enabled account */
+		return NULL;
+	}
+
+	/* start at the second account */
+	for (iter = active_accts->next; iter; iter = iter->next) {
+		PurpleAccount *acct2 = iter->data;
+		GList *s1, *s2;
+
+		if (!g_str_equal(prpl1, purple_account_get_protocol_id(acct2))) {
+			acct1 = NULL;
+			break;
+		}
+
+		for (s1 = purple_account_get_status_types(acct1),
+				 s2 = purple_account_get_status_types(acct2); s1 && s2;
+			 s1 = s1->next, s2 = s2->next) {
+			PurpleStatusType *st1 = s1->data, *st2 = s2->data;
+			/* TODO: Are these enough to consider the statuses identical? */
+			if (purple_status_type_get_primitive(st1) != purple_status_type_get_primitive(st2)
+				|| strcmp(purple_status_type_get_id(st1), purple_status_type_get_id(st2))
+				|| strcmp(purple_status_type_get_name(st1), purple_status_type_get_name(st2))) {
+				acct1 = NULL;
 				break;
 			}
 		}
-		if (!acct)
+
+		if (s1 != s2) {/* Will both be NULL if matched */
+			acct1 = NULL;
 			break;
+		}
 	}
+
 	g_list_free(active_accts);
 
-	return acct;
+	return acct1;
 }
 
 static void
@@ -1068,7 +1079,7 @@
 }
 
 static void
-pidgin_status_box_regenerate(PidginStatusBox *status_box)
+pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed)
 {
 	GtkIconSize icon_size;
 
@@ -1104,7 +1115,7 @@
 		pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_CUSTOM, NULL, _("New status..."), NULL, NULL);
 		pidgin_status_box_add(PIDGIN_STATUS_BOX(status_box), PIDGIN_STATUS_BOX_TYPE_SAVED, NULL, _("Saved statuses..."), NULL, NULL);
 
-		status_menu_refresh_iter(status_box);
+		status_menu_refresh_iter(status_box, status_changed);
 		pidgin_status_box_refresh(status_box);
 
 	} else {
@@ -1156,7 +1167,7 @@
 			update_to_reflect_account_status(status_box, status_box->account,
 							purple_account_get_active_status(status_box->account));
 		else {
-			status_menu_refresh_iter(status_box);
+			status_menu_refresh_iter(status_box, TRUE);
 			pidgin_status_box_refresh(status_box);
 		}
 		return TRUE;
@@ -1227,7 +1238,7 @@
 
 	/* Regenerate the list if it has changed */
 	if (initial_token_acct != status_box->token_status_account) {
-		pidgin_status_box_regenerate(status_box);
+		pidgin_status_box_regenerate(status_box, TRUE);
 	}
 
 }
@@ -1236,13 +1247,14 @@
 current_savedstatus_changed_cb(PurpleSavedStatus *now, PurpleSavedStatus *old, PidginStatusBox *status_box)
 {
 	/* Make sure our current status is added to the list of popular statuses */
-	pidgin_status_box_regenerate(status_box);
+	pidgin_status_box_regenerate(status_box, TRUE);
 }
 
 static void
 saved_status_updated_cb(PurpleSavedStatus *status, PidginStatusBox *status_box)
 {
-	pidgin_status_box_regenerate(status_box);
+	pidgin_status_box_regenerate(status_box,
+		purple_savedstatus_get_current() == status);
 }
 
 static void
@@ -1890,7 +1902,7 @@
 	status_box->token_status_account = check_active_accounts_for_identical_statuses();
 
 	cache_pixbufs(status_box);
-	pidgin_status_box_regenerate(status_box);
+	pidgin_status_box_regenerate(status_box, TRUE);
 
 	purple_signal_connect(purple_savedstatuses_get_handle(), "savedstatus-changed",
 						status_box,
@@ -2291,18 +2303,6 @@
 	pidgin_status_box_refresh(status_box);
 }
 
-static gboolean
-message_changed(const char *one, const char *two)
-{
-	if (one == NULL && two == NULL)
-		return FALSE;
-
-	if (one == NULL || two == NULL)
-		return TRUE;
-
-	return (g_utf8_collate(one, two) != 0);
-}
-
 static void
 activate_currently_selected_status(PidginStatusBox *status_box)
 {
@@ -2353,6 +2353,7 @@
 
 	if (status_box->account == NULL) {
 		PurpleStatusType *acct_status_type = NULL;
+		const char *id = NULL; /* id of acct_status_type */
 		PurpleStatusPrimitive primitive = GPOINTER_TO_INT(data);
 		/* Global */
 		/* Save the newly selected status to prefs.xml and status.xml */
@@ -2361,7 +2362,6 @@
 		if (status_box->token_status_account) {
 			gint active;
 			PurpleStatus *status;
-			const char *id = NULL;
 			GtkTreePath *path = gtk_tree_row_reference_get_path(status_box->active_row);
 			active = gtk_tree_path_get_indices(path)[0];
 
@@ -2369,37 +2369,35 @@
 
 			status = purple_account_get_active_status(status_box->token_status_account);
 
-			 acct_status_type = find_status_type_by_index(status_box->token_status_account, active);
+			acct_status_type = find_status_type_by_index(status_box->token_status_account, active);
 			id = purple_status_type_get_id(acct_status_type);
 
-			if (strncmp(id, purple_status_get_id(status), strlen(id)) == 0)
+			if (g_str_equal(id, purple_status_get_id(status)) &&
+				purple_strequal(message, purple_status_get_attr_string(status, "message")))
 			{
 				/* Selected status and previous status is the same */
-				if (!message_changed(message, purple_status_get_attr_string(status, "message")))
-				{
-					PurpleSavedStatus *ss = purple_savedstatus_get_current();
-					/* Make sure that statusbox displays the correct thing.
-					 * It can get messed up if the previous selection was a
-					 * saved status that wasn't supported by this account */
-					if ((purple_savedstatus_get_type(ss) == primitive)
-							&& purple_savedstatus_is_transient(ss)
-							&& purple_savedstatus_has_substatuses(ss))
-						changed = FALSE;
-				}
+				PurpleSavedStatus *ss = purple_savedstatus_get_current();
+				/* Make sure that statusbox displays the correct thing.
+				 * It can get messed up if the previous selection was a
+				 * saved status that wasn't supported by this account */
+				if ((purple_savedstatus_get_type(ss) == primitive)
+					&& purple_savedstatus_is_transient(ss)
+					&& purple_savedstatus_has_substatuses(ss))
+					changed = FALSE;
 			}
 		} else {
 			saved_status = purple_savedstatus_get_current();
 			if (purple_savedstatus_get_type(saved_status) == primitive &&
-			    !purple_savedstatus_has_substatuses(saved_status))
+			    !purple_savedstatus_has_substatuses(saved_status) &&
+				purple_strequal(purple_savedstatus_get_message(saved_status), message))
 			{
-				if (!message_changed(purple_savedstatus_get_message(saved_status), message))
-					changed = FALSE;
+				changed = FALSE;
 			}
 		}
 
 		if (changed)
 		{
-			/* Manually find the appropriate transient acct */
+			/* Manually find the appropriate transient status */
 			if (status_box->token_status_account) {
 				GList *iter = purple_savedstatuses_get_all();
 				GList *tmp, *active_accts = purple_accounts_get_all_active();
@@ -2407,27 +2405,31 @@
 				for (; iter != NULL; iter = iter->next) {
 					PurpleSavedStatus *ss = iter->data;
 					const char *ss_msg = purple_savedstatus_get_message(ss);
+					/* find a known transient status that is the same as the
+					 * new selected one */
 					if ((purple_savedstatus_get_type(ss) == primitive) && purple_savedstatus_is_transient(ss) &&
 						purple_savedstatus_has_substatuses(ss) && /* Must have substatuses */
-						!message_changed(ss_msg, message))
+						purple_strequal(ss_msg, message))
 					{
 						gboolean found = FALSE;
-						/* The currently enabled accounts must have substatuses for all the active accts */
+						/* this status must have substatuses for all the active accts */
 						for(tmp = active_accts; tmp != NULL; tmp = tmp->next) {
 							PurpleAccount *acct = tmp->data;
 							PurpleSavedStatusSub *sub = purple_savedstatus_get_substatus(ss, acct);
 							if (sub) {
 								const PurpleStatusType *sub_type = purple_savedstatus_substatus_get_type(sub);
 								const char *subtype_status_id = purple_status_type_get_id(sub_type);
-								if (subtype_status_id && !strcmp(subtype_status_id,
-										purple_status_type_get_id(acct_status_type)))
+								if (purple_strequal(subtype_status_id, id)) {
 									found = TRUE;
+									break;
+								}
 							}
 						}
-						if (!found)
-							continue;
-						saved_status = ss;
-						break;
+
+						if (found) {
+							saved_status = ss;
+							break;
+						}
 					}
 				}
 
@@ -2470,11 +2472,11 @@
 		status_type = find_status_type_by_index(status_box->account, active);
 		id = purple_status_type_get_id(status_type);
 
-		if (strncmp(id, purple_status_get_id(status), strlen(id)) == 0)
+		if (g_str_equal(id, purple_status_get_id(status)) &&
+			purple_strequal(message, purple_status_get_attr_string(status, "message")))
 		{
 			/* Selected status and previous status is the same */
-			if (!message_changed(message, purple_status_get_attr_string(status, "message")))
-				changed = FALSE;
+			changed = FALSE;
 		}
 
 		if (changed)
@@ -2564,7 +2566,7 @@
 	if (status_box->typing == 0)
 	{
 		/* Nothing has changed, so we don't need to do anything */
-		status_menu_refresh_iter(status_box);
+		status_menu_refresh_iter(status_box, FALSE);
 		return;
 	}
 
@@ -2622,14 +2624,14 @@
 			pidgin_status_editor_show(FALSE,
 				purple_savedstatus_is_transient(saved_status)
 					? saved_status : NULL);
-			status_menu_refresh_iter(status_box);
+			status_menu_refresh_iter(status_box, FALSE);
 			return;
 		}
 
 		if (type == PIDGIN_STATUS_BOX_TYPE_SAVED)
 		{
 			pidgin_status_window_show();
-			status_menu_refresh_iter(status_box);
+			status_menu_refresh_iter(status_box, FALSE);
 			return;
 		}
 	}
--- a/po/ca.po	Sat Oct 31 17:49:11 2009 +0000
+++ b/po/ca.po	Sat Oct 31 17:52:54 2009 +0000
@@ -33,8 +33,8 @@
 msgstr ""
 "Project-Id-Version: Pidgin\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-09-07 18:26-0700\n"
-"PO-Revision-Date: 2009-07-26 17:23+0200\n"
+"POT-Creation-Date: 2009-10-25 17:57+0100\n"
+"PO-Revision-Date: 2009-10-26 09:20+0100\n"
 "Last-Translator: Josep Puigdemont i Casamajó <josep.puigdemont@gmail.com>\n"
 "Language-Team: Catalan <tradgnome@softcatala.net>\n"
 "MIME-Version: 1.0\n"
@@ -576,13 +576,6 @@
 msgid "Re-enable Account"
 msgstr "Rehabilita el compte"
 
-msgid ""
-"The account has disconnected and you are no longer in this chat. You will be "
-"automatically rejoined in the chat when the account reconnects."
-msgstr ""
-"El compte s'ha desconnectat i ja no sou al xat. Quan es torni a connectar el "
-"compte entrareu de nou automàticament al xat."
-
 msgid "No such command."
 msgstr "No existeix l'ordre."
 
@@ -625,6 +618,13 @@
 msgid "You have left this chat."
 msgstr "Heu sortit d'aquest xat"
 
+msgid ""
+"The account has disconnected and you are no longer in this chat. You will be "
+"automatically rejoined in the chat when the account reconnects."
+msgstr ""
+"El compte s'ha desconnectat i ja no sou al xat. Quan es torni a connectar el "
+"compte entrareu de nou automàticament al xat."
+
 msgid "Logging started. Future messages in this conversation will be logged."
 msgstr ""
 "S'ha iniciat el registre. Es registraran els propers missatges d'aquesta "
@@ -661,6 +661,9 @@
 msgid "Enable Sounds"
 msgstr "Habilita els sons"
 
+msgid "You are not connected."
+msgstr "No esteu connectat."
+
 msgid "<AUTO-REPLY> "
 msgstr "<RESPOSTA-AUTOMÀTICA> "
 
@@ -670,8 +673,8 @@
 msgstr[0] "Llista d'%d usuari:\n"
 msgstr[1] "Llista de %d usuaris:\n"
 
-msgid "Supported debug options are:  version"
-msgstr "Les opcions de depuració disponibles són:  version"
+msgid "Supported debug options are: plugins version"
+msgstr "Les opcions de depuració disponibles són:  plugins version"
 
 msgid "No such command (in this context)."
 msgstr "L'ordre no existeix (en aquest context)."
@@ -977,6 +980,9 @@
 msgid "(none)"
 msgstr "(cap)"
 
+#. XXX: The following expects that finch_notify_message gets called. This
+#. * may not always happen, e.g. when another plugin sets its own
+#. * notify_message. So tread carefully.
 msgid "URI"
 msgstr "URI"
 
@@ -1554,9 +1560,15 @@
 "\n"
 "S'està aconseguint un TinyURL..."
 
-#, fuzzy
+#, c-format
+msgid "TinyURL for above: %s"
+msgstr "Fes un TinyURL d'això d'aquí dalt: %s"
+
+msgid "Please wait while TinyURL fetches a shorter URL ..."
+msgstr "Espreu mentre TinyURL obté una URL més curta..."
+
 msgid "Only create TinyURL for URLs of this length or greater"
-msgstr "Crea TinyURL per a URL així de llargues o més"
+msgstr "Només crea TinyURL per a URL així de llargues o més"
 
 msgid "TinyURL (or other) address prefix"
 msgstr "Prefix de l'adreça TinyURL (o altra)"
@@ -1567,10 +1579,9 @@
 msgid "TinyURL plugin"
 msgstr "Connector TinyURL"
 
-#, fuzzy
 msgid "When receiving a message with URL(s), use TinyURL for easier copying"
 msgstr ""
-"Quan rebeu missagtes amb URL, feu servir TinyURL per a copiar més fàcilment"
+"En rebre missagtes amb URL, s'empra TinyURL perquè sigui més fàcil copiar"
 
 msgid "Online"
 msgstr "En línia"
@@ -1676,27 +1687,25 @@
 msgid "buddy list"
 msgstr "llista d'amics"
 
-#, fuzzy
 msgid "The certificate is self-signed and cannot be automatically checked."
-msgstr ""
-"No es pot comprovar el certificat que presenta «%s» atès que està auto-signat."
-
-#, fuzzy
-msgid "The root certificate this one claims to be issued by is unknown."
-msgstr "El Pidgin no coneix el certificat arrel d'aquest certificat."
-
-#, fuzzy
+msgstr "No es pot comprovar el certificat atès que està auto-signat."
+
+msgid ""
+"The certificate is not trusted because no certificate that can verify it is "
+"currently trusted."
+msgstr ""
+"No es pot confiar en el certificat atès que no hi hi ha cap altre certificat "
+"de confiança que el pugui verificar."
+
 msgid "The certificate is not valid yet."
-msgstr "La cadena de certificació que presenta %s no és vàlida."
-
-#, fuzzy
+msgstr "El certificat encara no és vàlid."
+
 msgid "The certificate has expired and should not be considered valid."
-msgstr "La cadena de certificació que presenta %s no és vàlida."
+msgstr "El certificat ha expirat i no s'hauria de considerar vàlid."
 
 #. Translators: "domain" refers to a DNS domain (e.g. talk.google.com)
-#, fuzzy
 msgid "The certificate presented is not issued to this domain."
-msgstr "La cadena de certificació que presenta %s no és vàlida."
+msgstr "El certificat que s'ha presentat no ha estat emès per a aquest domini."
 
 msgid ""
 "You have no database of root certificates, so this certificate cannot be "
@@ -1705,17 +1714,14 @@
 "Aquest certificat no es pot validar perquè no teniu cap base de dades de "
 "certificats arrel."
 
-#, fuzzy
 msgid "The certificate chain presented is invalid."
-msgstr "La cadena de certificació que presenta %s no és vàlida."
-
-#, fuzzy
+msgstr "La cadena de certificació que s'ha presentat no és vàlida."
+
 msgid "The certificate has been revoked."
-msgstr "Ha finalitzat la trucada."
-
-#, fuzzy
+msgstr "El certificat ha estat revocat."
+
 msgid "An unknown certificate error occurred."
-msgstr "Hi ha hagut un error de connexió desconegut: %s."
+msgstr "S'ha produït un error desconegut en el certificat."
 
 msgid "(DOES NOT MATCH)"
 msgstr "(NO COINCIDEIX)"
@@ -1760,26 +1766,25 @@
 msgid "_View Certificate..."
 msgstr "_Mostra el certificat..."
 
-#, fuzzy, c-format
+#, c-format
 msgid "The certificate for %s could not be validated."
-msgstr "La cadena de certificació que presenta %s no és vàlida."
+msgstr "No s'ha pogut validar el certificat de %s."
 
 # Títol de finestra (josep)
 #. TODO: Probably wrong.
 msgid "SSL Certificate Error"
 msgstr "Error en el certificat SSL"
 
-#, fuzzy
 msgid "Unable to validate certificate"
-msgstr "No s'ha pogut autenticar: %s"
-
-#, fuzzy, c-format
+msgstr "No s'ha pogut certificar"
+
+#, c-format
 msgid ""
 "The certificate claims to be from \"%s\" instead. This could mean that you "
 "are not connecting to the service you believe you are."
 msgstr ""
-"El certificat de «%s» sembla indicar que és de «%s». Això podria voler dir que "
-"us esteu connectant a un servei diferent del que us penseu."
+"El certificat indica que és de «%s». Això podria voler dir que us esteu "
+"connectant a un servei diferent del que us penseu."
 
 #. Make messages
 #, c-format
@@ -1927,6 +1932,10 @@
 msgstr "El procés resoledor ha acabat sense respondre la nostra sol·licitud"
 
 #, c-format
+msgid "Error converting %s to punycode: %d"
+msgstr "S'ha produït un error en convertir %s a punycode: %d"
+
+#, c-format
 msgid "Thread creation failure: %s"
 msgstr "S'ha produït un error en crear un fil: %s"
 
@@ -2020,18 +2029,18 @@
 msgid "File transfer complete"
 msgstr "S'ha completat la transferència del fitxer"
 
-#, fuzzy, c-format
+#, c-format
 msgid "You cancelled the transfer of %s"
 msgstr "Heu cancel·lat la transferència de %s"
 
 msgid "File transfer cancelled"
 msgstr "S'ha cancel·lat la transferència del fitxer"
 
-#, fuzzy, c-format
+#, c-format
 msgid "%s cancelled the transfer of %s"
 msgstr "%s ha cancel·lat la transferència de %s"
 
-#, fuzzy, c-format
+#, c-format
 msgid "%s cancelled the file transfer"
 msgstr "%s ha cancel·lat la transferència del fitxer"
 
@@ -2224,28 +2233,30 @@
 "No codecs found. Install some GStreamer codecs found in GStreamer plugins "
 "packages."
 msgstr ""
+"No s'ha trobat cap còdec. Instal·leu els còdecs del GStreamer que podeu "
+"trobar en els paquests de connectors del GStreamer."
 
 msgid ""
 "No codecs left. Your codec preferences in fs-codecs.conf are too strict."
 msgstr ""
-
-#, fuzzy
+"No hi ha cap més còdec. Les preferències dels còdecs al fitxer fs-codecs."
+"conf són massa estrictes."
+
 msgid "A non-recoverable Farsight2 error has occurred."
-msgstr "Hi ha hagut un error de connexió desconegut: %s."
-
-#, fuzzy
-msgid "Conference error."
-msgstr "Conferència tancada"
-
-msgid "Error with your microphone."
-msgstr ""
-
-msgid "Error with your webcam."
-msgstr ""
-
-#, fuzzy, c-format
+msgstr "S'ha produït un error no recuperable del Farsight2."
+
+msgid "Conference error"
+msgstr "Error en la conferència"
+
+msgid "Error with your microphone"
+msgstr "S'ha produït un error amb el micròfon"
+
+msgid "Error with your webcam"
+msgstr "S'ha produït un error amb la càmera web"
+
+#, c-format
 msgid "Error creating session: %s"
-msgstr "S'ha produït un error en crear la connexió"
+msgstr "S'ha produït un error en crear la sessió: %s"
 
 msgid "Error creating conference."
 msgstr "S'ha produït un error en crear la conferència."
@@ -2511,16 +2522,15 @@
 msgid "Test plugin IPC support, as a server. This registers the IPC commands."
 msgstr "Connector de proves per a servidor d'IPC, que registra les ordres IPC."
 
-#, fuzzy
 msgid "Hide Joins/Parts"
-msgstr "Oculta els errors en entrar"
+msgstr "Oculta en entrar/sortir"
 
 #. Translators: Followed by an input request a number of people
 msgid "For rooms with more than this many people"
-msgstr ""
+msgstr "Per sales amb més persones que"
 
 msgid "If user has not spoken in this many minutes"
-msgstr ""
+msgstr "Si l'usuari no ha parlat en"
 
 msgid "Apply hiding rules to buddies"
 msgstr "Aplica les normes d'ocultació als amics"
@@ -3973,11 +3983,11 @@
 msgid "Logo"
 msgstr "Logotip"
 
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "%s will no longer be able to see your status updates.  Do you want to "
 "continue?"
-msgstr "Esteu segur que voleu suprimir %s de la llista d'amics?"
+msgstr "%s no podrà veure l'actualització del vostre estat. Voleu continuar?"
 
 msgid "Cancel Presence Notification"
 msgstr "Cancel·la la notificació de presència"
@@ -3996,6 +4006,9 @@
 msgid "Unsubscribe"
 msgstr "Cancel·la la subscripció"
 
+msgid "Initiate _Chat"
+msgstr "Inicia un _xat"
+
 msgid "Log In"
 msgstr "Connecta"
 
@@ -4580,7 +4593,7 @@
 msgid "configure:  Configure a chat room."
 msgstr "configure:  configura la sala de xat."
 
-msgid "part [room]:  Leave the room."
+msgid "part [message]:  Leave the room."
 msgstr "part [sala]:  surt de la sala."
 
 msgid "register:  Register with a chat room."
@@ -4599,13 +4612,12 @@
 "affiliate &lt;owner|admin|member|outcast|none&gt; [sobrenom1] "
 "[sobrenom2] ...: obtén els usuaris amb una afiliació, o els l'estableix."
 
-#, fuzzy
 msgid ""
 "role &lt;moderator|participant|visitor|none&gt; [nick1] [nick2] ...: Get the "
 "users with a role or set users' role with the room."
 msgstr ""
-"role &lt;usuari&gt; &lt;moderator|participant|visitor|none&gt; [sobrenom1] "
-"[sobrenom2] ...: obtén els usuaris amb el rol especificat, o els l'estableix."
+"role &lt;moderator|participant|visitor|none&gt; [sobrenom1] [sobrenom2] ...: "
+"obtén els usuaris amb el rol especificat, o els l'estableix."
 
 msgid "invite &lt;user&gt; [message]:  Invite a user to the room."
 msgstr "invite &lt;usuari&gt; [sala]:  convida un usuari a la sala."
@@ -5025,7 +5037,6 @@
 msgid "Not expected"
 msgstr "Inesperat"
 
-#, fuzzy
 msgid "Friendly name is changing too rapidly"
 msgstr "El nom amistós canvia massa de pressa"
 
@@ -5245,19 +5256,16 @@
 msgid "Send to Mobile"
 msgstr "Envia a un mòbil"
 
-msgid "Initiate _Chat"
-msgstr "Inicia un _xat"
-
 msgid "SSL support is needed for MSN. Please install a supported SSL library."
 msgstr "L'MSN necessita SSL, instal·leu alguna biblioteca d'SSL permesa."
 
 #, c-format
 msgid ""
 "Unable to add the buddy %s because the username is invalid.  Usernames must "
-"be a valid email address."
+"be valid email addresses."
 msgstr ""
 "No s'ha pogut afegir l'amic %s perquè el nom d'usuari no és vàlid. Els noms "
-"d'usuari han de ser adreces de correu vàlides."
+"d'usuari han de ser adreces de correu electròniques vàlides."
 
 msgid "Unable to Add"
 msgstr "No s'ha pogut afegir"
@@ -5597,10 +5605,10 @@
 "%s ha sol·licitat poder veure la vostra càmera web, però això encara no està "
 "implementat."
 
-#, fuzzy, c-format
+#, c-format
 msgid "%s invited you to view his/her webcam, but this is not yet supported."
 msgstr ""
-"%s ha sol·licitat poder veure la vostra càmera web, però això encara no està "
+"%s us ha convidat a veure la seva càmera web, però això encara no està "
 "implementat."
 
 msgid "Away From Computer"
@@ -6354,9 +6362,9 @@
 msgstr "Port en el servidor"
 
 #. Note to translators: %s in this string is a URL
-#, fuzzy, c-format
+#, c-format
 msgid "Received unexpected response from %s"
-msgstr "S'ha rebut una resposta inesperada de "
+msgstr "S'ha rebut una resposta inesperada de %s"
 
 #. username connecting too frequently
 msgid ""
@@ -6369,9 +6377,9 @@
 
 #. Note to translators: The first %s is a URL, the second is an
 #. error message.
-#, fuzzy, c-format
+#, c-format
 msgid "Error requesting %s: %s"
-msgstr "S'ha produït en sol·licitar "
+msgstr "S'ha produït un error en sol·licitar %s: %s"
 
 msgid "AOL does not allow your screen name to authenticate here"
 msgstr "AOL no permet que us autentiqueu amb aquest nom d'usuari aquí"
@@ -7149,9 +7157,8 @@
 msgid "C_onnect"
 msgstr "C_onnecta"
 
-#, fuzzy
 msgid "You closed the connection."
-msgstr "El servidor ha tancat la connexió"
+msgstr "Heu tancat la connexió."
 
 msgid "Get AIM Info"
 msgstr "Obtén informació de AIM"
@@ -7163,9 +7170,8 @@
 msgid "Get Status Msg"
 msgstr "Aconsegueix el missatge d'estat"
 
-#, fuzzy
 msgid "End Direct IM Session"
-msgstr "S'ha establert una connexió directa de MI"
+msgstr "Finalitzar la sessió de MI directa"
 
 msgid "Direct IM"
 msgstr "MI directa"
@@ -8007,7 +8013,7 @@
 msgid "File Send"
 msgstr "S'ha enviat el fitxer"
 
-#, fuzzy, c-format
+#, c-format
 msgid "%d cancelled the transfer of %s"
 msgstr "%d ha cancel·lat la transferència de %s"
 
@@ -9545,7 +9551,7 @@
 msgstr "Bloca invitacions a conferències i sales de xat"
 
 msgid "Use account proxy for SSL connections"
-msgstr ""
+msgstr "Empra un compte per al servidor intermediàri per a connexions SSL"
 
 msgid "Chat room list URL"
 msgstr "URL de la llista de sales de xat"
@@ -9653,26 +9659,26 @@
 msgid "Ignore buddy?"
 msgstr "Voleu ignorar l'amic?"
 
-#, fuzzy
 msgid "Invalid username or password"
-msgstr "El sobrenom o la contrasenya no són correctes"
-
-#, fuzzy
+msgstr "El sobrenom o la contrasenya no són vàlides"
+
 msgid ""
 "Your account has been locked due to too many failed login attempts.  Please "
 "try logging into the Yahoo! website."
 msgstr ""
-"El compte està blocat perquè s'ha intentat entrar massa cops. Això es pot "
-"solucionar entrant al web de Yahoo!"
+"S'ha blocat el vostre compte perquè s'ha intentat entrar massa cops. Entreu "
+"al web de Yahoo! per solucionar això."
 
 #, c-format
 msgid "Unknown error 52.  Reconnecting should fix this."
-msgstr ""
+msgstr "Error desconegut 52. Es pot sol·lucionar connectant de nou."
 
 msgid ""
 "Error 1013: The username you have entered is invalid.  The most common cause "
 "of this error is entering your email address instead of your Yahoo! ID."
 msgstr ""
+"Error 1013: el nom d'usuari no és vàlid. Pot ser que hagueu introduït la "
+"vostra adreça de correu en lloc del nom d'usuari de Yahoo!"
 
 #, c-format
 msgid "Unknown error number %d. Logging into the Yahoo! website may fix this."
@@ -9764,6 +9770,16 @@
 msgid "Open Inbox"
 msgstr "Obre la safata d'entrada"
 
+msgid "Can't send SMS. Unable to obtain mobile carrier."
+msgstr ""
+"No es poden enviar SMS, no s'ha pogut obtenir l'operador de telefonia mòbil."
+
+msgid "Can't send SMS. Unknown mobile carrier."
+msgstr "No es poden enviar SMS, no es coneix l'operador de telefona mòbil."
+
+msgid "Getting mobile carrier to send the SMS."
+msgstr "S'està obtenint l'operador de telefonia mòbil per a poder enviar SMS."
+
 #. Write a local message to this conversation showing that a request for a
 #. * Doodle session has been made
 #.
@@ -10456,7 +10472,6 @@
 msgid "Layout"
 msgstr "Format"
 
-#, fuzzy
 msgid "The layout of icons, name, and status of the buddy list"
 msgstr "El format de les icones, el nom, i l'estat de la llista d'amics"
 
@@ -10513,9 +10528,8 @@
 
 #. Note to translators: These two strings refer to the font and color
 #. of a buddy list buddy when it is online
-#, fuzzy
 msgid "Online Text"
-msgstr "Text en línia"
+msgstr "Text en estar en línia"
 
 msgid "The text information for when a buddy is online"
 msgstr "Text informatiu per quan un amic estigui en línia"
@@ -10523,18 +10537,16 @@
 #. Note to translators: These two strings refer to the font and color
 #. of a buddy list buddy when it is away
 msgid "Away Text"
-msgstr "Text d'absència"
+msgstr "Text en estar absent"
 
 msgid "The text information for when a buddy is away"
 msgstr "Text informatiu per quan un amic estigui absent"
 
 #. Note to translators: These two strings refer to the font and color
 #. of a buddy list buddy when it is offline
-#, fuzzy
 msgid "Offline Text"
-msgstr "Text de fora de línia"
-
-#, fuzzy
+msgstr "Text fora de línia"
+
 msgid "The text information for when a buddy is offline"
 msgstr "Text informatiu per quan un amic estigui fora de línia"
 
@@ -10559,7 +10571,6 @@
 msgid "Message (Nick Said) Text"
 msgstr "Text del missatge (on s'hi ha dit el sobrenom)"
 
-#, fuzzy
 msgid ""
 "The text information for when a chat has an unread message that mentions "
 "your nickname"
@@ -11005,9 +11016,8 @@
 msgid "_Group:"
 msgstr "_Grup:"
 
-#, fuzzy
 msgid "Auto_join when account connects."
-msgstr "_Entra automàticament quant el compte estigui connectat."
+msgstr "_Entra automàticament quant es connecti el compte."
 
 msgid "_Remain in chat after window is closed."
 msgstr "Co_ntinua al xat quan la finestra es tanqui."
@@ -11121,9 +11131,8 @@
 msgid "/Conversation/New Instant _Message..."
 msgstr "/Conversa/_Missatge instantani nou..."
 
-#, fuzzy
 msgid "/Conversation/Join a _Chat..."
-msgstr "/Conversa/Con_vida..."
+msgstr "/Conversa/Entra a un _xat..."
 
 msgid "/Conversation/_Find..."
 msgstr "/Conversa/_Cerca..."
@@ -11514,7 +11523,7 @@
 msgstr "Estonià"
 
 msgid "Basque"
-msgstr ""
+msgstr "Basc"
 
 msgid "Persian"
 msgstr "Persa"
@@ -11728,6 +11737,13 @@
 "primary language is <b>English</b>.  You are welcome to post in another "
 "language, but the responses may be less helpful.<br/><br/>"
 msgstr ""
+"<font size=\"4\">Ajuda d'altres usuaris del Pidgin:</font> <a href=\"mailto:"
+"support@pidgin.im\">support@pidgin.im</a><br/>Aquesta és una llista de "
+"correu <b>pública</b>. (<a href=\"http://pidgin.im/pipermail/support/"
+"\">arxiu</a>)<br/>No us podem ajudar amb connectors d'altres proveïdors.<br/"
+">En aquesta llista s'hi empra principalment l'<b>anglès</b>.  Podeu escriure-"
+"hi en un altre idioma, però és possible que les respostes no siguin de gaire "
+"ajuda.<br/><br/>"
 
 #, c-format
 msgid ""
@@ -12299,45 +12315,48 @@
 "Usage: %s [OPTION]...\n"
 "\n"
 msgstr ""
-
-#, fuzzy
+"Forma d'ús: %s [OPCIÓ]...\n"
+"\n"
+
 msgid "DIR"
-msgstr "IRC"
+msgstr "DIR"
 
 msgid "use DIR for config files"
-msgstr ""
+msgstr "empra DIR per a fitxers de configuració"
 
 msgid "print debugging messages to stdout"
-msgstr ""
+msgstr "escriu missatges de depuració a la sortida estàndard"
 
 msgid "force online, regardless of network status"
-msgstr ""
+msgstr "força estar en línia, independentment de l'estat de la xarxa"
 
 msgid "display this help and exit"
-msgstr ""
+msgstr "mostra aquesta ajuda i surt"
 
 # FIXME: entrades/registres?
-#, fuzzy
 msgid "allow multiple instances"
-msgstr "Permet diverses entrades simultànies"
+msgstr "permet diverses instàncies"
 
 msgid "don't automatically login"
-msgstr ""
+msgstr "no entra als comptes"
 
 msgid "NAME"
-msgstr ""
+msgstr "NOM"
 
 msgid ""
 "enable specified account(s) (optional argument NAME\n"
 "                      specifies account(s) to use, separated by commas.\n"
 "                      Without this only the first account will be enabled)."
 msgstr ""
+"habilita els comptes especificats (l'argument opcional NAME especifica\n"
+"                      els comptes a emprar, separats per comes. Sense això\n"
+"                      només s'habilitarà el primer compte)."
 
 msgid "X display to use"
-msgstr ""
+msgstr "pantalla d'X a emprar"
 
 msgid "display the current version and exit"
-msgstr ""
+msgstr "mostra la versió actual i surt"
 
 # FIXME: backtrace -> traça (bug-buddy) ?
 #, c-format
@@ -12394,7 +12413,7 @@
 msgstr "%s vol iniciar una sessió de vídeo."
 
 msgid "Incoming Call"
-msgstr ""
+msgstr "Trucada entrant"
 
 msgid "_Pause"
 msgstr "_Pausa"
@@ -12576,50 +12595,54 @@
 msgid "Pounce Target"
 msgstr "Objectiu de l'avís"
 
-#, c-format
 msgid "Started typing"
 msgstr "Hagi començat a escriure"
 
-#, c-format
 msgid "Paused while typing"
 msgstr "S'aturi mentre tecleja"
 
-#, c-format
 msgid "Signed on"
 msgstr "Es connecti"
 
-#, c-format
 msgid "Returned from being idle"
 msgstr "Torna a estar actiu"
 
-#, c-format
 msgid "Returned from being away"
 msgstr "Torni a estar present"
 
-#, c-format
 msgid "Stopped typing"
 msgstr "Pari d'escriure"
 
-#, c-format
 msgid "Signed off"
 msgstr "Es desconnecti"
 
-#, c-format
 msgid "Became idle"
 msgstr "Passi a inactiu"
 
-#, c-format
 msgid "Went away"
 msgstr "En estar absent"
 
-#, c-format
 msgid "Sent a message"
 msgstr "Envia un missatge"
 
-#, c-format
 msgid "Unknown.... Please report this!"
 msgstr "Esdeveniment d'avís desconegut, informeu-nos-en."
 
+msgid "(Custom)"
+msgstr "(Personalitzat)"
+
+msgid "(Default)"
+msgstr "(Predeterminat)"
+
+msgid "The default Pidgin sound theme"
+msgstr "El tema de sons predeterminat del pidgin"
+
+msgid "The default Pidgin buddy list theme"
+msgstr "El tema per a la llista d'amics predeterminat del Pidgin"
+
+msgid "The default Pidgin status icon theme"
+msgstr "El tema de les icones d'estat predeterminat del Pidgin"
+
 msgid "Theme failed to unpack."
 msgstr "No s'ha pogut desempaquetar el tema."
 
@@ -12764,14 +12787,16 @@
 msgid "Cannot start browser configuration program."
 msgstr "No s'ha pogut iniciar el programa de configuració del navegador."
 
-#, fuzzy
 msgid "Disabled"
-msgstr "_Inhabilita"
+msgstr "Inhabilitat"
 
 #, c-format
 msgid "Use _automatically detected IP address: %s"
 msgstr "Empra l'_adreça IP detectada automàticament: %s"
 
+msgid "ST_UN server:"
+msgstr "Servidor ST_UN:"
+
 msgid "<span style=\"italic\">Example: stunserver.org</span>"
 msgstr "<span style=\"italic\">Exemple: stunserver.org</span>"
 
@@ -12797,9 +12822,8 @@
 msgid "Relay Server (TURN)"
 msgstr "Servidor repetidor (TURN)"
 
-#, fuzzy
 msgid "_TURN server:"
-msgstr "Servidor ST_UN:"
+msgstr "Servidor _TURN:"
 
 msgid "Proxy Server &amp; Browser"
 msgstr "Servidor intermediari i navegador"
@@ -14372,35 +14396,29 @@
 "Aquest connector permet a l'usuari personalitzar els formats de les marques "
 "horàries de les converses i dels registres."
 
-#, fuzzy
 msgid "Audio"
-msgstr "Auto"
-
-#, fuzzy
+msgstr "Àudio"
+
 msgid "Video"
 msgstr " Vídeo"
 
 msgid "Output"
-msgstr ""
-
-#, fuzzy
+msgstr "Sortida"
+
 msgid "_Plugin"
-msgstr "Connectors"
-
-#, fuzzy
+msgstr "_Connectors"
+
 msgid "_Device"
-msgstr "Dispositiu"
+msgstr "_Dispositiu"
 
 msgid "Input"
-msgstr ""
-
-#, fuzzy
+msgstr "Entrada"
+
 msgid "P_lugin"
-msgstr "Connectors"
-
-#, fuzzy
+msgstr "C_onnectors"
+
 msgid "D_evice"
-msgstr "Dispositiu"
+msgstr "D_ispositiu"
 
 #. *< magic
 #. *< major version
@@ -14411,18 +14429,19 @@
 #. *< dependencies
 #. *< priority
 #. *< id
-#, fuzzy
 msgid "Voice/Video Settings"
-msgstr "Edita els paràmetres"
+msgstr "Configuració del so/vídeo"
 
 #. *< name
 #. *< version
 msgid "Configure your microphone and webcam."
-msgstr ""
+msgstr "Configureu el micròfon i la càmera web."
 
 #. *< summary
 msgid "Configure microphone and webcam settings for voice/video calls."
 msgstr ""
+"Configureu els paràmetres del micròfon i la càmera web per a trucades de veu/"
+"vídeo."
 
 msgid "Opacity:"
 msgstr "Opacitat:"
@@ -14481,9 +14500,6 @@
 "\n"
 "* Nota: aquest connector requereix Windows 2000 o superior."
 
-msgid "GTK+ Runtime Version"
-msgstr "Versió del mòdul d'execució de GTK+"
-
 #. Autostart
 msgid "Startup"
 msgstr "Inicialització"
@@ -14492,6 +14508,10 @@
 msgid "_Start %s on Windows startup"
 msgstr "_Inicia el %s en iniciar Windows"
 
+# FIXME: entrades/registres?
+msgid "Allow multiple instances"
+msgstr "Permet diverses instàncies"
+
 msgid "_Dockable Buddy List"
 msgstr "Llista _d'amics acoblable"
 
@@ -14553,6 +14573,9 @@
 msgid "This plugin is useful for debbuging XMPP servers or clients."
 msgstr "Aquest connector és útil per a depurar servidors i clients XMPP."
 
+#~ msgid "GTK+ Runtime Version"
+#~ msgstr "Versió del mòdul d'execució de GTK+"
+
 #~ msgid "Calling ... "
 #~ msgstr "S'està trucant..."
 
@@ -14796,9 +14819,6 @@
 #~ msgid "Could not write"
 #~ msgstr "No s'ha pogut escriure"
 
-#~ msgid "Could not connect"
-#~ msgstr "No s'ha pogut connectar"
-
 #~ msgid "Could not create listen socket"
 #~ msgstr "No s'ha pogut crear el sòcol per a escoltar"