changeset 19625:d47bfe67552a

merge of '03fef04c64d9f2d63fe8ba4e58704908e5f8dba8' and 'db4491bcf6c5691919d6131fe99b8da68423253e'
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Tue, 04 Sep 2007 00:39:12 +0000
parents 1b22d4c6fe47 (current diff) f0aef60819af (diff)
children 1a0fabe867be
files libpurple/protocols/myspace/myspace.c
diffstat 28 files changed, 521 insertions(+), 375 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue Sep 04 00:10:03 2007 +0000
+++ b/COPYRIGHT	Tue Sep 04 00:39:12 2007 +0000
@@ -338,6 +338,7 @@
 Michael Shkutkov
 Ettore Simone
 John Silvestri
+Ankit Singla
 Craig Slusher
 Alex Smith
 Brad Smith
@@ -348,6 +349,7 @@
 Sony Computer Entertainment America, Inc.
 Andy Spencer
 Mark Spencer
+Peter Speybrouck
 Lex Spoon
 Chris Stafford
 Kevin Stange
@@ -374,6 +376,7 @@
 Warren Togami
 Stu Tomlinson
 Bill Tompkins
+Gal Topper
 Chris Toshok
 Ken Tossell
 Tom Tromey
--- a/ChangeLog.API	Tue Sep 04 00:10:03 2007 +0000
+++ b/ChangeLog.API	Tue Sep 04 00:39:12 2007 +0000
@@ -9,9 +9,13 @@
 		* serv_send_attention(), serv_got_attention(), as well as send_attention 
 		  and attention_types in PurplePluginProtocolInfo. This new API is used
 		  for zapping in MySpaceIM, buzzing in Yahoo, and nudging in MSN.
+
 		Changed:
 		* purple_prefs_load is now called within purple_prefs_init.
 		  The UI no longer needs to call it.
+		* writing-im-msg now receives the conversation name as the who
+		  argument if the caller of purple_conversation_write didn't
+		  provide a value for who.
 
 	Pidgin:
 		Added:
@@ -21,6 +25,10 @@
 		  conversation
 		* conversation-hiding and conversation-displayed signals.
 
+		Changed:
+		* pidgin_conversations_fill_menu now also adds a separator and a 'Show
+		  All' item if there are more than one conversations in the list.
+
 	Finch:
 		Added:
 		* finch_sound_is_enabled
--- a/finch/plugins/gntclipboard.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/finch/plugins/gntclipboard.c	Tue Sep 04 00:39:12 2007 +0000
@@ -38,10 +38,12 @@
 #include <plugin.h>
 #include <version.h>
 #include <debug.h>
+#include <notify.h>
 #include <gntwm.h>
 
 #include <gntplugin.h>
 
+#ifdef HAVE_X11
 static pid_t child = 0;
 
 static gulong sig_handle;
@@ -49,7 +51,6 @@
 static void
 set_clip(gchar *string)
 {
-#ifdef HAVE_X11
 	Window w;
 	XEvent e, respond;
 	XSelectionRequestEvent *req;
@@ -89,14 +90,12 @@
 			return;
 		}
 	}
-#endif
 	return;
 }
 
 static void
 clipboard_changed(GntWM *wm, gchar *string)
 {
-#ifdef HAVE_X11
 	if (child) {
 		kill(child, SIGTERM);
 	}
@@ -104,8 +103,8 @@
 		set_clip(string);
 		_exit(0);
 	}
+}
 #endif
-}
 
 static gboolean
 plugin_load(PurplePlugin *plugin)
@@ -113,25 +112,35 @@
 #ifdef HAVE_X11
 	if (!XOpenDisplay(NULL)) {
 		purple_debug_warning("gntclipboard", "Couldn't find X display\n");
+		purple_notify_error(NULL, _("Error"), _("Error loading the plugin."),
+				_("Couldn't find X display"));
 		return FALSE;
 	}
-#endif
 	if (!getenv("WINDOWID")) {
 		purple_debug_warning("gntclipboard", "Couldn't find window\n");
+		purple_notify_error(NULL, _("Error"), _("Error loading the plugin."),
+				_("Couldn't find window"));
 		return FALSE;
 	}
 	sig_handle = g_signal_connect(G_OBJECT(gnt_get_clipboard()), "clipboard_changed", G_CALLBACK(clipboard_changed), NULL);
 	return TRUE;
+#else
+	purple_notify_error(NULL, _("Error"), _("Error loading the plugin."),
+			_("This plugin cannot be loaded because it was not built with X11 support."));
+	return FALSE;
+#endif
 }
 
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
+#ifdef HAVE_X11
 	if (child) {
 		kill(child, SIGTERM);
 		child = 0;
 	}
 	g_signal_handler_disconnect(G_OBJECT(gnt_get_clipboard()), sig_handle);
+#endif
 	return TRUE;
 }
 
--- a/libpurple/account.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/account.c	Tue Sep 04 00:39:12 2007 +0000
@@ -1720,15 +1720,6 @@
 purple_account_get_protocol_id(const PurpleAccount *account)
 {
 	g_return_val_if_fail(account != NULL, NULL);
-	/*
-	 * HACK by Seanegan
-	 */
-	if (!strcmp(account->protocol_id, "prpl-oscar")) {
-		if (isdigit(account->username[0]))
-			return "prpl-icq";
-		else
-			return "prpl-aim";
-	}
 	return account->protocol_id;
 }
 
--- a/libpurple/conversation.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/conversation.c	Tue Sep 04 00:39:12 2007 +0000
@@ -869,6 +869,10 @@
 
 	displayed = g_strdup(message);
 
+	if (who == NULL || *who == '\0')
+		who = purple_conversation_get_name(conv);
+	alias = who;
+
 	plugin_return =
 		GPOINTER_TO_INT(purple_signal_emit_return_1(
 			purple_conversations_get_handle(),
@@ -883,11 +887,6 @@
 		return;
 	}
 
-	if (who == NULL || *who == '\0')
-		who = purple_conversation_get_name(conv);
-
-	alias = who;
-
 	if (account != NULL) {
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account)));
 
--- a/libpurple/internal.h	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/internal.h	Tue Sep 04 00:39:12 2007 +0000
@@ -29,6 +29,10 @@
 # include <config.h>
 #endif
 
+/* for SIOCGIFCONF  in SKYOS */
+#ifdef SKYOS
+#include <net/sockios.h>
+#endif
 /*
  * If we're using NLS, make sure gettext works.  If not, then define
  * dummy macros in place of the normal gettext macros.
--- a/libpurple/protocols/bonjour/bonjour.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Tue Sep 04 00:39:12 2007 +0000
@@ -235,6 +235,13 @@
 	g_free(stripped);
 }
 
+static void bonjour_remove_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) {
+	if (buddy->proto_data) {
+		bonjour_buddy_delete(buddy->proto_data);
+		buddy->proto_data = NULL;
+	}
+}
+
 static GList *
 bonjour_status_types(PurpleAccount *account)
 {
@@ -395,7 +402,7 @@
 	NULL,                                                    /* change_passwd */
 	NULL,                                                    /* add_buddy */
 	NULL,                                                    /* add_buddies */
-	NULL,                                                    /* remove_buddy */
+	bonjour_remove_buddy,                                    /* remove_buddy */
 	NULL,                                                    /* remove_buddies */
 	NULL,                                                    /* add_permit */
 	NULL,                                                    /* add_deny */
--- a/libpurple/protocols/bonjour/buddy.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Tue Sep 04 00:39:12 2007 +0000
@@ -121,9 +121,8 @@
  * the buddy.
  */
 void
-bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy)
+bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy)
 {
-	PurpleBuddy *buddy;
 	PurpleGroup *group;
 	PurpleAccount *account = bonjour_buddy->account;
 	const char *status_id, *old_hash, *new_hash;
@@ -147,7 +146,8 @@
 	}
 
 	/* Make sure the buddy exists in our buddy list */
