changeset 25481:48ef40b32eb7

propagate from branch 'im.pidgin.pidgin' (head b131b26bdebd017ae74090008e1672615c9080bc) to branch 'im.pidgin.pidgin.yaz' (head cc410ab56ed0715a80ba68c86470f3c5f1f00036)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Wed, 09 May 2007 06:05:32 +0000
parents 9ded461750a9 (diff) 50a9c82d32a1 (current diff)
children e4ee1c5bd51e
files configure.ac libpurple/protocols/jabber/jabber.c libpurple/protocols/oscar/oscar.c pidgin/gtkconv.c pidgin/gtkimhtml.c pidgin/gtkmain.c
diffstat 32 files changed, 430 insertions(+), 583 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Mon May 07 01:58:53 2007 +0000
+++ b/COPYRIGHT	Wed May 09 06:05:32 2007 +0000
@@ -161,6 +161,7 @@
 Nigel Horne
 Jensen Hornick
 Juanjo Molinero Horno
+Dustin Howett
 Nathanael Hoyle
 Greg Hudson
 Magnus Hult
--- a/ChangeLog	Mon May 07 01:58:53 2007 +0000
+++ b/ChangeLog	Wed May 09 06:05:32 2007 +0000
@@ -3,6 +3,7 @@
 version 2.0.1 (??/??/????):
 	* Buddy list update speedups when buddy icons are not being
 	  displayed.  (Scott Wolchok)
+	* Custom smileys on MSN can be saved by right-clicking on them.
 
 	Finch:
 	* Userlist in chat windows, which can be turned on or off using
--- a/config.h.mingw	Mon May 07 01:58:53 2007 +0000
+++ b/config.h.mingw	Wed May 09 06:05:32 2007 +0000
@@ -4,65 +4,26 @@
 /* configure arguments */
 /* #undef CONFIG_ARGS */
 
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-   systems. This function is required for `alloca.c' support on those systems.
-   */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define to 1 if using `alloca.c'. */
-/* #undef C_ALLOCA */
-
 /* Define if debugging is enabled. */
 /* #undef DEBUG */
 
-/* Use binary relocation? */
-/* #undef ENABLE_BINRELOC */
-
 /* Define if mono enabled. */
 /* #undef ENABLE_MONO */
 
-/* Define to 1 if translation of program messages to the user's native
-   language is requested. */
+/* always defined to indicate that i18n is enabled */
 #define ENABLE_NLS 1
 
-/* Define to make assertions fatal (useful for debugging). */
-/* #undef PURPLE_FATAL_ASSERTS */
-
-/* Define if plugins are enabled. */
-#define PURPLE_PLUGINS 1
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
-   */
-/* #undef HAVE_ALLOCA_H */
-
-/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
-/* #undef HAVE_ALSA_ASOUNDLIB_H */
-
 /* Define if you have the external 'altzone' variable. */
 /* #undef HAVE_ALTZONE */
 
-/* Define to 1 if you have the <argz.h> header file. */
-/* #undef HAVE_ARGZ_H */
-
 /* Define to 1 if you have the <arpa/nameser_compat.h> header file. */
 /* #undef HAVE_ARPA_NAMESER_COMPAT_H */
 
-/* Define to 1 if you have the `asprintf' function. */
-/* #undef HAVE_ASPRINTF */
-
 /* Define to 1 if you have the `atexit' function. */
 #define HAVE_ATEXIT 1
 
-/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
-   CoreFoundation framework. */
-/* #undef HAVE_CFLOCALECOPYCURRENT */
-
-/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
-   the CoreFoundation framework. */
-/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+/* Define to 1 if you have the `bind_textdomain_codeset' function. */
+/* #undef HAVE_BIND_TEXTDOMAIN_CODESET */
 
 /* Define to 1 if you have the `connect' function. */
 /* #undef HAVE_CONNECT */
@@ -73,39 +34,19 @@
 /* Define if you have the external 'daylight' variable. */
 #define HAVE_DAYLIGHT 1
 
-/* Define if we are re using DBUS. */
+/* Define if we are using D-Bus. */
 /* #undef HAVE_DBUS */
 
-/* Define if the GNU dcgettext() function is already present or preinstalled.
-   */
+/* Define to 1 if you have the `dcgettext' function. */
 /* #undef HAVE_DCGETTEXT */
 
-/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_FEOF_UNLOCKED */
-
-/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
-   you don't. */
-/* #undef HAVE_DECL_FGETS_UNLOCKED */
-
-/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
-   don't. */
-/* #undef HAVE_DECL_GETC_UNLOCKED */
-
-/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
-   don't. */
-#define HAVE_DECL__SNPRINTF 1
-
-/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you
-   don't. */
-#define HAVE_DECL__SNWPRINTF 1
+/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't.
+   */
+/* #undef HAVE_DECL_TZNAME */
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
 /* #undef HAVE_DLFCN_H */
 
-/* Define to 1 if you have the `dlopen' function. */
-/* #undef HAVE_DLOPEN */
-
 /* whether or not we have dot */
 /* #undef HAVE_DOT */
 
@@ -121,68 +62,28 @@
 /* Define to 1 if you have the <fcntl.h> header file. */
 #define HAVE_FCNTL_H 1
 
-/* Define to 1 if you have the `fwprintf' function. */
-#define HAVE_FWPRINTF 1
-
 /* Define to 1 if you have the getaddrinfo function. */
 /* TODO: Use this on new enough versions of Windows */
 /* #define HAVE_GETADDRINFO 1 */
 
-/* Define to 1 if you have the `getcwd' function. */
-#define HAVE_GETCWD 1
-
-/* Define to 1 if you have the `getegid' function. */
-/* #define HAVE_GETEGID 1 */
-
-/* Define to 1 if you have the `geteuid' function. */
-/* #define HAVE_GETEUID 1 */
-
-/* Define to 1 if you have the `getgid' function. */
-/* #define HAVE_GETGID 1 */
-
 /* Define to 1 if you have the `gethostid' function. */
 /* #define HAVE_GETHOSTID 1 */
 
 /* Define to 1 if you have the `getopt_long' function. */
 /* #define HAVE_GETOPT_LONG 1 */
 
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
 /* Define if the GNU gettext() function is already present or preinstalled. */
 /* #define HAVE_GETTEXT 1 */
 
-/* Define to 1 if you have the `getuid' function. */
-/* #define HAVE_GETUID 1 */
-
-/* Pidgin always has GLib, but Linphone can be built without it */
-/* #undef HAVE_GLIB */
-
 /* Define if you have GNUTLS */
 /* #define HAVE_GNUTLS 1 */
 
 /* Define to 1 if you have the <gnutls/gnutls.h> header file. */
 /* #define HAVE_GNUTLS_GNUTLS_H 1 */
 
-/* Define if you have the iconv() function. */
-/* #define HAVE_ICONV 1 */
-
-/* Defined when we have ilbc codec lib */
-/* #undef HAVE_ILBC */
-
-/* Define to 1 if you have the <iLBC_decode.h> header file. */
-/* #undef HAVE_ILBC_DECODE_H */
-
-/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
-#define HAVE_INTMAX_T 1
-
 /* Define if <inttypes.h> exists and doesn't clash with <sys/types.h>. */
 #define HAVE_INTTYPES_H 1
 
-/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
-   declares uintmax_t. */
-#define HAVE_INTTYPES_H_WITH_UINTMAX 1
-
 /* Define if we have IOKit */
 /* #undef HAVE_IOKIT */
 
@@ -201,15 +102,15 @@
 /* Define to 1 if you have the `krb_set_key' function. */
 /* #undef HAVE_KRB_SET_KEY */
 
-/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
-/* #define HAVE_LANGINFO_CODESET 1 */
-
 /* Define if your <locale.h> file defines LC_MESSAGES. */
 /* #define HAVE_LC_MESSAGES 1 */
 
 /* Define to 1 if you have libgadu. */
 #define HAVE_LIBGADU 1
 
+/* Define if you have NetworkManager */
+/* #undef HAVE_LIBNM */
+
 /* Define to 1 if you have the `nsl' library (-lnsl). */
 /* #define HAVE_LIBNSL 1 */
 
@@ -219,24 +120,12 @@
 /* Define to 1 if you have the `socket' library (-lsocket). */
 /* #undef HAVE_LIBSOCKET */
 
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
 /* Define to 1 if you have the <locale.h> header file. */
 #define HAVE_LOCALE_H 1
 
-/* Define if you have the 'long double' type. */
-#define HAVE_LONG_DOUBLE 1
-
-/* Define if you have the 'long long' type. */
-#define HAVE_LONG_LONG 1
-
 /* Define to 1 if you have the `lrand48' function. */
 /* #define HAVE_LRAND48 1 */
 
-/* Define to 1 if you have the <machine/soundcard.h> header file. */
-/* #undef HAVE_MACHINE_SOUNDCARD_H */
-
 /* Define to 1 if you have the <malloc.h> header file. */
 #define HAVE_MALLOC_H 1
 
@@ -249,12 +138,6 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
-/* Define to 1 if you have the `mempcpy' function. */
-/* #define HAVE_MEMPCPY 1*/
-
-/* Define to 1 if you have a working `mmap' system call. */
-/* #define HAVE_MMAP 1 */
-
 /* Define to 1 if you have the `mono_jit_init' function. */
 /* #undef HAVE_MONO_JIT_INIT */
 
@@ -264,12 +147,6 @@
 /* Define to 1 if you have the <mono/metadata/object.h> header file. */
 /* #undef HAVE_MONO_METADATA_OBJECT_H */
 
-/* Define to 1 if you have the `munmap' function. */
-/* #define HAVE_MUNMAP 1 */
-
-/* Define to 1 if you have the <nl_types.h> header file. */
-/* #define HAVE_NL_TYPES_H 1 */
-
 /* Define to 1 if you have the <nspr.h> header file. */
 /* #undef HAVE_NSPR_H */
 
@@ -297,24 +174,15 @@
 /* Define to 1 if you have the `perl_run' function. */
 /* #define HAVE_PERL_RUN 1 */
 
-/* Define if your printf() function supports format strings with positions. */
-#define HAVE_POSIX_PRINTF 1
-
 /* Define to 1 if you have the <prio.h> header file. */
 /* #undef HAVE_PRIO_H */
 
-/* Define to 1 if you have the `putenv' function. */
-#define HAVE_PUTENV 1
-
 /* Define to 1 if you have the `random' function. */
 /* #define HAVE_RANDOM 1 */
 
 /* Define to 1 if you have the <regex.h> header file. */
 /* #define HAVE_REGEX_H 1 */
 
-/* Define to 1 if you have the `setenv' function. */
-/* #define HAVE_SETENV 1 */
-
 /* Define to 1 if you have the `setlocale' function. */
 #define HAVE_SETLOCALE 1
 
@@ -333,12 +201,6 @@
 /* Define to 1 if you have the `snprintf' function. */
 #define HAVE_SNPRINTF 1
 
-/* Define to 1 if you have the <soundcard.h> header file. */
-/* #undef HAVE_SOUNDCARD_H */
-
-/* Define to 1 if you have the <speex.h> header file. */
-/* #undef HAVE_SPEEX_H */
-
 /* Define if you have SSL */
 #define HAVE_SSL 1
 
@@ -351,25 +213,12 @@
 /* Define to 1 if you have the <stdarg.h> header file. */
 #define HAVE_STDARG_H 1
 
-/* Define to 1 if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
 /* Define to 1 if you have the <stdint.h> header file. */
 #define HAVE_STDINT_H 1
 
-/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
-   uintmax_t. */
-#define HAVE_STDINT_H_WITH_UINTMAX 1
-
 /* Define to 1 if you have the <stdlib.h> header file. */
 #define HAVE_STDLIB_H 1
 
-/* Define to 1 if you have the `stpcpy' function. */
-/* #define HAVE_STPCPY 1 */
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#define HAVE_STRCASECMP 1
-
 /* Define to 1 if you have the `strchr' function. */
 #define HAVE_STRCHR 1
 
@@ -394,15 +243,9 @@
 /* Define to 1 if you have the `strstr' function. */
 #define HAVE_STRSTR 1
 
-/* Define to 1 if you have the `strtoul' function. */
-#define HAVE_STRTOUL 1
-
 /* Define to 1 if `tm_zone' is member of `struct tm'. */
 /* #define HAVE_STRUCT_TM_TM_ZONE 1 */
 
-/* Define to 1 if you have the <sys/audio.h> header file. */
-/* #undef HAVE_SYS_AUDIO_H */
-
 /* Define to 1 if you have the <sys/cdefs.h> header file. */
 /* #define HAVE_SYS_CDEFS_H 1 */
 
@@ -418,15 +261,9 @@
 /* Define to 1 if you have the <sys/msgbuf.h> header file. */
 /* #undef HAVE_SYS_MSGBUF_H */
 
-/* Define to 1 if you have the <sys/param.h> header file. */
-/* #define HAVE_SYS_PARAM_H 1 */
-
 /* Define to 1 if you have the <sys/select.h> header file. */
 /* #define HAVE_SYS_SELECT_H 1 */
 
-/* Define to 1 if you have the <sys/soundcard.h> header file. */
-/* #undef HAVE_SYS_SOUNDCARD_H */
-
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #define HAVE_SYS_STAT_H 1
 
@@ -464,61 +301,28 @@
    `HAVE_STRUCT_TM_TM_ZONE' instead. */
 /* #define HAVE_TM_ZONE 1 */
 
-/* Define to 1 if you have the `tsearch' function. */
-/* #define HAVE_TSEARCH 1 */
-
 /* Define to 1 if you don't have `tm_zone' but do have the external array
    `tzname'. */
 /* #undef HAVE_TZNAME */
 
-/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
-#define HAVE_UINTMAX_T 1
-
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
-/* Define if you have the 'unsigned long long' type. */
-#define HAVE_UNSIGNED_LONG_LONG 1
-
 /* Define to 1 if you have the `vprintf' function. */
 #define HAVE_VPRINTF 1
 
-/* Compile with Voice/Video support */
-/* #undef HAVE_VV */
-
-/* Define if you have the 'wchar_t' type. */
-#define HAVE_WCHAR_T 1
-
-/* Define to 1 if you have the `wcslen' function. */
-#define HAVE_WCSLEN 1
-
-/* Define if you have the 'wint_t' type. */
-#define HAVE_WINT_T 1
+/* Define to 1 if you have X11 */
+/* #define HAVE_X11 1 */
 
 /* Define to 1 if you have the <X11/SM/SMlib.h> header file. */
 /* #define HAVE_X11_SM_SMLIB_H 1 */
 
-/* Define to 1 if you have the `__argz_count' function. */
-/* #define HAVE___ARGZ_COUNT 1 */
-
-/* Define to 1 if you have the `__argz_next' function. */
-/* #define HAVE___ARGZ_NEXT 1 */
-
-/* Define to 1 if you have the `__argz_stringify' function. */
-/* #define HAVE___ARGZ_STRINGIFY 1 */
-
-/* Define to 1 if you have the `__fsetlocking' function. */
-/* #define HAVE___FSETLOCKING 1 */
-
-/* Define as const if the declaration of iconv() needs const. */
-/* #define ICONV_CONST */
-
-/* Define if integer division by zero raises signal SIGFPE. */
-/* #define INTDIV0_RAISES_SIGFPE 1 */
-
 /* Define if external libzephyr should be used. */
 /* #undef LIBZEPHYR_EXT */
 
+/* Define to 1 if you don't have wide-character support. */
+/* #undef NO_WIDECHAR */
+
 /* Define if old perl is installed. */
 /* #undef OLD_PERL */
 
@@ -540,23 +344,17 @@
 /* Define to the version of this package. */
 /* #define PACKAGE_VERSION "2.0.0dev" */
 
-/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
-/* #undef PRI_MACROS_BROKEN */
+/* Define to make assertions fatal (useful for debugging). */
+/* #define PURPLE_FATAL_ASSERTS 1 */
+
+/* Define if plugins are enabled. */
+#define PURPLE_PLUGINS 1
 
 /* Define as the return type of signal handlers (`int' or `void'). */
 #define RETSIGTYPE void
 
-/* Define as the maximum value of type 'size_t', if the system doesn't define
-   it. */
-/* #undef SIZE_MAX */
-
-/* If using the C implementation of alloca, define if you know the
-   direction of stack growth for your system; otherwise it will be
-   automatically deduced at run-time.
-    STACK_DIRECTION > 0 => grows toward higher addresses
-    STACK_DIRECTION < 0 => grows toward lower addresses
-    STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
+/* The size of `time_t', as computed by sizeof. */
+#define SIZEOF_TIME_T 4
 
 /* Loads static protocol plugin module initialization functions. */
 #ifndef STATIC_PROTO_INIT
@@ -569,10 +367,10 @@
 /* Define to 1 if your <sys/time.h> declares `struct tm'. */
 /* #undef TM_IN_SYS_TIME */
 
-/* Define if we're using libao and libaudiofile for sound playing */
-/* #define USE_AO 1 */
+/* Use GStreamer for playing sounds */
+/* #define USE_GSTREAMER 1 */
 
-/* do we have gtkspell? */
+/* Define if we're using GtkSpell */
 #define USE_GTKSPELL 1
 
 /* Define if we're using XScreenSaver. */
@@ -603,48 +401,14 @@
 /* Define for large files, on AIX-style hosts. */
 /* #undef _LARGE_FILES */
 
-/* Defined when alsa support is enabled */
-/* #undef __ALSA_ENABLED__ */
-
-/* Jack support */
-/* #undef __JACK_ENABLED__ */
-
 /* Define to empty if `const' does not conform to ANSI C. */
 /* #undef const */
 
-/* Define to `__inline__' or `__inline' if that's what the C compiler
-   calls it, or to nothing if 'inline' is not supported under any name.  */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-/* Define to `long' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define as the type of the result of subtracting two pointers, if the system
-   doesn't define it. */
-/* #undef ptrdiff_t */
-
-/* Define to empty if the C compiler doesn't support this keyword. */
-/* #undef signed */
-
-/* Define to `unsigned' if <sys/types.h> does not define. */
-/* #undef size_t */
-
 /* socklen_t size */
-/* #define socklen_t int */
-
-/* Define to unsigned long or unsigned long long if <stdint.h> and
-   <inttypes.h> don't define. */
-/* #undef uintmax_t */
-
-#define HAVE_LIBXML 1
+/* #undef socklen_t */
 
 /*
  * Following are added for Win32 version of Pidgin
  */
 #define HAVE_VSNPRINTF 1
 