-	buddy = purple_find_buddy(account, bonjour_buddy->name);
+	if (buddy == NULL)
+		buddy = purple_find_buddy(account, bonjour_buddy->name);
 
 	if (buddy == NULL) {
 		buddy = purple_buddy_new(account, bonjour_buddy->name, NULL);
--- a/libpurple/protocols/bonjour/buddy.h	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Tue Sep 04 00:39:12 2007 +0000
@@ -92,8 +92,9 @@
 
 /**
  * If the buddy doesn't previoulsy exists, it is created. Else, its data is changed (???)
+ * purple_buddy is optional; it saves an additional lookup if we already have it
  */
-void bonjour_buddy_add_to_purple(BonjourBuddy *buddy);
+void bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *purple_buddy);
 
 /**
  * We got the buddy icon data; deal with it
--- a/libpurple/protocols/bonjour/jabber.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Tue Sep 04 00:39:12 2007 +0000
@@ -373,17 +373,19 @@
 
 	g_return_if_fail(bb != NULL);
 
-	/* Close the socket, clear the watcher and free memory */
-	bonjour_jabber_close_conversation(bb->conversation);
-	bb->conversation = NULL;
+	/* Inform the user that the conversation has been closed */
+	if (bb->conversation != NULL) {
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, pb->account);
+		if (conv != NULL) {
+			char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name);
+			purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+			g_free(tmp);
+		}
+		/* Close the socket, clear the watcher and free memory */
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
+	}
 