-#define SIZEOF_TIME_T 4
-
-#define PIDGIN_NAME "Pidgin"
--- a/configure.ac	Mon May 07 01:58:53 2007 +0000
+++ b/configure.ac	Wed May 09 06:05:32 2007 +0000
@@ -139,6 +139,19 @@
 ALL_LINGUAS=""
 AM_GLIB_GNU_GETTEXT
 
+dnl If we don't have msgfmt, then po/ is going to fail -- ensure that
+dnl AM_GLIB_GNU_GETTEXT found it.
+
+if test x$MSGFMT = xno -o x$GMSGFMT = x
+then
+	AC_ERROR([
+
+The msgfmt command is required to build libpurple.  If it is installed
+on your system, ensure that it is in your path.  If it is not, install
+GNU gettext to continue.
+])
+fi
+
 dnl we don't use autobreak on cygwin!!
 dnl AC_CYGWIN
 
--- a/finch/finch.c	Mon May 07 01:58:53 2007 +0000
+++ b/finch/finch.c	Wed May 09 06:05:32 2007 +0000
@@ -274,6 +274,8 @@
 	}
 	/* show version message */
 	if (opt_version) {
+		/* Translators may want to transliterate the name.
+		 It is not to be translated. */
 		printf("%s %s\n", _("Finch"), VERSION);
 		return 0;
 	}
--- a/finch/gntblist.c	Mon May 07 01:58:53 2007 +0000
+++ b/finch/gntblist.c	Wed May 09 06:05:32 2007 +0000
@@ -280,6 +280,8 @@
 		error = _("You must provide a group.");
 	else if (!account)
 		error = _("You must select an account.");
+	else if (!purple_account_is_connected(account))
+		error = _("The selected account is not online.");
 
 	if (error)
 	{
@@ -953,7 +955,7 @@
 
 	prompt = g_strdup_printf(_("Please enter the new name for %s"), name);
 
-	text = PURPLE_BLIST_NODE_IS_GROUP(node) ? _("Rename") : _("Alias");
+	text = PURPLE_BLIST_NODE_IS_GROUP(node) ? _("Rename") : _("Set Alias");
 	purple_request_input(node, text, prompt, _("Enter empty string to reset the name."),
 			name, FALSE, FALSE, NULL, text, G_CALLBACK(rename_blist_node),
 			_("Cancel"), NULL,
--- a/finch/gntconv.c	Mon May 07 01:58:53 2007 +0000
+++ b/finch/gntconv.c	Wed May 09 06:05:32 2007 +0000
@@ -396,17 +396,26 @@
 	gnt_menuitem_set_callback(item, toggle_timestamps_cb, ggc);
 
 	if (purple_conversation_get_type(ggc->active_conv) == PURPLE_CONV_TYPE_IM) {
-		item = gnt_menuitem_new(_("Send File"));
-		gnt_menu_add_item(GNT_MENU(sub), item);
-		gnt_menuitem_set_callback(item, send_file_cb, ggc);
+		PurpleAccount *account = purple_conversation_get_account(ggc->active_conv);
+		PurplePluginProtocolInfo *pinfo = account->gc ? PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl) : NULL;
+
+		if (pinfo && pinfo->get_info) {
+			item = gnt_menuitem_new(_("Get Info"));
+			gnt_menu_add_item(GNT_MENU(sub), item);
+			gnt_menuitem_set_callback(item, get_info_cb, ggc);
+		}
 
 		item = gnt_menuitem_new(_("Add Buddy Pounce..."));
 		gnt_menu_add_item(GNT_MENU(sub), item);
 		gnt_menuitem_set_callback(item, add_pounce_cb, ggc);
 
-		item = gnt_menuitem_new(_("Get Info"));
-		gnt_menu_add_item(GNT_MENU(sub), item);
-		gnt_menuitem_set_callback(item, get_info_cb, ggc);
+		if (pinfo && pinfo->send_file &&
+				(!pinfo->can_receive_file ||
+				 	pinfo->can_receive_file(account->gc, purple_conversation_get_name(ggc->active_conv)))) {
+			item = gnt_menuitem_new(_("Send File"));
+			gnt_menu_add_item(GNT_MENU(sub), item);
+			gnt_menuitem_set_callback(item, send_file_cb, ggc);
+		}
 
 		generate_send_to_menu(ggc);
 	}
@@ -789,7 +798,7 @@
 	PurpleCmdStatus status;
 
 	if (!g_ascii_strcasecmp(args[0], "version")) {
-		tmp = g_strdup_printf("me is using %s.", VERSION);
+		tmp = g_strdup_printf("me is using Finch v%s.", VERSION);
 		markup = g_markup_escape_text(tmp, -1);
 
 		status = purple_cmd_do_command(conv, tmp, markup, error);
--- a/finch/gntplugin.c	Mon May 07 01:58:53 2007 +0000
+++ b/finch/gntplugin.c	Wed May 09 06:05:32 2007 +0000
@@ -105,6 +105,20 @@
 {
 	PurplePlugin *plugin = current;
 	char *text;
+	GList *list = NULL, *iter = NULL;
+
+	/* If the selected plugin was unseen before, mark it as seen. But save the list
+	 * only when the plugin list is closed. So if the user enables a plugin, and it
+	 * crashes, it won't get marked as seen so the user can fix the bug and still
+	 * quickly find the plugin in the list.
+	 * I probably mean 'plugin developers' by 'users' here. */
+	list = g_object_get_data(G_OBJECT(widget), "seen-list");
+	if (list)
+		iter = g_list_find_custom(list, plugin->path, (GCompareFunc)strcmp);
+	if (!iter) {
+		list = g_list_prepend(list, g_strdup(plugin->path));
+		g_object_set_data(G_OBJECT(widget), "seen-list", list);
+	}
 
 	/* XXX: Use formatting and stuff */
 	gnt_text_view_clear(GNT_TEXT_VIEW(plugins.aboot));
@@ -121,6 +135,11 @@
 static void
 reset_plugin_window(GntWidget *window, gpointer null)
 {
+	GList *list = g_object_get_data(G_OBJECT(plugins.tree), "seen-list");
+	purple_prefs_set_path_list("/finch/plugins/seen", list);
+	g_list_foreach(list, (GFunc)g_free, NULL);
+	g_list_free(list);
+
 	plugins.window = NULL;
 	plugins.tree = NULL;
 	plugins.aboot = NULL;
@@ -214,6 +233,8 @@
 {
 	GntWidget *window, *tree, *box, *aboot, *button;
 	GList *iter;
+	GList *seen;
+
 	if (plugins.window)
 		return;
 
@@ -244,6 +265,7 @@
 	gnt_widget_set_size(aboot, 40, 20);
 	gnt_box_add_widget(GNT_BOX(box), aboot);
 
+	seen = purple_prefs_get_path_list("/finch/plugins/seen");
 	for (iter = purple_plugins_get_all(); iter; iter = iter->next)
 	{
 		PurplePlugin *plug = iter->data;
@@ -256,10 +278,13 @@
 		gnt_tree_add_choice(GNT_TREE(tree), plug,
 				gnt_tree_create_row(GNT_TREE(tree), plug->info->name), NULL, NULL);
 		gnt_tree_set_choice(GNT_TREE(tree), plug, purple_plugin_is_loaded(plug));
+		if (!g_list_find_custom(seen, plug->path, (GCompareFunc)strcmp))
+			gnt_tree_set_row_flags(GNT_TREE(tree), plug, GNT_TEXT_FLAG_BOLD);
 	}
 	gnt_tree_set_col_width(GNT_TREE(tree), 0, 30);
 	g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(plugin_toggled_cb), NULL);
 	g_signal_connect(G_OBJECT(tree), "selection_changed", G_CALLBACK(selection_changed), NULL);
+	g_object_set_data(G_OBJECT(tree), "seen-list", seen);
 
 	box = gnt_hbox_new(FALSE);
 	gnt_box_add_widget(GNT_BOX(window), box);
--- a/finch/gntprefs.c	Mon May 07 01:58:53 2007 +0000
+++ b/finch/gntprefs.c	Wed May 09 06:05:32 2007 +0000
@@ -39,6 +39,7 @@
 
 	purple_prefs_add_none("/finch/plugins");
 	purple_prefs_add_path_list("/finch/plugins/loaded", NULL);
+	purple_prefs_add_path_list("/finch/plugins/seen", NULL);
 
 	purple_prefs_add_none("/finch/conversations");
 	purple_prefs_add_bool("/finch/conversations/timestamps", TRUE);
--- a/finch/gntrequest.c	Mon May 07 01:58:53 2007 +0000
+++ b/finch/gntrequest.c	Wed May 09 06:05:32 2007 +0000
@@ -497,7 +497,9 @@
 				field->ui_data = combo;
 
 				all = purple_request_field_account_get_show_all(field);
-				def = purple_request_field_account_get_default_value(field);
+				def = purple_request_field_account_get_value(field);
+				if (!def)
+					def = purple_request_field_account_get_default_value(field);
 
 				if (all)
 					list = purple_accounts_get_all();
--- a/libpurple/log.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/log.c	Wed May 09 06:05:32 2007 +0000
@@ -778,7 +778,7 @@
 			if (tz_off != PURPLE_NO_TZ_OFF)
 				tm.tm_gmtoff = tz_off - tm.tm_gmtoff;
 
-			if (rest == NULL || (end = strchr(rest, '.')) == NULL || strchr(rest, ' ') != NULL)
+			if (stamp == 0 || rest == NULL || (end = strchr(rest, '.')) == NULL || strchr(rest, ' ') != NULL)
 			{
 				log = purple_log_new(type, name, account, NULL, stamp, NULL);
 			}
@@ -792,7 +792,7 @@
 #else
 			time_t stamp = purple_str_to_time(filename, FALSE, &tm, NULL, NULL);
 
-			log = purple_log_new(type, name, account, NULL, stamp, &tm);
+			log = purple_log_new(type, name, account, NULL, stamp, (stamp != 0) ?  &tm : NULL);
 #endif
 
 			log->logger = logger;
--- a/libpurple/prefs.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/prefs.c	Wed May 09 06:05:32 2007 +0000
@@ -937,7 +937,7 @@
 
 		if(pref->type != PURPLE_PREF_PATH_LIST) {
 			purple_debug_error("prefs",
-					"purple_prefs_set_path_list: %s not a string list pref\n",
+					"purple_prefs_set_path_list: %s not a path list pref\n",
 					name);
 			return;
 		}
--- a/libpurple/protocols/irc/irc.h	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/irc/irc.h	Wed May 09 06:05:32 2007 +0000
@@ -142,8 +142,8 @@
 void irc_msg_ping(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_pong(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_privmsg(struct irc_conn *irc, const char *name, const char *from, char **args);
+void irc_msg_quit(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_regonly(struct irc_conn *irc, const char *name, const char *from, char **args);
-void irc_msg_quit(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_time(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_unavailable(struct irc_conn *irc, const char *name, const char *from, char **args);
--- a/libpurple/protocols/irc/msgs.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/irc/msgs.c	Wed May 09 06:05:32 2007 +0000
@@ -1079,7 +1079,7 @@
 	if (!args || !args[1] || !args[2] || !gc)
 		return;
 
-	msg = g_strdup_printf(_("Cannot join %s:"), args[1]);
+	msg = g_strdup_printf(_("Cannot join %s: Registration is required."), args[1]);
 	purple_notify_error(gc, _("Cannot join channel"), msg, args[2]);
 	g_free(msg);
 }
--- a/libpurple/protocols/irc/parse.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/irc/parse.c	Wed May 09 06:05:32 2007 +0000
@@ -91,6 +91,7 @@
 	{ "442", "nc:", irc_msg_notinchan },	/* Not in channel		*/
 	{ "473", "nc:", irc_msg_inviteonly },	/* Tried to join invite-only	*/
 	{ "474", "nc:", irc_msg_banned },	/* Banned from channel		*/
+	{ "477", "nc:", irc_msg_regonly },	/* Registration Required	*/
 	{ "478", "nct:", irc_msg_banfull },	/* Banlist is full		*/
 	{ "482", "nc:", irc_msg_notop },	/* Need to be op to do that	*/
 	{ "501", "n:", irc_msg_badmode },	/* Unknown mode flag		*/
--- a/libpurple/protocols/jabber/buddy.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Wed May 09 06:05:32 2007 +0000
@@ -1793,7 +1793,7 @@
 
 	purple_request_input(gc, _("Enter a User Directory"), _("Enter a User Directory"),
 			_("Select a user directory to search"),
-			js->user_directories ? js->user_directories->data : "users.jabber.org",
+			js->user_directories ? js->user_directories->data : NULL,
 			FALSE, FALSE, NULL,
 			_("Search Directory"), PURPLE_CALLBACK(jabber_user_search_ok),
 			_("Cancel"), NULL,
--- a/libpurple/protocols/jabber/chat.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/jabber/chat.c	Wed May 09 06:05:32 2007 +0000
@@ -75,8 +75,6 @@
 
 	if (js->chat_servers)
 		g_hash_table_insert(defaults, "server", g_strdup(js->chat_servers->data));
-	else
-		g_hash_table_insert(defaults, "server", g_strdup("conference.jabber.org"));
 
 	if (chat_name != NULL) {
 		JabberID *jid = jabber_id_new(chat_name);
@@ -782,7 +780,7 @@
 
 	purple_request_input(gc, _("Enter a Conference Server"), _("Enter a Conference Server"),
 			_("Select a conference server to query"),
-			js->chat_servers ? js->chat_servers->data : "conference.jabber.org",
+			js->chat_servers ? js->chat_servers->data : NULL,
 			FALSE, FALSE, NULL,
 			_("Find Rooms"), PURPLE_CALLBACK(roomlist_ok_cb),
 			_("Cancel"), PURPLE_CALLBACK(roomlist_cancel_cb),
--- a/libpurple/protocols/jabber/google.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/jabber/google.c	Wed May 09 06:05:32 2007 +0000
@@ -398,7 +398,7 @@
 					*(p+1) == '<')) {
 				bold_count++;
 				in_bold = FALSE;
-			} else if (preceding_space && !in_bold) {
+			} else if (preceding_space && !in_bold && !g_unichar_isspace(*(p+1))) {
 				bold_count++;
 				in_bold = TRUE;
 			}
@@ -409,7 +409,7 @@
 					*(p+1) == '<')) {
 				italic_count++;
 				in_italic = FALSE;
-			} else if (preceding_space && !in_italic) {
+			} else if (preceding_space && !in_italic && !g_unichar_isspace(*(p+1))) {
 				italic_count++;
 				in_italic = TRUE;
 			}
@@ -445,7 +445,7 @@
 				str = g_string_append(str, "</b>");
 				in_bold = FALSE;
 				bold_count--;
-			} else if (preceding_space && bold_count > 1) {
+			} else if (preceding_space && bold_count > 1 && !g_unichar_isspace(*(p+1))) {
 				str = g_string_append(str, "<b>");
 				bold_count--;
 				in_bold = TRUE;
@@ -459,7 +459,7 @@
 				str = g_string_append(str, "</i>");
 				italic_count--;
 				in_italic = FALSE;
-			} else if (preceding_space && italic_count > 1) {
+			} else if (preceding_space && italic_count > 1 && !g_unichar_isspace(*(p+1))) {
 				str = g_string_append(str, "<i>");
 				italic_count--;
 				in_italic = TRUE;
--- a/libpurple/protocols/jabber/jabber.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed May 09 06:05:32 2007 +0000
@@ -557,7 +557,6 @@
 			g_free, (GDestroyNotify)jabber_buddy_free);
 	js->chats = g_hash_table_new_full(g_str_hash, g_str_equal,
 			g_free, (GDestroyNotify)jabber_chat_free);
-	js->chat_servers = g_list_append(NULL, g_strdup("conference.jabber.org"));
 	js->user = jabber_id_new(purple_account_get_username(account));
 	js->next_id = g_random_int();
 	js->write_buffer = purple_circ_buffer_new(512);
@@ -566,7 +565,12 @@
 		purple_connection_error(gc, _("Invalid XMPP ID"));
 		return;
 	}
-
+	
+	if (!js->user->domain || *(js->user->domain) == '\0') {
+		purple_connection_error(gc, _("Invalid XMPP ID. Domain must be set."));
+		return;
+	}
+	
 	if(!js->user->resource) {
 		char *me;
 		js->user->resource = g_strdup("Home");
--- a/libpurple/protocols/jabber/libxmpp.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Wed May 09 06:05:32 2007 +0000
@@ -191,7 +191,8 @@
         PurpleAccountUserSplit *split;
         PurpleAccountOption *option;
 
-        split = purple_account_user_split_new(_("Server"), "jabber.org", '@');
+	/* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
+        split = purple_account_user_split_new(_("Domain"), "gmail.com", '@');
         prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
 
         split = purple_account_user_split_new(_("Resource"), "Home", '/');
--- a/libpurple/protocols/oscar/oscar.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Wed May 09 06:05:32 2007 +0000
@@ -6490,15 +6490,18 @@
 gboolean
 oscar_offline_message(const PurpleBuddy *buddy)
 {
-	OscarData *od;
+	OscarData *od = NULL;
 	PurpleAccount *account;
-	PurpleConnection *gc;
+	PurpleConnection *gc = NULL;
 
 	account = purple_buddy_get_account(buddy);
-	gc = purple_account_get_connection(account);
-	od = (OscarData *)gc->proto_data;
-
-	return (od->icq && aim_sn_is_icq(purple_account_get_username(account)));
+	if (account != NULL) {
+		gc = purple_account_get_connection(account);
+		if (gc != NULL)
+			od = (OscarData *)gc->proto_data;
+	}
+
+	return (od != NULL && od->icq && aim_sn_is_icq(purple_account_get_username(account)));
 }
 
 /* TODO: Find somewhere to put this instead of including it in a bunch of places.
--- a/libpurple/prpl.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/prpl.c	Wed May 09 06:05:32 2007 +0000
@@ -128,7 +128,7 @@
 purple_prpl_got_user_status(PurpleAccount *account, const char *name,
 		const char *status_id, ...)
 {
-	GSList *list;
+	GSList *list, *l;
 	PurpleBuddy *buddy;
 	PurplePresence *presence;
 	PurpleStatus *status;
@@ -140,24 +140,30 @@
 	g_return_if_fail(status_id != NULL);
 	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
 
-	if ((buddy = purple_find_buddy(account, name)) == NULL)
+	if((list = purple_find_buddies(account, name)) == NULL)
 		return;
 
-	presence = purple_buddy_get_presence(buddy);
-	status   = purple_presence_get_status(presence, status_id);
+	for(l = list; l != NULL; l = l->next) {
+		buddy = l->data;
 
-	g_return_if_fail(status != NULL);
+		presence = purple_buddy_get_presence(buddy);
+		status   = purple_presence_get_status(presence, status_id);
 
-	old_status = purple_presence_get_active_status(presence);
+		if(NULL == status)
+			continue;
 
-	va_start(args, status_id);
-	purple_status_set_active_with_attrs(status, TRUE, args);
-	va_end(args);
+		old_status = purple_presence_get_active_status(presence);
 
-	list = purple_find_buddies(account, name);
-	g_slist_foreach(list, (GFunc)purple_blist_update_buddy_status, old_status);
+		va_start(args, status_id);
+		purple_status_set_active_with_attrs(status, TRUE, args);
+		va_end(args);
+
+		purple_blist_update_buddy_status(buddy, old_status);
+	}
+
 	g_slist_free(list);
 
+	/* we get to re-use the last status we found */
 	if (!purple_status_is_online(status))
 		serv_got_typing_stopped(purple_account_get_connection(account), name);
 }
@@ -165,6 +171,7 @@
 void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *name,
 					const char *status_id)
 {
+	GSList *list, *l;
 	PurpleBuddy *buddy;
 	PurplePresence *presence;
 	PurpleStatus *status;
@@ -174,14 +181,22 @@
 	g_return_if_fail(status_id != NULL);
 	g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account));
 
-	if ((buddy = purple_find_buddy(account, name)) == NULL)
+	if((list = purple_find_buddies(account, name)) == NULL)
 		return;
 
-	presence = purple_buddy_get_presence(buddy);
-	status   = purple_presence_get_status(presence, status_id);
+	for(l = list; l != NULL; l = l->next) {
+		buddy = l->data;
+
+		presence = purple_buddy_get_presence(buddy);
+		status   = purple_presence_get_status(presence, status_id);
 
-	g_return_if_fail(status != NULL);
-	purple_status_set_active(status, FALSE);
+		if(NULL == status)
+			continue;
+
+		purple_status_set_active(status, FALSE);
+	}
+
+	g_slist_free(list);
 }
 
 static void
--- a/libpurple/status.c	Mon May 07 01:58:53 2007 +0000
+++ b/libpurple/status.c	Wed May 09 06:05:32 2007 +0000
@@ -134,8 +134,6 @@
 	10      /* Offline messageable      */
 };
 
-static GHashTable *buddy_presences = NULL;
-
 #define SCORE_IDLE      8
 #define SCORE_IDLE_TIME 9
 #define SCORE_OFFLINE_MESSAGE 10
@@ -1118,32 +1116,17 @@
 purple_presence_new_for_buddy(PurpleBuddy *buddy)
 {
 	PurplePresence *presence;
-	PurpleStatusBuddyKey *key;
 	PurpleAccount *account;
 
 	g_return_val_if_fail(buddy != NULL, NULL);
 	account = buddy->account;
 
-	key = g_new0(PurpleStatusBuddyKey, 1);
-	key->account = buddy->account;
-	key->name    = g_strdup(buddy->name);
-
-	presence = g_hash_table_lookup(buddy_presences, key);
-	if (presence == NULL)
-	{
-		presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_BUDDY);
+	presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_BUDDY);
 
-		presence->u.buddy.name    = g_strdup(buddy->name);
-		presence->u.buddy.account = buddy->account;
-		presence->statuses = purple_prpl_get_statuses(buddy->account, presence);
+	presence->u.buddy.name    = g_strdup(buddy->name);
+	presence->u.buddy.account = buddy->account;
+	presence->statuses = purple_prpl_get_statuses(buddy->account, presence);
 
-		g_hash_table_insert(buddy_presences, key, presence);
-	}
-	else
-	{
-		g_free(key->name);
-		g_free(key);
-	}
 	presence->u.buddy.buddy = buddy;
 
 	return presence;