-	/* Inform the user that the conversation has been closed */
-	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, pb->account);
-	if (conv != NULL) {
-		char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name);
-		purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-		g_free(tmp);
-	}
 }
 
 void bonjour_jabber_stream_started(PurpleBuddy *pb) {
--- a/libpurple/protocols/bonjour/mdns_avahi.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_avahi.c	Tue Sep 04 00:39:12 2007 +0000
@@ -33,7 +33,7 @@
 #include <avahi-glib/glib-malloc.h>
 #include <avahi-glib/glib-watch.h>
 
-/* For some reason, this is missing from the Avahi type defines */
+/* Avahi only defines the types that it actually uses (which at this time doesn't include NULL) */
 #ifndef AVAHI_DNS_TYPE_NULL
 #define AVAHI_DNS_TYPE_NULL 0x0A
 #endif
@@ -58,7 +58,8 @@
 		  const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt,
 		  AvahiLookupResultFlags flags, void *userdata) {
 
-	BonjourBuddy *buddy;
+	PurpleBuddy *pb;
+	BonjourBuddy *bb;
 	PurpleAccount *account = userdata;
 	AvahiStringList *l;
 	size_t size;
@@ -67,44 +68,62 @@
 
 	g_return_if_fail(r != NULL);
 
+	pb = purple_find_buddy(account, name);
+	bb = (pb != NULL) ? pb->proto_data : NULL;
+
 	switch (event) {
 		case AVAHI_RESOLVER_FAILURE:
 			purple_debug_error("bonjour", "_resolve_callback - Failure: %s\n",
 				avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
+
 			avahi_service_resolver_free(r);
+			if (bb != NULL) {
+				/* We've already freed the resolver */
+				if (r == ((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver)
+					((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver = NULL;
+				purple_blist_remove_buddy(pb);
+			}
 			break;
 		case AVAHI_RESOLVER_FOUND:
 			/* create a buddy record */
-			buddy = bonjour_buddy_new(name, account);
+			if (bb == NULL)
+				bb = bonjour_buddy_new(name, account);
 
-			((AvahiBuddyImplData *)buddy->mdns_impl_data)->resolver = r;
+			/* If we're reusing an existing buddy, make sure if it is a different resolver to clean up the old one.
+			 * I don't think this should ever happen, but I'm afraid we might get events out of sequence. */
+			if (((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver != NULL
+					&& ((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver != r) {
+				avahi_service_resolver_free(((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver);
+			}
+			((AvahiBuddyImplData *)bb->mdns_impl_data)->resolver = r;
 
+			g_free(bb->ip);
 			/* Get the ip as a string */
-			buddy->ip = g_malloc(AVAHI_ADDRESS_STR_MAX);
-			avahi_address_snprint(buddy->ip, AVAHI_ADDRESS_STR_MAX, a);
+			bb->ip = g_malloc(AVAHI_ADDRESS_STR_MAX);
+			avahi_address_snprint(bb->ip, AVAHI_ADDRESS_STR_MAX, a);
 
-			buddy->port_p2pj = port;
+			bb->port_p2pj = port;
 
 			/* Obtain the parameters from the text_record */
-			clear_bonjour_buddy_values(buddy);
-			l = txt;
-			while (l != NULL) {
-				ret = avahi_string_list_get_pair(l, &key, &value, &size);
-				l = l->next;
-				if (ret < 0)
+			clear_bonjour_buddy_values(bb);
+			for(l = txt; l != NULL; l = l->next) {
+				if ((ret = avahi_string_list_get_pair(l, &key, &value, &size)) < 0)
 					continue;
-				set_bonjour_buddy_value(buddy, key, value, size);
+				set_bonjour_buddy_value(bb, key, value, size);
 				/* TODO: Since we're using the glib allocator, I think we
 				 * can use the values instead of re-copying them */
 				avahi_free(key);
 				avahi_free(value);
 			}
 
-			if (!bonjour_buddy_check(buddy))
-				bonjour_buddy_delete(buddy);
-			else
+			if (!bonjour_buddy_check(bb)) {
+				if (pb != NULL)
+					purple_blist_remove_buddy(pb);
+				else
+					bonjour_buddy_delete(bb);
+			} else
 				/* Add or update the buddy in our buddy list */
-				bonjour_buddy_add_to_purple(buddy);
+				bonjour_buddy_add_to_purple(bb, pb);
 
 			break;
 		default:
@@ -120,7 +139,7 @@
 		  AvahiLookupResultFlags flags, void *userdata) {
 
 	PurpleAccount *account = userdata;
-	PurpleBuddy *gb = NULL;
+	PurpleBuddy *pb = NULL;
 
 	switch (event) {
 		case AVAHI_BROWSER_FAILURE:
@@ -132,7 +151,7 @@
 			/* A new peer has joined the network and uses iChat bonjour */
 			purple_debug_info("bonjour", "_browser_callback - new service\n");
 			/* Make sure it isn't us */
-			if (g_ascii_strcasecmp(name, account->username) != 0) {
+			if (purple_utf8_strcasecmp(name, account->username) != 0) {
 				if (!avahi_service_resolver_new(avahi_service_browser_get_client(b),
 						interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC,
 						0, _resolver_callback, account)) {
@@ -143,16 +162,12 @@
 			break;
 		case AVAHI_BROWSER_REMOVE:
 			purple_debug_info("bonjour", "_browser_callback - Remove service\n");
-			gb = purple_find_buddy(account, name);
-			if (gb != NULL) {
-				bonjour_buddy_delete(gb->proto_data);
-				purple_blist_remove_buddy(gb);
-			}
+			pb = purple_find_buddy(account, name);
+			if (pb != NULL)
+				purple_blist_remove_buddy(pb);
 			break;
 		case AVAHI_BROWSER_ALL_FOR_NOW:
 		case AVAHI_BROWSER_CACHE_EXHAUSTED:
-			purple_debug_warning("bonjour", "(Browser) %s\n",
-				event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
 			break;
 		default:
 			purple_debug_info("bonjour", "Unrecognized Service browser event: %d.\n", event);
--- a/libpurple/protocols/bonjour/mdns_howl.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Tue Sep 04 00:39:12 2007 +0000
@@ -71,6 +71,7 @@
 	char value[SW_TEXT_RECORD_MAX_LEN];
 	sw_uint32 value_length;
 
+	/* TODO: We want to keep listening for updates*/
 	sw_discovery_cancel(discovery, oid);
 
 	/* create a buddy record */
@@ -100,7 +101,7 @@
 	}
 
 	/* Add or update the buddy in our buddy list */
-	bonjour_buddy_add_to_purple(buddy);
+	bonjour_buddy_add_to_purple(buddy, NULL);
 
 	return SW_OKAY;
 }
@@ -149,10 +150,7 @@
 			purple_debug_info("bonjour", "_browser_reply --> Remove service\n");
 			gb = purple_find_buddy(account, name);
 			if (gb != NULL)
-			{
-				bonjour_buddy_delete(gb->proto_data);
 				purple_blist_remove_buddy(gb);
-			}
 			break;
 		case SW_DISCOVERY_BROWSE_RESOLVED:
 			purple_debug_info("bonjour", "_browse_reply --> Resolved\n");
--- a/libpurple/protocols/bonjour/mdns_win32.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Tue Sep 04 00:39:12 2007 +0000
@@ -79,23 +79,23 @@
 	uint32_t ttl, void *context)
 {
 
-	if (kDNSServiceErr_NoError != errorCode)
+	if (kDNSServiceErr_NoError != errorCode) {
 		purple_debug_error("bonjour", "record query - callback error.\n");
-	else if (flags & kDNSServiceFlagsAdd)
-	{
+		/* TODO: Probably should remove the buddy when this happens */
+	} else if (flags & kDNSServiceFlagsAdd) {
 		if (rrtype == kDNSServiceType_TXT) {
 			/* New Buddy */
-			BonjourBuddy *buddy = (BonjourBuddy*) context;
-			_mdns_parse_text_record(buddy, rdata, rdlen);
-			bonjour_buddy_add_to_purple(buddy);
+			BonjourBuddy *bb = (BonjourBuddy*) context;
+			_mdns_parse_text_record(bb, rdata, rdlen);
+			bonjour_buddy_add_to_purple(bb, NULL);
 		} else if (rrtype == kDNSServiceType_NULL) {
 			/* Buddy Icon response */
-			BonjourBuddy *buddy = (BonjourBuddy*) context;
-			Win32BuddyImplData *idata = buddy->mdns_impl_data;
+			BonjourBuddy *bb = (BonjourBuddy*) context;
+			Win32BuddyImplData *idata = bb->mdns_impl_data;
 
 			g_return_if_fail(idata != NULL);
 
-			bonjour_buddy_got_buddy_icon(buddy, rdata, rdlen);
+			bonjour_buddy_got_buddy_icon(bb, rdata, rdlen);
 
 			/* We've got what we need; stop listening */
 			purple_input_remove(idata->null_query_handler);
@@ -110,32 +110,34 @@
 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message)
 {
 	ResolveCallbackArgs* args = (ResolveCallbackArgs*)data;
+	BonjourBuddy* bb = args->buddy;
 
-	if (!hosts || !hosts->data)
+	if (!hosts || !hosts->data) {
 		purple_debug_error("bonjour", "host resolution - callback error.\n");
-	else {
+		bonjour_buddy_delete(bb);
+	} else {
 		struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1);
-		BonjourBuddy* buddy = args->buddy;
-		Win32BuddyImplData *idata = buddy->mdns_impl_data;
+		Win32BuddyImplData *idata = bb->mdns_impl_data;
 
 		g_return_if_fail(idata != NULL);
 
-		buddy->ip = g_strdup(inet_ntoa(addr->sin_addr));
+		g_free(bb->ip);
+		bb->ip = g_strdup(inet_ntoa(addr->sin_addr));
 
 		/* finally, set up the continuous txt record watcher, and add the buddy to purple */
 
 		if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, kDNSServiceFlagsLongLivedQuery,
 				kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT,
-				kDNSServiceClass_IN, _mdns_record_query_callback, buddy)) {
+				kDNSServiceClass_IN, _mdns_record_query_callback, bb)) {
 
-			purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", buddy->name, buddy->ip, buddy->port_p2pj);
+			purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", bb->name, bb->ip, bb->port_p2pj);
 
 			idata->txt_query_handler = purple_input_add(DNSServiceRefSockFD(idata->txt_query),
 				PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query);
 
-			bonjour_buddy_add_to_purple(buddy);
+			bonjour_buddy_add_to_purple(bb, NULL);
 		} else
-			bonjour_buddy_delete(buddy);
+			bonjour_buddy_delete(bb);
 
 	}
 
@@ -202,18 +204,19 @@
     DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context)
 {
 	PurpleAccount *account = (PurpleAccount*)context;
-	PurpleBuddy *gb = NULL;
+	PurpleBuddy *pb = NULL;
 
 	if (kDNSServiceErr_NoError != errorCode)
 		purple_debug_error("bonjour", "service browser - callback error");
 	else if (flags & kDNSServiceFlagsAdd) {
 		/* A presence service instance has been discovered... check it isn't us! */
-		if (g_ascii_strcasecmp(serviceName, account->username) != 0) {
+		if (purple_utf8_strcasecmp(serviceName, account->username) != 0) {
 			/* OK, lets go ahead and resolve it to add to the buddy list */
 			ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1);
 			args->buddy = bonjour_buddy_new(serviceName, account);
 
-			if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args)) {
+			if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype,
+					replyDomain, _mdns_service_resolve_callback, args)) {
 				bonjour_buddy_delete(args->buddy);
 				g_free(args);
 				purple_debug_error("bonjour", "service browser - failed to resolve service.\n");
@@ -226,11 +229,9 @@
 	} else {
 		/* A peer has sent a goodbye packet, remove them from the buddy list */
 		purple_debug_info("bonjour", "service browser - remove notification\n");
-		gb = purple_find_buddy(account, serviceName);
-		if (gb != NULL) {
-			bonjour_buddy_delete(gb->proto_data);
-			purple_blist_remove_buddy(gb);
-		}
+		pb = purple_find_buddy(account, serviceName);
+		if (pb != NULL)
+			purple_blist_remove_buddy(pb);
 	}
 }
 
--- a/libpurple/protocols/irc/irc.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/irc/irc.c	Tue Sep 04 00:39:12 2007 +0000
@@ -347,6 +347,7 @@
 	const char *username, *realname;
 	struct irc_conn *irc = gc->proto_data;
 	const char *pass = purple_connection_get_password(gc);
+	int ret;
 
 	if (pass && *pass) {
 		buf = irc_format(irc, "vv", "PASS", pass);
@@ -359,8 +360,12 @@
 	}
 
 
-	gethostname(hostname, sizeof(hostname));
+	ret = gethostname(hostname, sizeof(hostname));
 	hostname[sizeof(hostname) - 1] = '\0';
+	if (ret < 0 || hostname[0] == '\0') {
+		purple_debug_warning("irc", "gethostname() failed -- is your hostname set?");
+		strcpy(hostname, "localhost");
+	}
 	realname = purple_account_get_string(irc->account, "realname", "");
 	username = purple_account_get_string(irc->account, "username", "");
 
--- a/libpurple/protocols/msn/slp.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/msn/slp.c	Tue Sep 04 00:39:12 2007 +0000
@@ -343,7 +343,7 @@
 		if (xfer)
 		{
 			bin = (char *)purple_base64_decode(context, &bin_len);
-			file_size = GUINT32_FROM_LE(*((gsize *)bin + 2));
+			file_size = GUINT32_FROM_LE(*(gsize *)(bin + 2));
 
 			uni_name = (gunichar2 *)(bin + 20);
 			while(*uni_name != 0 && ((char *)uni_name - (bin + 20)) < MAX_FILE_NAME_LEN) {
--- a/libpurple/protocols/myspace/myspace.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/myspace/myspace.c	Tue Sep 04 00:39:12 2007 +0000
@@ -1444,7 +1444,7 @@
 
 	/* If a local alias wasn't set, set it to user's username. */
 	if (!session->account->alias || !strlen(session->account->alias))
-		session->account->alias = session->username;
+		purple_account_set_alias(session->account, session->username);
 
 	/* The session is now set up, ready to be connected. This emits the
 	 * signedOn signal, so clients can now do anything with msimprpl, and
--- a/libpurple/protocols/oscar/oscar.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue Sep 04 00:39:12 2007 +0000
@@ -3574,7 +3574,7 @@
 	g_free(tmp);
 
 	presence = purple_status_get_presence(status);
-	aim_srv_setidle(od, purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence));
+	aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence));
 
 	if (od->icq) {
 		aim_icq_reqofflinemsgs(od);
--- a/libpurple/protocols/oscar/oscarcommon.h	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/protocols/oscar/oscarcommon.h	Tue Sep 04 00:39:12 2007 +0000
@@ -30,7 +30,7 @@
 #include "version.h"
 #include "notify.h"
 
-#define OSCAR_DEFAULT_LOGIN_SERVER "login.oscar.aol.com"
+#define OSCAR_DEFAULT_LOGIN_SERVER "login.messaging.aol.com"
 #define OSCAR_DEFAULT_LOGIN_PORT 5190
 #ifndef _WIN32
 #define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1"
--- a/libpurple/stun.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/stun.c	Tue Sep 04 00:39:12 2007 +0000
@@ -252,7 +252,7 @@
 				sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
 				if(sinptr->sin_addr.s_addr == in.s_addr) {
 					/* no NAT */
-					purple_debug_info("stun", "no nat");
+					purple_debug_info("stun", "no nat\n");
 					nattype.type = PURPLE_STUN_NAT_TYPE_PUBLIC_IP;
 				}
 			}
--- a/libpurple/util.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/libpurple/util.c	Tue Sep 04 00:39:12 2007 +0000
@@ -4460,10 +4460,11 @@
 const char *_purple_oscar_convert(const char *act, const char *protocol)
 {
 	if (protocol && act && strcmp(protocol, "prpl-oscar") == 0) {
-		if (isdigit(*act))
-			protocol = "prpl-icq";
-		else
-			protocol = "prpl-aim";
+		int i;
+		for (i = 0; act[i] != '\0'; i++)
+			if (!isdigit(act[i]))
+				return "prpl-aim";
+		return "prpl-icq";
 	}
 	return protocol;
 }
--- a/pidgin/gtkaccount.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkaccount.c	Tue Sep 04 00:39:12 2007 +0000
@@ -652,8 +652,10 @@
 		if (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK))
 			gtk_widget_hide(dialog->new_mail_check);
 
-		if (dialog->prpl_info->icon_spec.format == NULL)
+		if (dialog->prpl_info->icon_spec.format == NULL) {
+			gtk_widget_hide(dialog->icon_check);
 			gtk_widget_hide(dialog->icon_hbox);
+		}
 	}
 
 	if (dialog->account != NULL) {
--- a/pidgin/gtkblist.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkblist.c	Tue Sep 04 00:39:12 2007 +0000
@@ -2870,11 +2870,11 @@
 	{ N_("/Buddies/View User _Log..."), "<CTL>L", pidgin_dialogs_log, 0, "<Item>", NULL },
 	{ "/Buddies/sep1", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Buddies/Show"), NULL, NULL, 0, "<Branch>", NULL},
-	{ N_("/Buddies/Show/Show _Offline Buddies"), NULL, pidgin_blist_edit_mode_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/Show _Empty Groups"), NULL, pidgin_blist_show_empty_groups_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/Show Buddy _Details"), NULL, pidgin_blist_buddy_details_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/Show Idle _Times"), NULL, pidgin_blist_show_idle_time_cb, 1, "<CheckItem>", NULL },
-	{ N_("/Buddies/Show/Show _Protocol Icons"), NULL, pidgin_blist_show_protocol_icons_cb, 1, "<CheckItem>", NULL },
+	{ N_("/Buddies/Show/_Offline Buddies"), NULL, pidgin_blist_edit_mode_cb, 1, "<CheckItem>", NULL },
+	{ N_("/Buddies/Show/_Empty Groups"), NULL, pidgin_blist_show_empty_groups_cb, 1, "<CheckItem>", NULL },
+	{ N_("/Buddies/Show/Buddy _Details"), NULL, pidgin_blist_buddy_details_cb, 1, "<CheckItem>", NULL },
+	{ N_("/Buddies/Show/Idle _Times"), NULL, pidgin_blist_show_idle_time_cb, 1, "<CheckItem>", NULL },
+	{ N_("/Buddies/Show/_Protocol Icons"), NULL, pidgin_blist_show_protocol_icons_cb, 1, "<CheckItem>", NULL },
 	{ N_("/Buddies/_Sort Buddies"), NULL, NULL, 0, "<Branch>", NULL },
 	{ "/Buddies/sep2", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Buddies/_Add Buddy..."), "<CTL>B", pidgin_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD },
@@ -4590,22 +4590,22 @@
 	/* set the Show Offline Buddies option. must be done
 	 * after the treeview or faceprint gets mad. -Robot101
 	 */
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Show Offline Buddies"))),
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Offline Buddies"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"));
 
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Show Empty Groups"))),
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Empty Groups"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups"));
 
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Tools/Mute Sounds"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/sound/mute"));
 
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Show Buddy Details"))),
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Buddy Details"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"));
 
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Show Idle Times"))),
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Idle Times"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time"));
 
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Show Protocol Icons"))),
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Protocol Icons"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"));
 
 	if(!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"), "none"))
--- a/pidgin/gtkconv.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkconv.c	Tue Sep 04 00:39:12 2007 +0000
@@ -139,6 +139,7 @@
 static void generate_send_to_items(PidginWindow *win);
 
 /* Prototypes. <-- because Paco-Paco hates this comment. */
+static gboolean infopane_entry_activate(PidginConversation *gtkconv);
 static void got_typing_keypress(PidginConversation *gtkconv, gboolean first);
 static void gray_stuff_out(PidginConversation *gtkconv);
 static GList *generate_invite_user_names(PurpleConnection *gc);
@@ -157,7 +158,8 @@
 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win);
 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv);
 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv);
-static gboolean alias_double_click_cb(GtkWidget *widget, GdkEventButton *event, PidginConversation *gtkconv);
+static gboolean pidgin_userlist_motion_cb (GtkWidget *w, GdkEventMotion *event, PidginConversation *gtkconv);
+static void pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv);
 
 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y,
 		int width, int height);