@@ -1156,13 +1139,6 @@
 
 	if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_BUDDY)
 	{
-		PurpleStatusBuddyKey key;
-
-		key.account = presence->u.buddy.account;
-		key.name    = presence->u.buddy.name;
-
-		g_hash_table_remove(buddy_presences, &key);
-
 		g_free(presence->u.buddy.name);
 	}
 	else if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_CONV)
@@ -1639,41 +1615,6 @@
 	primitive_scores[index] = GPOINTER_TO_INT(value);
 }
 
-static guint
-purple_buddy_presences_hash(gconstpointer key)
-{
-	const PurpleStatusBuddyKey *me = key;
-	guint ret;
-	char *str;
-
-	str = g_strdup_printf("%p%s", me->account, me->name);
-	ret = g_str_hash(str);
-	g_free(str);
-
-	return ret;
-}
-
-static gboolean
-purple_buddy_presences_equal(gconstpointer a, gconstpointer b)
-{
-	PurpleStatusBuddyKey *key_a = (PurpleStatusBuddyKey *)a;
-	PurpleStatusBuddyKey *key_b = (PurpleStatusBuddyKey *)b;
-
-	if(key_a->account == key_b->account &&
-			!strcmp(key_a->name, key_b->name))
-		return TRUE;
-	else
-		return FALSE;
-}
-
-static void
-purple_buddy_presences_key_free(gpointer a)
-{
-	PurpleStatusBuddyKey *key = (PurpleStatusBuddyKey *)a;
-	g_free(key->name);
-	g_free(key);
-}
-
 void *
 purple_status_get_handle(void) {
 	static int handle;
@@ -1725,19 +1666,9 @@
 	purple_prefs_connect_callback(handle, "/purple/status/scores/offline_msg",
 			score_pref_changed_cb,
 			GINT_TO_POINTER(SCORE_OFFLINE_MESSAGE));
-
-	buddy_presences = g_hash_table_new_full(purple_buddy_presences_hash,
-											purple_buddy_presences_equal,
-											purple_buddy_presences_key_free, NULL);
 }
 
 void
 purple_status_uninit(void)
 {
-	if (buddy_presences != NULL)
-	{
-		g_hash_table_destroy(buddy_presences);
-
-		buddy_presences = NULL;
-	}
 }
--- a/pidgin/gtkconv.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkconv.c	Wed May 09 06:05:32 2007 +0000
@@ -380,7 +380,7 @@
 	PurpleCmdStatus status;
 
 	if (!g_ascii_strcasecmp(args[0], "version")) {
-		tmp = g_strdup_printf("me is using %s v%s.", PIDGIN_NAME, VERSION);
+		tmp = g_strdup_printf("me is using %s v%s.", "Pidgin", VERSION);
 		markup = g_markup_escape_text(tmp, -1);
 
 		status = purple_cmd_do_command(conv, tmp, markup, error);
@@ -5007,6 +5007,8 @@
 	char *bracket;
 	int tag_count = 0;
 	gboolean is_rtl_message = FALSE;
+	GtkSmileyTree *tree = NULL;
+	GHashTable *smiley_data = NULL;
 
 	g_return_if_fail(conv != NULL);
 	gtkconv = PIDGIN_CONVERSATION(conv);
@@ -5150,6 +5152,17 @@
 		gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
 	}
 
+	if (!(flags & PURPLE_MESSAGE_RECV))
+	{
+		/* Temporarily revert to the original smiley-data to avoid showing up
+		 * custom smileys of the buddy when sending message
+		 */
+		tree = GTK_IMHTML(gtkconv->imhtml)->default_smilies;
+		GTK_IMHTML(gtkconv->imhtml)->default_smilies =
+								GTK_IMHTML(gtkconv->entry)->default_smilies;
+		smiley_data = GTK_IMHTML(gtkconv->imhtml)->smiley_data;
+		GTK_IMHTML(gtkconv->imhtml)->smiley_data = GTK_IMHTML(gtkconv->entry)->smiley_data;
+	}
 
 	/* TODO: These colors should not be hardcoded so log.c can use them */
 	if (flags & PURPLE_MESSAGE_RAW) {
@@ -5181,25 +5194,11 @@
 		 * escaped entities making the string longer */
 		int tag_start_offset = alias ? (strlen(alias_escaped) - strlen(alias)) : 0;
 		int tag_end_offset = 0;
-		GtkSmileyTree *tree = NULL;
-		GHashTable *smiley_data = NULL;
 
 		/* Enforce direction on alias */
 		if (is_rtl_message)
 			str_embed_direction_chars(&alias_escaped);
 
-		if (flags & PURPLE_MESSAGE_SEND)
-		{
-			/* Temporarily revert to the original smiley-data to avoid showing up
-			 * custom smileys of the buddy when sending message
-			 */
-			tree = GTK_IMHTML(gtkconv->imhtml)->default_smilies;
-			GTK_IMHTML(gtkconv->imhtml)->default_smilies =
-									GTK_IMHTML(gtkconv->entry)->default_smilies;
-			smiley_data = GTK_IMHTML(gtkconv->imhtml)->smiley_data;
-			GTK_IMHTML(gtkconv->imhtml)->smiley_data = GTK_IMHTML(gtkconv->entry)->smiley_data;
-		}
-
 		if (flags & PURPLE_MESSAGE_WHISPER) {
 			str = g_malloc(1024);
 
@@ -5341,13 +5340,6 @@
 		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml),
 							 with_font_tag, gtk_font_options | gtk_font_options_all);
 