@@ -1791,17 +1793,108 @@
 }
 
 static gboolean
+conv_keypress_common(PidginConversation *gtkconv, GdkEventKey *event)
+{
+	PidginWindow *win;
+	PurpleConversation *conv;
+	int curconv;
+
+	conv     = gtkconv->active_conv;
+	win      = gtkconv->win;
+	curconv = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook));
+
+	/* If CTRL was held down... */
+	if (event->state & GDK_CONTROL_MASK) {
+		switch (event->keyval) {
+			case GDK_Page_Down:
+			case ']':
+				if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv + 1))
+					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0);
+				else
+					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv + 1);
+				return TRUE;
+				break;
+
+			case GDK_Page_Up:
+			case '[':
+				if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv - 1))
+					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1);
+				else
+					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv - 1);
+				return TRUE;
+				break;
+
+			case GDK_Tab:
+			case GDK_ISO_Left_Tab:
+				if (event->state & GDK_SHIFT_MASK) {
+					move_to_next_unread_tab(gtkconv, FALSE);
+				} else {
+					move_to_next_unread_tab(gtkconv, TRUE);
+				}
+
+				return TRUE;
+				break;
+
+			case GDK_comma:
+				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
+						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
+						curconv - 1);
+				break;
+
+			case GDK_period:
+				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
+						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
+#if GTK_CHECK_VERSION(2,2,0)
+						(curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook)));
+#else
+						(curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children));
+#endif
+				break;
+
+		} /* End of switch */
+	}
+
+	/* If ALT (or whatever) was held down... */
+	else if (event->state & GDK_MOD1_MASK)
+	{
+		if (event->keyval > '0' && event->keyval <= '9')
+		{
+			guint switchto = event->keyval - '1';
+			if (switchto < pidgin_conv_window_get_gtkconv_count(win))
+				gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), switchto);
+
+			return TRUE;
+		}
+	}
+
+	/* If neither CTRL nor ALT were held down... */
+	else
+	{
+		switch (event->keyval) {
+		case GDK_F2:
+			if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) {
+				infopane_entry_activate(gtkconv);
+				return TRUE;
+			}
+			break;
+		}
+	}
+	return FALSE;
+}
+
+static gboolean
 entry_key_press_cb(GtkWidget *entry, GdkEventKey *event, gpointer data)
 {
 	PidginWindow *win;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
-	int curconv;
 
 	gtkconv  = (PidginConversation *)data;
 	conv     = gtkconv->active_conv;
 	win      = gtkconv->win;
-	curconv = gtk_notebook_get_current_page(GTK_NOTEBOOK(win->notebook));
+	
+	if (conv_keypress_common(gtkconv, event))
+		return TRUE;
 
 	/* If CTRL was held down... */
 	if (event->state & GDK_CONTROL_MASK) {
@@ -1899,88 +1992,32 @@
 
 				return TRUE;
 				break;
-
-			case GDK_Page_Down:
-			case ']':
-				if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv + 1))
-					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0);
-				else
-					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv + 1);
-				return TRUE;
-				break;
-
-			case GDK_Page_Up:
-			case '[':
-				if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv - 1))
-					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1);
-				else
-					gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), curconv - 1);
-				return TRUE;
-				break;
-
-			case GDK_Tab:
-			case GDK_ISO_Left_Tab:
-				if (event->state & GDK_SHIFT_MASK) {
-					move_to_next_unread_tab(gtkconv, FALSE);
-				} else {
-					move_to_next_unread_tab(gtkconv, TRUE);
-				}
-
-				return TRUE;
-				break;
-
-			case GDK_comma:
-				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
-						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
-						curconv - 1);
-				break;
-
-			case GDK_period:
-				gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook),
-						gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv),
-#if GTK_CHECK_VERSION(2,2,0)
-						(curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook)));
-#else
-						(curconv + 1) % g_list_length(GTK_NOTEBOOK(win->notebook)->children));
-#endif
-				break;
-
 		} /* End of switch */
 	}
 
 	/* If ALT (or whatever) was held down... */