-		if (flags & PURPLE_MESSAGE_SEND)
-		{
-			/* Restore the smiley-data */
-			GTK_IMHTML(gtkconv->imhtml)->default_smilies = tree;
-			GTK_IMHTML(gtkconv->imhtml)->smiley_data = smiley_data;
-		}
-
 		g_free(with_font_tag);
 		g_free(new_message);
 	}
@@ -5373,6 +5365,13 @@
 		gtkconv_set_unseen(gtkconv, unseen);
 	}
 
+	if (!(flags & PURPLE_MESSAGE_RECV))
+	{
+		/* Restore the smiley-data */
+		GTK_IMHTML(gtkconv->imhtml)->default_smilies = tree;
+		GTK_IMHTML(gtkconv->imhtml)->smiley_data = smiley_data;
+	}
+
 	purple_signal_emit(pidgin_conversations_get_handle(),
 		(type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"),
 		account, name, displaying, conv, flags);
@@ -5636,15 +5635,25 @@
 				icon, smiley->icon, smiley->smile);
 #endif
 		if (icon) {
+			GList *wids;
 			gtk_widget_show(icon);
 
 			anchor = GTK_TEXT_CHILD_ANCHOR(current->data);
+			wids = gtk_text_child_anchor_get_widgets(anchor);
 
 			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", purple_unescape_html(smiley->smile), g_free);
 			g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley->smile), g_free);
 
-			if (smiley->imhtml)
-				gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor);
+			if (smiley->imhtml) {
+				if (wids) {
+					GList *children = gtk_container_get_children(GTK_CONTAINER(wids->data));
+					g_list_foreach(children, (GFunc)gtk_widget_destroy, NULL);
+					g_list_free(children);
+					gtk_container_add(GTK_CONTAINER(wids->data), icon);
+				} else
+					gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor);
+			}
+			g_list_free(wids);
 		}
 
 	}
--- a/pidgin/gtkdocklet-x11.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkdocklet-x11.c	Wed May 09 06:05:32 2007 +0000
@@ -42,7 +42,6 @@
 static GtkTooltips *tooltips = NULL;
 static GdkPixbuf *blank_icon = NULL;
 static int embed_timeout = 0;
-static DockletStatus icon_status = 0;
 static int docklet_height = 0;
 
 /* protos */
@@ -90,39 +89,38 @@
 }
 
 static void
-docklet_x11_update_icon(DockletStatus icon)
+docklet_x11_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
 {
 	const gchar *icon_name = NULL;
 
 	g_return_if_fail(image != NULL);
 
-	switch (icon) {
-		case DOCKLET_STATUS_OFFLINE:
+	switch (status) {
+		case PURPLE_STATUS_OFFLINE:
 			icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
 			break;
-		case DOCKLET_STATUS_CONNECTING:
-			icon_name = PIDGIN_STOCK_TRAY_CONNECT;
+		case PURPLE_STATUS_AWAY:
+			icon_name = PIDGIN_STOCK_TRAY_AWAY;
+			break;
+		case PURPLE_STATUS_UNAVAILABLE:
+			icon_name = PIDGIN_STOCK_TRAY_BUSY;
 			break;
-		case DOCKLET_STATUS_AVAILABLE:
+		case PURPLE_STATUS_EXTENDED_AWAY:
+			icon_name = PIDGIN_STOCK_TRAY_XA;
+			break;
+		case PURPLE_STATUS_INVISIBLE:
+			icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
+			break;
+		default:
 			icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
 			break;
-		case DOCKLET_STATUS_PENDING:
-			icon_name = PIDGIN_STOCK_TRAY_PENDING;
-			break;
-		case DOCKLET_STATUS_AWAY:
-			icon_name = PIDGIN_STOCK_TRAY_AWAY;
-			break;
-		case DOCKLET_STATUS_BUSY:
-			icon_name = PIDGIN_STOCK_TRAY_BUSY;
-			break;
-		case DOCKLET_STATUS_XA:
-			icon_name = PIDGIN_STOCK_TRAY_XA;
-			break;
-		case DOCKLET_STATUS_INVISIBLE:
-			icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
-			break;
 	}
 
+	if (pending)
+		icon_name = PIDGIN_STOCK_TRAY_PENDING;
+	if (connecting)
+		icon_name = PIDGIN_STOCK_TRAY_CONNECT;
+
 	if(icon_name) {
 		int icon_size;
 		if (docklet_height < 22)
@@ -132,7 +130,6 @@
 
 		gtk_image_set_from_stock(GTK_IMAGE(image), icon_name, icon_size);
 	}
-	icon_status = icon;
 }
 
 static void
@@ -141,7 +138,7 @@
 	if (docklet_height == widget->allocation.height)
 		return;
 	docklet_height = widget->allocation.height;
-	docklet_x11_update_icon(icon_status);
+	pidgin_docklet_update_icon();
 }
 
 static void
--- a/pidgin/gtkdocklet.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkdocklet.c	Wed May 09 06:05:32 2007 +0000
@@ -49,7 +49,9 @@
 
 /* globals */
 static struct docklet_ui_ops *ui_ops = NULL;
-static DockletStatus status = DOCKLET_STATUS_OFFLINE;
+static PurpleStatusPrimitive status = PURPLE_STATUS_OFFLINE;
+static gboolean pending = FALSE;
+static gboolean connecting = FALSE;
 static gboolean enable_join_chat = FALSE;
 static guint docklet_blinking_timer = 0;
 static gboolean visible = FALSE;
@@ -66,21 +68,17 @@
 
 	blinked = !blinked;
 
-	switch (status) {
-		case DOCKLET_STATUS_PENDING:
-			if (blinked) {
-				if (ui_ops && ui_ops->blank_icon)
-					ui_ops->blank_icon();
-			} else {
-				if (ui_ops && ui_ops->update_icon)
-					ui_ops->update_icon(status);
-			}
-			ret = TRUE; /* keep blinking */
-			break;
-		default:
-			docklet_blinking_timer = 0;
-			blinked = FALSE;
-			break;
+	if(pending && !connecting) {
+		if (blinked) {
+			if (ui_ops && ui_ops->blank_icon)
+				ui_ops->blank_icon();
+		} else {
+			pidgin_docklet_update_icon();
+		}
+		ret = TRUE; /* keep blinking */
+	} else {
+		docklet_blinking_timer = 0;
+		blinked = FALSE;
 	}
 
 	return ret;
@@ -114,9 +112,8 @@
 	GList *convs, *l;
 	int count;
 	PurpleSavedStatus *saved_status;
-	PurpleStatusPrimitive prim;
-	DockletStatus newstatus = DOCKLET_STATUS_OFFLINE;
-	gboolean pending = FALSE, connecting = FALSE;
+	PurpleStatusPrimitive newstatus = PURPLE_STATUS_OFFLINE;
+	gboolean newpending = FALSE, newconnecting = FALSE;
 
 	/* get the current savedstatus */
 	saved_status = purple_savedstatus_get_current();
@@ -141,7 +138,7 @@
 	}
 
 	if (convs != NULL) {
-		pending = TRUE;
+		newpending = TRUE;
 
 		/* set tooltip if messages are pending */
 		if (ui_ops->set_tooltip) {
@@ -190,38 +187,22 @@
 
 		account_status = purple_account_get_active_status(account);
 		if (purple_account_is_connecting(account))
-			connecting = TRUE;
+			newconnecting = TRUE;
 	}
 
-	prim = purple_savedstatus_get_type(saved_status);
-	if (pending)
-		newstatus = DOCKLET_STATUS_PENDING;
-	else if (connecting)
-		newstatus = DOCKLET_STATUS_CONNECTING;
-	else if (prim == PURPLE_STATUS_UNAVAILABLE)
-		newstatus = DOCKLET_STATUS_BUSY;
-	else if (prim == PURPLE_STATUS_AWAY)
-		newstatus = DOCKLET_STATUS_AWAY;
-	else if (prim == PURPLE_STATUS_EXTENDED_AWAY)
-		newstatus = DOCKLET_STATUS_XA;
-	else if (prim == PURPLE_STATUS_OFFLINE)
-		newstatus = DOCKLET_STATUS_OFFLINE;
-	else if (prim == PURPLE_STATUS_INVISIBLE)
-		newstatus = DOCKLET_STATUS_INVISIBLE;
-	else
-		newstatus = DOCKLET_STATUS_AVAILABLE;
+	newstatus = purple_savedstatus_get_type(saved_status);
 
 	/* update the icon if we changed status */
-	if (status != newstatus) {
+	if (status != newstatus || pending!=newpending || connecting!=newconnecting) {
 		status = newstatus;
+		pending = newpending;
+		connecting = newconnecting;
 
-		if (ui_ops && ui_ops->update_icon)
-			ui_ops->update_icon(status);
+		pidgin_docklet_update_icon();
 
 		/* and schedule the blinker function if messages are pending */
-		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink") &&
-		    status == DOCKLET_STATUS_PENDING
-		    && docklet_blinking_timer == 0) {
+		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")
+			&& pending && !connecting && docklet_blinking_timer == 0) {
 			docklet_blinking_timer = g_timeout_add(500, docklet_blink_icon, NULL);
 		}
 	}
@@ -510,7 +491,7 @@
 
 	menuitem = gtk_menu_item_new_with_label(_("Unread Messages"));
 
-	if (status == DOCKLET_STATUS_PENDING) {
+	if (pending) {
 		GtkWidget *submenu = gtk_menu_new();
 		GList *l = get_pending_list(0);
 		if (l == NULL) {
@@ -530,7 +511,7 @@
 	pidgin_separator(menu);
 
 	menuitem = pidgin_new_item_from_stock(menu, _("New Message..."), PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, G_CALLBACK(pidgin_dialogs_im), NULL, 0, 0, NULL);
-	if (status == DOCKLET_STATUS_OFFLINE)
+	if (status == PURPLE_STATUS_OFFLINE)
 		gtk_widget_set_sensitive(menuitem, FALSE);
 
 	menuitem = docklet_status_submenu();
@@ -558,10 +539,6 @@
 
 	pidgin_separator(menu);
 
-	/* TODO: need a submenu to change status, this needs to "link"
-	 * to the status in the buddy list gtkstatusbox
-	 */
-
 	pidgin_new_item_from_stock(menu, _("Quit"), GTK_STOCK_QUIT, G_CALLBACK(purple_core_quit), NULL, 0, 0, NULL);
 
 #ifdef _WIN32
@@ -578,11 +555,18 @@
  * public api for ui_ops
  **************************************************************************/
 void
+pidgin_docklet_update_icon()
+{
+	if (ui_ops && ui_ops->update_icon)
+		ui_ops->update_icon(status, connecting, pending);
+}
+
+void
 pidgin_docklet_clicked(int button_type)
 {
 	switch (button_type) {
 		case 1:
-			if (status == DOCKLET_STATUS_PENDING) {
+			if (pending) {
 				GList *l = get_pending_list(1);
 				if (l != NULL) {
 					purple_conversation_present((PurpleConversation *)l->data);
@@ -608,8 +592,7 @@
 	}
 	visible = TRUE;
 	docklet_update_status();
-	if (ui_ops && ui_ops->update_icon)
-		ui_ops->update_icon(status);
+	pidgin_docklet_update_icon();
 }
 
 void
@@ -625,7 +608,7 @@
 			docklet_blinking_timer = 0;
 		}
 		visible = FALSE;
-		status = DOCKLET_STATUS_OFFLINE;
+		status = PURPLE_STATUS_OFFLINE;
 	}
 }
 
--- a/pidgin/gtkdocklet.h	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkdocklet.h	Wed May 09 06:05:32 2007 +0000
@@ -25,23 +25,13 @@
 #ifndef _GTKDOCKLET_H_
 #define _GTKDOCKLET_H_
 
-typedef enum
-{
-	DOCKLET_STATUS_OFFLINE,
-	DOCKLET_STATUS_AVAILABLE,
-	DOCKLET_STATUS_INVISIBLE,
-	DOCKLET_STATUS_PENDING,
-	DOCKLET_STATUS_AWAY,
-	DOCKLET_STATUS_BUSY,
-	DOCKLET_STATUS_XA,
-	DOCKLET_STATUS_CONNECTING
-} DockletStatus;
+#include "status.h"
 
 struct docklet_ui_ops
 {
 	void (*create)(void);
 	void (*destroy)(void);
-	void (*update_icon)(DockletStatus);
+	void (*update_icon)(PurpleStatusPrimitive, gboolean, gboolean);
 	void (*blank_icon)(void);
 	void (*set_tooltip)(gchar *);
 	GtkMenuPositionFunc position_menu;
@@ -49,6 +39,7 @@
 
 
 /* functions in gtkdocklet.c */
+void pidgin_docklet_update_icon(void);
 void pidgin_docklet_clicked(int);
 void pidgin_docklet_embedded(void);
 void pidgin_docklet_remove(void);
--- a/pidgin/gtkimhtml.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkimhtml.c	Wed May 09 06:05:32 2007 +0000
@@ -1880,18 +1880,8 @@
 }
 
 static GdkPixbufAnimation *
-gtk_smiley_tree_image (GtkIMHtml     *imhtml,
-		       const gchar   *sml,
-		       const gchar   *text)
+gtk_smiley_get_image(GtkIMHtmlSmiley *smiley)
 {
-
-	GtkIMHtmlSmiley *smiley;
-
-	smiley = gtk_imhtml_smiley_get(imhtml,sml,text);
-
-	if (!smiley)
-		return NULL;
-
 	if (!smiley->icon && smiley->file) {
 		smiley->icon = gdk_pixbuf_animation_new_from_file(smiley->file, NULL);
 	} else if (!smiley->icon && smiley->loader) {
@@ -1903,6 +1893,21 @@
 	return smiley->icon;
 }
 
+static GdkPixbufAnimation *
+gtk_smiley_tree_image (GtkIMHtml     *imhtml,
+		       const gchar   *sml,
+		       const gchar   *text)
+{
+	GtkIMHtmlSmiley *smiley;
+
+	smiley = gtk_imhtml_smiley_get(imhtml,sml,text);
+
+	if (!smiley)
+		return NULL;
+
+	return gtk_smiley_get_image(smiley);
+}
+
 #define VALID_TAG(x)	if (!g_ascii_strncasecmp (string, x ">", strlen (x ">"))) {	\
 				*tag = g_strndup (string, strlen (x));		\
 				*len = strlen (x) + 1;				\
@@ -3371,6 +3376,29 @@
 		return FALSE; /* Let clicks go through if we didn't catch anything */
 
 }
+
+static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
+{
+	GdkPixbufAnimation *anim = NULL;
+	GdkPixbuf *pix = NULL;
+	GtkIMHtmlScalable *image = NULL;
+	gboolean ret;
+	
+	if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
+		return FALSE;
+
+	anim = gtk_smiley_get_image(smiley);
+	if (!anim)
+		return FALSE;
+
+	pix = gdk_pixbuf_animation_get_static_image(anim);
+	image = gtk_imhtml_image_new(pix, NULL, 0);
+	ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image);
+	g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_image_free);
+	g_object_unref(G_OBJECT(pix));
+	return ret;
+}
+
 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
 {
 	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
@@ -4386,9 +4414,10 @@
 	GdkPixbuf *pixbuf = NULL;
 	GdkPixbufAnimation *annipixbuf = NULL;
 	GtkWidget *icon = NULL;
-	GtkTextChildAnchor *anchor;
+	GtkTextChildAnchor *anchor = NULL;
 	char *unescaped = purple_unescape_html(smiley);
 	GtkIMHtmlSmiley *imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped);
+	GtkWidget *ebox = NULL;
 
 	if (imhtml->format_functions & GTK_IMHTML_SMILEY) {
 		annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped);
@@ -4405,6 +4434,7 @@
 					if (anim) {
 						GdkPixbuf *pb = gdk_pixbuf_animation_get_static_image(anim);
 						gtk_image_set_from_pixbuf(image, pb);
+						g_object_unref(G_OBJECT(pb));
 					}
 				} else {
  					imhtml->num_animations++;
@@ -4415,6 +4445,12 @@
 		}
 	}
 
+	if (imhtml_smiley->flags & GTK_IMHTML_SMILEY_CUSTOM) {
+		ebox = gtk_event_box_new();
+		gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
+		gtk_widget_show(ebox);
+	}
+
 	if (icon) {
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free);
@@ -4427,14 +4463,26 @@
 		g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL);
 
 		gtk_widget_show(icon);
-		gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor);
+		if (ebox)
+			gtk_container_add(GTK_CONTAINER(ebox), icon);
+		gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor);
 	} else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) {
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor);
+		if (ebox) {
+			GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU);
+			gtk_container_add(GTK_CONTAINER(ebox), img);
+			gtk_widget_show(img);
+			gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox, anchor);
+		}
 	} else {
 		gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1);
 	}
 
+	if (ebox) {
+		g_signal_connect(G_OBJECT(ebox), "event", G_CALLBACK(gtk_imhtml_smiley_clicked), imhtml_smiley);
+	}
+
 	g_free(unescaped);
 }
 
--- a/pidgin/gtkmain.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkmain.c	Wed May 09 06:05:32 2007 +0000
@@ -476,6 +476,9 @@
 	debug_enabled = FALSE;
 #endif
 
+	/* This is the first Glib function call. Make sure to initialize GThread bfeore then */
+	g_thread_init(NULL);
+	
 #ifdef PURPLE_FATAL_ASSERTS
 	/* Make g_return_... functions fatal. */
 	g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
--- a/pidgin/gtkutils.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/gtkutils.c	Wed May 09 06:05:32 2007 +0000
@@ -442,6 +442,14 @@
 	item = gtk_menu_get_active(GTK_MENU(menu));
 
 	protocol = g_object_get_data(G_OBJECT(item), "protocol");
+
+	if (!strcmp(protocol, "prpl-fake"))
+	{
+		guint index = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(item), "real_index"));
+		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), index);
+		return;
+	}
+
 	user_data = (g_object_get_data(G_OBJECT(optmenu), "user_data"));
 
 	if (cb != NULL)