-	else if (event->state & GDK_MOD1_MASK)
-	{
-		if (event->keyval > '0' && event->keyval <= '9')
-		{
-			guint switchto = event->keyval - '1';
-			if (switchto < pidgin_conv_window_get_gtkconv_count(win))
-				gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), switchto);
-
-			return TRUE;
-		}
+	else if (event->state & GDK_MOD1_MASK) 	{
+
 	}
 
 	/* If neither CTRL nor ALT were held down... */
-	else
-	{
-		switch (event->keyval)
-		{
-			case GDK_Tab:
-				if (gtkconv->entry != entry)
-					break;
-				return tab_complete(conv);
+	else {
+		switch (event->keyval) {
+		case GDK_Tab:
+			if (gtkconv->entry != entry)
 				break;
-
-			case GDK_Page_Up:
-				gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml));
-				return TRUE;
-				break;
-
-			case GDK_Page_Down:
-				gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml));
-				return TRUE;
-				break;
+			return tab_complete(conv);
+			break;
+
+		case GDK_Page_Up:
+			gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml));
+			return TRUE;
+			break;
+
+		case GDK_Page_Down:
+			gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml));
+			return TRUE;
+			break;
 
 		}
 	}
@@ -2021,6 +2058,7 @@
 
 	/* If we have a valid key for the conversation display, then exit */
 	if ((event->state & GDK_CONTROL_MASK) ||
+		(event->keyval == GDK_F6) ||
 		(event->keyval == GDK_F10) ||
 		(event->keyval == GDK_Shift_L) ||
 		(event->keyval == GDK_Shift_R) ||
@@ -2031,11 +2069,17 @@
 		(event->keyval == GDK_Down) ||
 		(event->keyval == GDK_Left) ||
 		(event->keyval == GDK_Right) ||
+		(event->keyval == GDK_Page_Up) ||
+		(event->keyval == GDK_Page_Down) ||
 		(event->keyval == GDK_Home) ||
 		(event->keyval == GDK_End) ||
 		(event->keyval == GDK_Tab) ||
 		(event->keyval == GDK_ISO_Left_Tab))
-			return FALSE;
+	{
+		if (event->type == GDK_KEY_PRESS)
+			return conv_keypress_common(gtkconv, event);
+		return FALSE;
+	}
 
 	if (event->type == GDK_KEY_RELEASE)
 		gtk_widget_grab_focus(gtkconv->entry);
@@ -2516,7 +2560,6 @@
 	gtkconv->u.im->show_icon = FALSE;
 
 	gtkwin = gtkconv->win;
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkwin->menu.show_icon), FALSE);
 }
 
 static void
@@ -2677,31 +2720,6 @@
 	return TRUE;
 }
 
-static void
-menu_buddyicon_cb(gpointer data, guint action, GtkWidget *widget)
-{
-	PidginWindow *win = data;
-	PurpleConversation *conv;
-	PidginConversation *gtkconv;
-	gboolean active;
-
-	conv = pidgin_conv_window_get_active_conversation(win);
-
-	if (!conv)
-		return;
-
-	g_return_if_fail(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM);
-
-	gtkconv = PIDGIN_CONVERSATION(conv);
-
-	active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
-	gtkconv->u.im->show_icon = active;
-	if (active)
-		pidgin_conv_update_buddy_icon(conv);
-	else
-		remove_icon(NULL, gtkconv);
-}
-
 /**************************************************************************
  * End of the bunch of buddy icon functions
  **************************************************************************/
@@ -2768,6 +2786,18 @@
 	pidgin_conv_present_conversation(conv);
 }
 
+static void
+unseen_all_conv_menu_cb(GtkMenuItem *item, GList *list)
+{
+	g_return_if_fail(list != NULL);
+	/* Do not free the list from here. It will be freed from the
+	 * 'destroy' callback on the menuitem. */
+	while (list) {
+		pidgin_conv_present_conversation(list->data);
+		list = list->next;
+	}
+}
+
 guint
 pidgin_conversations_fill_menu(GtkWidget *menu, GList *convs)
 {
@@ -2799,6 +2829,19 @@
 		ret++;
 	}
 
+	if (convs->next) {
+		/* There are more than one conversation. Add an option to show all conversations. */
+		GtkWidget *item;
+		GList *list = g_list_copy(convs);
+
+		pidgin_separator(menu);
+
+		item = gtk_menu_item_new_with_label(_("Show All"));
+		g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(unseen_all_conv_menu_cb), list);
+		g_signal_connect_swapped(G_OBJECT(item), "destroy", G_CALLBACK(g_list_free), list);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+	}
+
 	return ret;
 }
 
@@ -2861,7 +2904,7 @@
 
 
 	{ N_("/Conversation/_Hide"), NULL, menu_hide_conv_cb, 0,
-			"<StockItem>", NULL},
+			"<Item>", NULL},
 	{ N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0,
 			"<StockItem>", GTK_STOCK_CLOSE },
 
@@ -2869,7 +2912,6 @@
 	{ N_("/_Options"), NULL, NULL, 0, "<Branch>", NULL },
 	{ N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "<CheckItem>", NULL },
 	{ N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "<CheckItem>", NULL },