@@ -449,19 +457,53 @@
 															user_data);
 }
 
+static GtkWidget *
+pidgin_protocol_option_menu_item(GtkWidget *menu, GtkSizeGroup *sg, GtkWidget *image,
+                                  const char *name, const char *id)
+{
+	GtkWidget *item;
+	GtkWidget *hbox;
+	GtkWidget *label;
+
+	/* Create the item. */
+	item = gtk_menu_item_new();
+
+	/* Create the hbox. */
+	hbox = gtk_hbox_new(FALSE, 4);
+	gtk_container_add(GTK_CONTAINER(item), hbox);
+	gtk_widget_show(hbox);
+
+	gtk_size_group_add_widget(sg, image);
+
+	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+	gtk_widget_show(image);
+
+	/* Create the label. */
+	label = gtk_label_new(name);
+	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+	gtk_widget_show(label);
+
+	g_object_set_data(G_OBJECT(item), "protocol", (gpointer)id);
+
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+	gtk_widget_show(item);
+	pidgin_set_accessible_label (item, label);
+
+	return item;
+}
+
 GtkWidget *
 pidgin_protocol_option_menu_new(const char *id, GCallback cb,
 								  gpointer user_data)
 {
 	PurplePluginProtocolInfo *prpl_info;
 	PurplePlugin *plugin;
-	GtkWidget *hbox;
-	GtkWidget *label;
 	GtkWidget *optmenu;
 	GtkWidget *menu;
-	GtkWidget *item;
+	GdkPixbuf *pixbuf;
 	GtkWidget *image;
-	GdkPixbuf *pixbuf;
 	GList *p;
 	GtkSizeGroup *sg;
 	char *filename;
@@ -486,14 +528,6 @@
 		plugin = (PurplePlugin *)p->data;
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 
-		/* Create the item. */
-		item = gtk_menu_item_new();
-
-		/* Create the hbox. */
-		hbox = gtk_hbox_new(FALSE, 4);
-		gtk_container_add(GTK_CONTAINER(item), hbox);
-		gtk_widget_show(hbox);
-
 		/* Load the image. */
 		proto_name = prpl_info->list_icon(NULL, NULL);
 		g_snprintf(buf, sizeof(buf), "%s.png", proto_name);
@@ -503,34 +537,31 @@
 		pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
 		g_free(filename);
 
-		if (pixbuf) {
+		if (pixbuf)
 			image = gtk_image_new_from_pixbuf(pixbuf);
-
-			g_object_unref(G_OBJECT(pixbuf));
-		}
 		else
 			image = gtk_image_new();
 
-		gtk_size_group_add_widget(sg, image);
-
-		gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-		gtk_widget_show(image);
-
-		/* Create the label. */
-		label = gtk_label_new(plugin->info->name);
-		gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
-		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-		gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-		gtk_widget_show(label);
-
-		g_object_set_data(G_OBJECT(item), "protocol", plugin->info->id);
-
-		gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-		gtk_widget_show(item);
-		pidgin_set_accessible_label (item, label);
+		pidgin_protocol_option_menu_item(menu, sg, image, plugin->info->name, plugin->info->id);
 
 		if (id != NULL && !strcmp(plugin->info->id, id))
 			selected_index = i;
+
+		if (!strcmp(plugin->info->id, "prpl-jabber"))
+		{
+			GtkWidget *gtalk_item;
+			if (pixbuf)
+				image = gtk_image_new_from_pixbuf(pixbuf);
+			else
+				image = gtk_image_new();
+
+			gtalk_item = pidgin_protocol_option_menu_item(menu, sg, image, _("Google Talk (XMPP)"), "prpl-fake");
+			g_object_set_data(G_OBJECT(gtalk_item), "real_index", GUINT_TO_POINTER(i));
+			i++;
+		}
+
+		if (pixbuf)
+			g_object_unref(G_OBJECT(pixbuf));
 	}
 
 	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
--- a/pidgin/pidgin.h	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/pidgin.h	Wed May 09 06:05:32 2007 +0000
@@ -45,7 +45,8 @@
 /* change this only when we have a sane upgrade path for old prefs */
 #define PIDGIN_PREFS_ROOT "/pidgin"
 
-/* Translators may want to transliterate the name. */
+/* Translators may want to transliterate the name.
+ It is not to be translated. */
 #define PIDGIN_NAME _("Pidgin")
 
 #ifndef _WIN32
--- a/pidgin/win32/gtkdocklet-win32.c	Mon May 07 01:58:53 2007 +0000
+++ b/pidgin/win32/gtkdocklet-win32.c	Wed May 09 06:05:32 2007 +0000
@@ -45,7 +45,8 @@
  *  LOCALS
  */
 static HWND systray_hwnd = NULL;
-static HICON cached_icons[DOCKLET_STATUS_CONNECTING + 1];
+/* additional two cached_icons entries for pending and connecting icons */
+static HICON cached_icons[PURPLE_STATUS_NUM_PRIMITIVES + 2];
 static GtkWidget *image = NULL;
 static NOTIFYICONDATA _nicon_data;
 
@@ -466,46 +467,56 @@
 	Shell_NotifyIcon(NIM_DELETE, &_nicon_data);
 }
 
-static void winpidgin_tray_update_icon(DockletStatus icon) {
+static void winpidgin_tray_update_icon(PurpleStatusPrimitive status,
+		gboolean connecting, gboolean pending) {
+
+	int icon_index;
+	g_return_if_fail(image != NULL);
 
-	g_return_if_fail(image != NULL);
-	g_return_if_fail(icon < (sizeof(cached_icons) / sizeof(HICON)));
+	if(connecting)
+		icon_index = PURPLE_STATUS_NUM_PRIMITIVES;
+	else if(pending)
+		icon_index = PURPLE_STATUS_NUM_PRIMITIVES+1;
+	else
+		icon_index = status;
+
+	g_return_if_fail(icon_index < (sizeof(cached_icons) / sizeof(HICON)));
 
 	/* Look up and cache the HICON if we don't already have it */
-	if (cached_icons[icon] == NULL) {
+	if (cached_icons[icon_index] == NULL) {
 		const gchar *icon_name = NULL;
-		switch (icon) {
-		case DOCKLET_STATUS_OFFLINE:
-			icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
-			break;
-		case DOCKLET_STATUS_CONNECTING:
-			icon_name = PIDGIN_STOCK_TRAY_CONNECT;
-			break;
-		case DOCKLET_STATUS_AVAILABLE:
-			icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
-			break;
-		case DOCKLET_STATUS_PENDING:
-			icon_name = PIDGIN_STOCK_TRAY_PENDING;
-			break;
-		case DOCKLET_STATUS_AWAY:
-			icon_name = PIDGIN_STOCK_TRAY_AWAY;
-			break;
-		case DOCKLET_STATUS_BUSY:
-			icon_name = PIDGIN_STOCK_TRAY_BUSY;
-			break;
-		case DOCKLET_STATUS_XA:
-			icon_name = PIDGIN_STOCK_TRAY_XA;
-			break;
-		case DOCKLET_STATUS_INVISIBLE:
-			icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
+		switch (status) {
+			case PURPLE_STATUS_OFFLINE:
+				icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
+				break;
+			case PURPLE_STATUS_AWAY:
+				icon_name = PIDGIN_STOCK_TRAY_AWAY;
+				break;
+			case PURPLE_STATUS_UNAVAILABLE:
+				icon_name = PIDGIN_STOCK_TRAY_BUSY;
+				break;
+			case PURPLE_STATUS_EXTENDED_AWAY:
+				icon_name = PIDGIN_STOCK_TRAY_XA;
+				break;
+			case PURPLE_STATUS_INVISIBLE:
+				icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
+				break;
+			default:
+				icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
+				break;
 		}
 
+		if (pending)
+			icon_name = PIDGIN_STOCK_TRAY_PENDING;
+		if (connecting)
+			icon_name = PIDGIN_STOCK_TRAY_CONNECT;
+	
 		g_return_if_fail(icon_name != NULL);
 
-		cached_icons[icon] = load_hicon_from_stock(icon_name);
+		cached_icons[icon_index] = load_hicon_from_stock(icon_name);
 	}
 
-	systray_change_icon(cached_icons[icon]);
+	systray_change_icon(cached_icons[icon_index]);
 }
 
 static void winpidgin_tray_blank_icon() {
@@ -557,21 +568,21 @@
 	 * That is why we use custom 4-bit icons for pre XP Windowses */
 	if (osinfo.dwMajorVersion < 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion == 0))
 	{
-		cached_icons[DOCKLET_STATUS_OFFLINE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_OFFLINE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_OFFLINE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_AVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_AVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_AVAILABLE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_AWAY_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_XA] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_EXTENDED_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_XA_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_BUSY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_UNAVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_BUSY_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_CONNECTING] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_NUM_PRIMITIVES] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_CONNECTING_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_PENDING] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_NUM_PRIMITIVES+1] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_PENDING_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-		cached_icons[DOCKLET_STATUS_INVISIBLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+		cached_icons[PURPLE_STATUS_INVISIBLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
 			MAKEINTRESOURCE(PIDGIN_TRAY_INVISIBLE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
 	}