-	{ N_("/Options/Show Buddy _Icon"), NULL, menu_buddyicon_cb, 0, "<CheckItem>", NULL },
 	{ "/Options/sep0", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "<CheckItem>", NULL },
 	{ N_("/Options/Show Ti_mestamps"), "F2", menu_timestamps_cb, 0, "<CheckItem>", NULL },
@@ -2909,31 +2951,6 @@
 	}
 }
 
-static void
-show_buddy_icons_pref_changed_cb(const char *name, PurplePrefType type,
-								 gconstpointer value, gpointer data)
-{
-	PidginWindow *win = data;
-	gboolean show_icons = GPOINTER_TO_INT(value);
-
-	if (!show_icons)
-	{
-		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_icon),
-		                               FALSE);
-		gtk_widget_set_sensitive(win->menu.show_icon, FALSE);
-	}
-	else
-	{
-		PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
-
-		if (gtkconv != NULL)
-			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_icon),
-			                               TRUE);
-		gtk_widget_set_sensitive(win->menu.show_icon, TRUE);
-
-	}
-}
-
 /* Returns TRUE if some items were added to the menu, FALSE otherwise */
 static gboolean
 populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all)
@@ -2992,8 +3009,12 @@
 		node = (PurpleBlistNode *)buddy;
 
 	/* Now add the stuff */
-	if (all && buddy) {
-		pidgin_blist_make_buddy_menu(menu, buddy, TRUE);
+	if (all) {
+		if (buddy)
+			pidgin_blist_make_buddy_menu(menu, buddy, TRUE);
+		else if (chat) {
+			/* XXX: */
+		}
 	} else if (node) {
 		if (purple_account_is_connected(conv->account))
 			pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node);
@@ -3226,17 +3247,7 @@
 	win->menu.show_timestamps =
 		gtk_item_factory_get_widget(win->menu.item_factory,
 		                            N_("/Options/Show Timestamps"));
-	win->menu.show_icon =
-		gtk_item_factory_get_widget(win->menu.item_factory,
-		                            N_("/Options/Show Buddy Icon"));
-	if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
-	{
-		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_icon),
-		                               FALSE);
-		gtk_widget_set_sensitive(win->menu.show_icon, FALSE);
-	}
-	purple_prefs_connect_callback(win, PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons",
-				    show_buddy_icons_pref_changed_cb, win);
+	win->menu.show_icon = NULL;
 
 	win->menu.tray = pidgin_menu_tray_new();
 	gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar),
@@ -4393,6 +4404,10 @@
 
 	g_signal_connect(G_OBJECT(list), "button_press_event",
 					 G_CALLBACK(right_click_chat_cb), gtkconv);
+	g_signal_connect(G_OBJECT(list), "motion-notify-event",
+					 G_CALLBACK(pidgin_userlist_motion_cb), gtkconv);
+	g_signal_connect(G_OBJECT(list), "leave-notify-event",
+					 G_CALLBACK(pidgin_userlist_motion_cb), gtkconv);
 	g_signal_connect(G_OBJECT(list), "popup-menu",
 			 G_CALLBACK(gtkconv_chat_popup_menu_cb), gtkconv);
 	g_signal_connect(G_OBJECT(lbox), "size-allocate", G_CALLBACK(lbox_size_allocate_cb), gtkconv);
@@ -4437,6 +4452,8 @@
 	int timeout;
 	PidginConversation *gtkconv;   /* This is the Pidgin conversation that
 	                                  triggered the tooltip */
+	int userlistx;
+	int userlisty;
 } tooltip;
 
 static void
@@ -4493,6 +4510,72 @@
 	return FALSE;
 }
 
+static gboolean
+pidgin_userlist_tooltip_timeout(PidginConversation *gtkconv)
+{
+	PurplePluginProtocolInfo *prpl_info;
+	PurpleConversation *conv = gtkconv->active_conv;
+	PidginChatPane *gtkchat;
+	PurpleConnection *gc;
+	PurpleBlistNode *node = NULL;
+	PurpleAccount *account;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	GtkTreeViewColumn *column;
+	gchar *who;
+	int x, y;
+
+	gtkchat = gtkconv->u.chat;
+	account = purple_conversation_get_account(conv);
+	gc = account->gc;
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+
+	model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
+
+	gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(gtkchat->list),
+								  tooltip.userlistx, tooltip.userlisty, &path, &column, &x, &y);
+
+	if (path == NULL)
+		return FALSE;
+
+	gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
+	gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1);
+
+	node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who));
+	if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) 
+		pidgin_blist_draw_tooltip(node, gtkconv->infopane);
+
+	g_free(who);
+	gtk_tree_path_free(path);
+
+
+	return FALSE;
+}
+
+static gboolean 
+pidgin_userlist_motion_cb (GtkWidget *w, GdkEventMotion *event, PidginConversation *gtkconv)
+{
+	PurpleConversation *conv;
+	int delay = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/tooltip_delay");
+	
+	pidgin_blist_tooltip_destroy();
+	if (delay == 0)
+		return FALSE;
+
+	if (tooltip.timeout != 0) 
+		g_source_remove(tooltip.timeout);
+	
+	conv = gtkconv->active_conv;
+
+	tooltip.timeout = g_timeout_add(delay, (GSourceFunc)pidgin_userlist_tooltip_timeout, gtkconv);
+	tooltip.gtkconv = gtkconv;
+	tooltip.userlistx = event->x;
+	tooltip.userlisty = event->y;
+
+	return FALSE;
+}
+ 
 static GtkWidget *
 setup_common_pane(PidginConversation *gtkconv)
 {
@@ -6122,7 +6205,6 @@
 
 		gtk_widget_show(win->menu.insert_link);
 		gtk_widget_show(win->menu.insert_image);
-		gtk_widget_show(win->menu.show_icon);
 	} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		/* Show stuff that applies to Chats, hide stuff that applies to IMs */
 
@@ -6135,7 +6217,6 @@
 		gtk_widget_show(win->menu.alias);
 		gtk_widget_hide(win->menu.block);
 		gtk_widget_hide(win->menu.unblock);
-		gtk_widget_hide(win->menu.show_icon);
 
 		if ((account == NULL) || purple_blist_find_chat(account, purple_conversation_get_name(conv)) == NULL) {
 			/* If the chat is NOT in the buddy list */
@@ -6902,7 +6983,8 @@
 	for (l = purple_get_ims(); l != NULL; l = l->next) {
 		conv = (PurpleConversation *)l->data;
 		gtkconv = PIDGIN_CONVERSATION(conv);
-		gtkconv->u.im->animate = GPOINTER_TO_INT(value);
+		if (gtkconv)
+			gtkconv->u.im->animate = GPOINTER_TO_INT(value);
 	}
 
 	/* Now either stop or start animation for the active conversation in each window */
@@ -6921,6 +7003,8 @@
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		PurpleConversation *conv = l->data;
+		if (!PIDGIN_CONVERSATION(conv))
+			continue;
 		if (GPOINTER_TO_INT(value)) 
 			gtk_widget_show(PIDGIN_CONVERSATION(conv)->infopane_hbox);
 		else
@@ -6939,7 +7023,8 @@
 	GList *l;
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		PurpleConversation *conv = l->data;
-		update_tab_icon(conv);
+		if (PIDGIN_CONVERSATION(conv))
+			update_tab_icon(conv);
 	}
 }
 
@@ -7864,7 +7949,7 @@
 infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv)
 {
 	if (e->type == GDK_2BUTTON_PRESS && e->button == 1) {
-		if (alias_double_click_cb(widget, e, gtkconv))
+		if (infopane_entry_activate(gtkconv))
 			return TRUE;
 	}
 
@@ -8105,10 +8190,11 @@
 
 			gtk_window_get_size(GTK_WINDOW(dest_win->window),
 			                    &win_width, &win_height);
-
+#ifdef WIN32  /* only override window manager placement on Windows */
 			gtk_window_move(GTK_WINDOW(dest_win->window),
 			                e->x_root - (win_width  / 2),
 			                e->y_root - (win_height / 2));
+#endif
 
 			pidgin_conv_window_show(dest_win);
 		}
@@ -8321,16 +8407,12 @@
 }
 
 static gboolean
-alias_double_click_cb(GtkWidget *widget, GdkEventButton *event, PidginConversation *gtkconv)
+infopane_entry_activate(PidginConversation *gtkconv)
 {
 	GtkWidget *entry = NULL;
         PurpleConversation *conv = gtkconv->active_conv;
 	const char *text = NULL;
 
-	if (event->button != 1 || event->type != GDK_2BUTTON_PRESS) {
-		return FALSE;
-	}
-
 	if (!GTK_WIDGET_VISIBLE(gtkconv->tab_label)) {
 		/* There's already an entry for alias. Let's not create another one. */
 		return FALSE;
@@ -8373,7 +8455,15 @@
 	gtk_widget_hide(gtkconv->infopane);
 	gtk_widget_grab_focus(entry);
 
-	return FALSE;
+	return TRUE;
+}
+
+static gboolean
+window_keypress_cb(GtkWidget *widget, GdkEventKey *event, PidginWindow *win)
+{
+	PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
+
+	return conv_keypress_common(gtkconv, event);
 }
 
 static void
@@ -8418,13 +8508,6 @@
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_timestamps),
 	                               purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
 
-	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM &&
-	    purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
-	{
-		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_icon),
-		                               gtkconv->u.im->show_icon);
-	}
-
 	/*
 	 * We pause icons when they are not visible.  If this icon should
 	 * be animated then start it back up again.
@@ -8571,6 +8654,11 @@
 	g_signal_connect(G_OBJECT(win->window), "focus_in_event",
 	                 G_CALLBACK(focus_win_cb), win);
 
+	/* Intercept keystrokes from the menu items */
+	g_signal_connect(G_OBJECT(win->window), "key_press_event",
+					 G_CALLBACK(window_keypress_cb), win);
+	
+
 	/* Create the notebook. */
 	win->notebook = gtk_notebook_new();
 
--- a/pidgin/gtkimhtml.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkimhtml.c	Tue Sep 04 00:39:12 2007 +0000
@@ -4890,7 +4890,7 @@
 		} else if (c == '"') {
 			str = g_string_append(str, "&quot;");
 		} else if (c == '\n') {
-			str = g_string_append(str, "<br>");
+			str = g_string_append(str, "<br>\n");
 		} else {
 			str = g_string_append_unichar(str, c);
 		}
--- a/pidgin/gtkimhtmltoolbar.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Tue Sep 04 00:39:12 2007 +0000
@@ -28,6 +28,7 @@
 
 #include "imgstore.h"
 #include "notify.h"
+#include "prefs.h"
 #include "request.h"
 #include "pidginstock.h"
 #include "util.h"
@@ -1021,9 +1022,41 @@
 	if (menu)
 		gtk_widget_destroy(menu);
 
+	purple_prefs_disconnect_by_handle(object);
+
 	G_OBJECT_CLASS(parent_class)->finalize (object);
 }
 
+static void
+switch_toolbar_view(GtkWidget *item, GtkIMHtmlToolbar *toolbar)
+{
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide",
+			!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide"));
+}
+
+static gboolean
+gtk_imhtmltoolbar_popup_menu(GtkWidget *widget, GdkEventButton *event, GtkIMHtmlToolbar *toolbar)
+{
+	GtkWidget *menu;
+	GtkWidget *item;
+	gboolean wide;
+
+	if (event->button != 3)
+		return FALSE;
+
+	wide = GTK_WIDGET_VISIBLE(toolbar->bold);
+
+	menu = gtk_menu_new();
+	item = gtk_menu_item_new_with_mnemonic(wide ? _("Group Items") : _("Ungroup Items"));
+	g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(switch_toolbar_view), toolbar);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+	gtk_widget_show(item);
+
+	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, pidgin_menu_position_func_helper,
+				widget, event->button, event->time);
+	return TRUE;
+}
+
 /* Boring GTK+ stuff */
 static void gtk_imhtmltoolbar_class_init (GtkIMHtmlToolbarClass *class)
 {
@@ -1033,90 +1066,58 @@
 	gobject_class = (GObjectClass*) class;
 	parent_class = gtk_type_class(GTK_TYPE_HBOX);
 	gobject_class->finalize = gtk_imhtmltoolbar_finalize;
+
+	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/toolbar");
+	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide", FALSE);
 }
 
 static void gtk_imhtmltoolbar_create_old_buttons(GtkIMHtmlToolbar *toolbar)
 {
+	GtkWidget *hbox;
 	GtkWidget *button;
-	/* Bold */
-	button = pidgin_pixbuf_toolbar_button_from_stock(GTK_STOCK_BOLD);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(do_bold), toolbar);
-	toolbar->bold = button;
-
-
-	/* Italic */
-	button = pidgin_pixbuf_toolbar_button_from_stock(GTK_STOCK_ITALIC);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(do_italic), toolbar);
-	toolbar->italic = button;
-
-	/* Underline */
-	button = pidgin_pixbuf_toolbar_button_from_stock(GTK_STOCK_UNDERLINE);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(do_underline), toolbar);
-	toolbar->underline = button;
-
-
-	/* Strikethrough */
-	button = pidgin_pixbuf_toolbar_button_from_stock(GTK_STOCK_STRIKETHROUGH);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			G_CALLBACK(do_strikethrough), toolbar);
-	toolbar->strikethrough = button;
-
-	/* Increase font size */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_TEXT_LARGER);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(do_big), toolbar);
-	toolbar->larger_size = button;
-
-	/* Decrease font size */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(do_small), toolbar);
-	toolbar->smaller_size = button;
+	struct {
+		char *stock;
+		gpointer callback;
+		GtkWidget **button;
+		const char *tooltip;
+	} buttons[] = {
+		{GTK_STOCK_BOLD, G_CALLBACK(do_bold), &toolbar->bold, _("Bold")},
+		{GTK_STOCK_ITALIC, do_italic, &toolbar->italic, _("Italic")},
+		{GTK_STOCK_UNDERLINE, do_underline, &toolbar->underline, _("Underline")},
+		{GTK_STOCK_STRIKETHROUGH, do_strikethrough, &toolbar->strikethrough, _("Strikethrough")},
+		{"", NULL, NULL, NULL},
+		{PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, do_big, &toolbar->larger_size, _("Increase Font Size")},
+		{PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, do_small, &toolbar->smaller_size, _("Decrease Font Size")},
+		{"", NULL, NULL, NULL},
+		{PIDGIN_STOCK_TOOLBAR_FONT_FACE, toggle_font, &toolbar->font, _("Font Face")},
+		{PIDGIN_STOCK_TOOLBAR_FGCOLOR, toggle_bg_color, &toolbar->bgcolor, _("Background Color")},
+		{PIDGIN_STOCK_TOOLBAR_BGCOLOR, toggle_fg_color, &toolbar->fgcolor, _("Foreground Color")},
+		{"", NULL, NULL, NULL},
+		{PIDGIN_STOCK_CLEAR, clear_formatting_cb, &toolbar->clear, _("Reset Formatting")},
+		{"", NULL, NULL, NULL},
+		{PIDGIN_STOCK_TOOLBAR_INSERT_LINK, insert_link_cb, &toolbar->link, _("Insert Link")},
+		{PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, insert_image_cb, &toolbar->image, _("Insert IM Image")},
+		{PIDGIN_STOCK_TOOLBAR_SMILEY, insert_smiley_cb, &toolbar->smiley, _("Insert Smiley")},
+		{NULL, NULL, NULL, NULL}
+	};
+	int iter;
 
-	/* Font Face */
-
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_FONT_FACE);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(toggle_font), toolbar);
-	toolbar->font = button;
-
-	/* Foreground Color */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_FGCOLOR);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(toggle_fg_color), toolbar);
-	toolbar->fgcolor = button;
-
-	/* Background Color */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_BGCOLOR);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(toggle_bg_color), toolbar);
-	toolbar->bgcolor = button;
+	hbox = gtk_hbox_new(FALSE, 0);
 
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_INSERT_LINK);
-	g_signal_connect(G_OBJECT(button), "clicked",
-				 G_CALLBACK(insert_link_cb), toolbar);
-	toolbar->link = button;
-
-	/* Insert IM Image */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(insert_image_cb), toolbar);
-	toolbar->image = button;
+	for (iter = 0; buttons[iter].stock; iter++) {
+		if (buttons[iter].stock[0]) {
+			button = pidgin_pixbuf_toolbar_button_from_stock(buttons[iter].stock);
+			g_signal_connect(G_OBJECT(button), "clicked",
+					 G_CALLBACK(buttons[iter].callback), toolbar);
+			*(buttons[iter].button) = button;
+			gtk_tooltips_set_tip(toolbar->tooltips, button, buttons[iter].tooltip, NULL);
+		} else
+			button = gtk_vseparator_new();
+		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+	}
 
-	/* Insert Smiley */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(insert_smiley_cb), toolbar);
-	toolbar->smiley = button;
-
-	/* Reset formatting */
-	button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY);
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(clear_formatting_cb), toolbar);
-	toolbar->clear = button;
+	gtk_box_pack_start(GTK_BOX(toolbar), hbox, FALSE, FALSE, 0);
+	g_object_set_data(G_OBJECT(toolbar), "wide-view", hbox);
 }
 
 static void
@@ -1140,10 +1141,23 @@
 		g_object_set(G_OBJECT(widget), "use-markup", TRUE, NULL);
 }
 
+static void
+imhtmltoolbar_view_pref_changed(const char *name, PurplePrefType type,
+		gconstpointer value, gpointer toolbar)
+{
+	if (value) {
+		gtk_widget_hide_all(g_object_get_data(G_OBJECT(toolbar), "lean-view"));
+		gtk_widget_show_all(g_object_get_data(G_OBJECT(toolbar), "wide-view"));
+	} else {
+		gtk_widget_hide_all(g_object_get_data(G_OBJECT(toolbar), "wide-view"));
+		gtk_widget_show_all(g_object_get_data(G_OBJECT(toolbar), "lean-view"));
+	}
+}
+
 static void gtk_imhtmltoolbar_init (GtkIMHtmlToolbar *toolbar)
 {
-	GtkWidget *hbox = GTK_WIDGET(toolbar);
-	GtkWidget *bbox;
+	GtkWidget *hbox = GTK_WIDGET(toolbar), *event = gtk_event_box_new();
+	GtkWidget *bbox, *box = gtk_hbox_new(FALSE, 0);
 	GtkWidget *image;
 	GtkWidget *label;
 	GtkWidget *insert_button;
@@ -1177,7 +1191,6 @@
 		{NULL, NULL, FALSE}
 	};
 
-
 	toolbar->imhtml = NULL;
 	toolbar->font_dialog = NULL;
 	toolbar->fgcolor_dialog = NULL;
@@ -1203,7 +1216,7 @@
 	gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
 	g_object_set_data(G_OBJECT(hbox), "font_label", label);
 	gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(hbox), font_button, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(box), font_button, FALSE, FALSE, 0);
 	gtk_widget_show_all(font_button);
 
 	font_menu = gtk_menu_new();
@@ -1232,7 +1245,7 @@
 
 	/* Sep */
 	sep = gtk_vseparator_new();
-	gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0);
 	gtk_widget_show_all(sep);
 
 	/* Insert */
@@ -1244,7 +1257,7 @@
 	gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0);
 	label = gtk_label_new_with_mnemonic(_("_Insert"));
 	gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(hbox), insert_button, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(box), insert_button, FALSE, FALSE, 0);
 	gtk_widget_show_all(insert_button);
 
 	insert_menu = gtk_menu_new();
@@ -1277,6 +1290,18 @@
 	g_signal_connect(G_OBJECT(insert_button), "activate", G_CALLBACK(pidgin_menu_clicked), insert_menu);
 	g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button);
 	toolbar->sml = NULL;
+
+	gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0);
+	g_object_set_data(G_OBJECT(hbox), "lean-view", box);
+
+	purple_prefs_connect_callback(toolbar, PIDGIN_PREFS_ROOT "/conversations/toolbar/wide",
+			imhtmltoolbar_view_pref_changed, toolbar);
+	purple_prefs_trigger_callback(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide");
+
+	gtk_widget_add_events(event, GDK_BUTTON_PRESS_MASK);
+	gtk_box_pack_start(GTK_BOX(hbox), event, TRUE, TRUE, 0);
+	g_signal_connect(G_OBJECT(event), "button-press-event", G_CALLBACK(gtk_imhtmltoolbar_popup_menu), toolbar);
+	gtk_widget_show(event);
 }
 
 GtkWidget *gtk_imhtmltoolbar_new()
--- a/pidgin/gtkmain.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkmain.c	Tue Sep 04 00:39:12 2007 +0000
@@ -774,21 +774,6 @@
 	/* TODO: Move pounces loading into purple_pounces_init() */
 	purple_pounces_load();
 
-	/* HACK BY SEANEGAN:
-	 * We've renamed prpl-oscar to prpl-aim and prpl-icq, accordingly.
-	 * Let's do that change right here... after everything's loaded, but
-	 * before anything has happened
-	 */
-	for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
-		PurpleAccount *account = accounts->data;
-		if (!strcmp(purple_account_get_protocol_id(account), "prpl-oscar")) {
-			if (isdigit(*purple_account_get_username(account)))
-				purple_account_set_protocol_id(account, "prpl-icq");
-			else
-				purple_account_set_protocol_id(account, "prpl-aim");
-		}
-	}
-
 	ui_main();
 
 #ifdef USE_SM
--- a/pidgin/gtkpounce.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkpounce.c	Tue Sep 04 00:39:12 2007 +0000
@@ -975,7 +975,7 @@
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/pounces/default_actions/play-sound"));
 	}
 
-	gtk_widget_show_all(vbox2);
+	gtk_widget_show(vbox2);
 	gtk_widget_show(window);
 }
 
--- a/pidgin/gtkprefs.c	Tue Sep 04 00:10:03 2007 +0000
+++ b/pidgin/gtkprefs.c	Tue Sep 04 00:39:12 2007 +0000
@@ -1036,12 +1036,14 @@
 		gtk_widget_set_sensitive(hbox, FALSE);
 	g_signal_connect(G_OBJECT(fontpref), "clicked", G_CALLBACK(pidgin_toggle_sensitive), hbox);
 	g_signal_connect(G_OBJECT(font_button), "font-set", G_CALLBACK(pidgin_custom_font_set), NULL);
+	gtk_widget_show_all(hbox);
 #endif
 
 	vbox = pidgin_make_frame(ret, _("Default Formatting"));
 	gtk_box_set_child_packing(GTK_BOX(vbox->parent), vbox, TRUE, TRUE, 0, GTK_PACK_START);
 
 	frame = pidgin_create_imhtml(TRUE, &imhtml, &toolbar, NULL);
+	gtk_widget_show(frame);
 	gtk_widget_set_name(imhtml, "pidgin_prefs_font_imhtml");
 	gtk_widget_set_size_request(frame, 300, -1);
 	gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(imhtml), TRUE);
@@ -1068,7 +1070,7 @@
 					 G_CALLBACK(formatting_clear_cb), NULL);
 
 
-	gtk_widget_show_all(ret);
+	gtk_widget_show(ret);
 
 	return ret;
 }