changeset 27942:583c36c03e50

propagate from branch 'im.pidgin.pidgin' (head e54933232e44b0c259cee6eff8f9354e6b94fe5d) to branch 'im.pidgin.pidgin.yaz' (head 416fab2796f48c8af3e71470dd7995d0cfcdd6ea)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Fri, 24 Apr 2009 07:43:08 +0000
parents f3ccb5a36fd6 (diff) 951102c642c5 (current diff)
children 684690dbda4a
files pidgin/gtkconv.c
diffstat 44 files changed, 1668 insertions(+), 297 deletions(-) [+]
line wrap: on
line diff
--- a/autogen.sh	Thu Apr 23 20:05:26 2009 +0000
+++ b/autogen.sh	Fri Apr 24 07:43:08 2009 +0000
@@ -149,4 +149,4 @@
 # Run configure
 ###############################################################################
 echo "running ./configure ${CONFIGURE_FLAGS} $@"
-./configure ${CONFIGURE_FLAGS} $@
+#./configure ${CONFIGURE_FLAGS} $@
--- a/configure.ac	Thu Apr 23 20:05:26 2009 +0000
+++ b/configure.ac	Fri Apr 24 07:43:08 2009 +0000
@@ -144,7 +144,7 @@
 	;;
 esac
 
-ALL_LINGUAS="af am ar az be@latin bg bn bs ca ca@valencia cs da de dz el en_AU en_CA en_GB eo es et eu fa fi fr ga gl gu he hi hu id it ja ka km kn ko ku lo lt mk mn my_MM nb ne nl nn oc pa pl pt_BR pt ps ro ru si sk sl sq sr sr@latin sv ta te th tr uk ur vi xh zh_CN zh_HK zh_TW"
+ALL_LINGUAS=""
 AM_GLIB_GNU_GETTEXT
 
 dnl If we don't have msgfmt, then po/ is going to fail -- ensure that
--- a/libpurple/certificate.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/certificate.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1328,20 +1328,22 @@
 		/* TODO: Tell the user where the chain broke? */
 		/* TODO: This error will hopelessly confuse any
 		   non-elite user. */
-		gchar *secondary;
+		if(purple_prefs_get_bool("/purple/network/warn_cert")) {
+			gchar *secondary;
 
-		secondary = g_strdup_printf(_("The certificate chain presented"
-					      " for %s is not valid."),
-					    vrq->subject_name);
+			secondary = g_strdup_printf(_("The certificate chain presented"
+						      " for %s is not valid."),
+						    vrq->subject_name);
 
-		/* TODO: Make this error either block the ensuing SSL
-		   connection error until the user dismisses this one, or
-		   stifle it. */
-		purple_notify_error(NULL, /* TODO: Probably wrong. */
-				    _("SSL Certificate Error"),
-				    _("Invalid certificate chain"),
-				    secondary );
-		g_free(secondary);
+			/* TODO: Make this error either block the ensuing SSL
+			   connection error until the user dismisses this one, or
+			   stifle it. */
+			purple_notify_error(NULL, /* TODO: Probably wrong. */
+					    _("SSL Certificate Error"),
+					    _("Invalid certificate chain"),
+					    secondary );
+			g_free(secondary);
+		}
 
 		/* Okay, we're done here */
 		purple_certificate_verify_complete(vrq,
@@ -1399,21 +1401,23 @@
 		   now, a full DN is a little much with which to assault the
 		   user's poor, leaky eyes. */
 		/* TODO: This error message makes my eyes cross, and I wrote it */
-		gchar * secondary =
-			g_strdup_printf(_("The certificate chain presented by "
-					  "%s does not have a valid digital "
-					  "signature from the Certificate "
-					  "Authority from which it claims to "
-					  "have a signature."),
-					vrq->subject_name);
+		if(purple_prefs_get_bool("/purple/network/warn_cert")) {
 
-		purple_notify_error(NULL, /* TODO: Probably wrong */
-				    _("SSL Certificate Error"),
-				    _("Invalid certificate authority"
-				      " signature"),
-				    secondary);
-		g_free(secondary);
+			gchar * secondary =
+				g_strdup_printf(_("The certificate chain presented by "
+						  "%s does not have a valid digital "
+						  "signature from the Certificate "
+						  "Authority from which it claims to "
+						  "have a signature."),
+						vrq->subject_name);
 
+			purple_notify_error(NULL, /* TODO: Probably wrong */
+					    _("SSL Certificate Error"),
+					    _("Invalid certificate authority"
+					      " signature"),
+					    secondary);
+			g_free(secondary);
+		}
 		/* Signal "bad cert" */
 		purple_certificate_verify_complete(vrq,
 						   PURPLE_CERTIFICATE_INVALID);
--- a/libpurple/conversation.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/conversation.c	Fri Apr 24 07:43:08 2009 +0000
@@ -654,6 +654,8 @@
 	PurpleBuddy *b;
 	PurpleChat *chat;
 	const char *text = NULL, *name;
+	gchar *utf8;
+	gsize dummy;
 
 	g_return_if_fail(conv != NULL);
 
@@ -672,7 +674,9 @@
 	if(text == NULL)
 		text = name;
 
-	purple_conversation_set_title(conv, text);
+	utf8 = sanitize_utf(text, strlen(text), &dummy);
+	purple_conversation_set_title(conv, utf8);
+	g_free(utf8);
 }
 
 void
@@ -1161,17 +1165,27 @@
 			  PurpleMessageFlags flags, time_t mtime)
 {
 	PurpleConversation *c;
+	char *tmpmessage = NULL;
 
 	g_return_if_fail(im != NULL);
 	g_return_if_fail(message != NULL);
 
 	c = purple_conv_im_get_conversation(im);
 
+	// yaz
+	if (purple_prefs_get_bool("/purple/conversations/msnstyle")) {
+		tmpmessage = g_strdup_printf("<br>%s", message);
+	} else {
+		tmpmessage = g_strdup_printf("%s", message);
+	}
+
 	/* Pass this on to either the ops structure or the default write func. */
 	if (c->ui_ops != NULL && c->ui_ops->write_im != NULL)
-		c->ui_ops->write_im(c, who, message, flags, mtime);
+		c->ui_ops->write_im(c, who, tmpmessage, flags, mtime);
 	else
-		purple_conversation_write(c, who, message, flags, mtime);
+		purple_conversation_write(c, who, tmpmessage, flags, mtime);
+
+	g_free(tmpmessage);
 }
 
 gboolean purple_conv_present_error(const char *who, PurpleAccount *account, const char *what)
--- a/libpurple/notify.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/notify.c	Fri Apr 24 07:43:08 2009 +0000
@@ -417,6 +417,9 @@
 		purple_signal_emit(purple_notify_get_handle(), "displaying-userinfo",
 						 purple_connection_get_account(gc), who, user_info);
 
+		g_return_val_if_fail(g_utf8_validate(who, -1, NULL), NULL); //yaz
+		g_return_val_if_fail(g_utf8_validate(user_info, -1, NULL), NULL); //yaz
+
 		ui_handle = ops->notify_userinfo(gc, who, user_info);
 
 		if (ui_handle != NULL) {
--- a/libpurple/protocols/gg/lib/http.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/gg/lib/http.c	Fri Apr 24 07:43:08 2009 +0000
@@ -44,6 +44,7 @@
 
 #include "compat.h"
 #include "libgadu.h"
+#include <glib.h>
 
 /*
  * gg_http_connect() // funkcja pomocnicza
--- a/libpurple/protocols/gg/lib/pubdir50.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/gg/lib/pubdir50.c	Fri Apr 24 07:43:08 2009 +0000
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#include <glib.h>
 
 #include "libgadu.h"
 
--- a/libpurple/protocols/irc/irc.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/irc/irc.c	Fri Apr 24 07:43:08 2009 +0000
@@ -987,6 +987,12 @@
 	option = purple_account_option_bool_new(_("Auto-detect incoming UTF-8"), "autodetect_utf8", IRC_DEFAULT_AUTODETECT);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
+	option = purple_account_option_bool_new(_("Use SO/SI to send hankaku kana"), "irc_use_sosi", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+
+	option = purple_account_option_bool_new(_("Use 8bit to send hankaku kana"), "irc_use_8bit", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+
 	option = purple_account_option_string_new(_("Username"), "username", "");
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
--- a/libpurple/protocols/irc/parse.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/irc/parse.c	Fri Apr 24 07:43:08 2009 +0000
@@ -35,7 +35,7 @@
 #include <ctype.h>
 
 static char *irc_send_convert(struct irc_conn *irc, const char *string);
-static char *irc_recv_convert(struct irc_conn *irc, const char *string);
+static char *irc_recv_convert(struct irc_conn *irc, char *string);
 
 static void irc_parse_error_cb(struct irc_conn *irc, char *input);
 
@@ -160,6 +160,20 @@
 	{ NULL, NULL, NULL, NULL }
 };
 
+/* yaz */
+#define ASCII	0
+#define KANJI	1
+#define KANA	2
+#define ROMAN	3
+char seq_ascii[] = {0x1B,0x28,0x42,0x00}; /* ESC ( B */
+char seq_kanji[] = {0x1B,0x24,0x42,0x00}; /* ESC $ B */
+char seq_kana[]  = {0x1B,0x28,0x49,0x00}; /* ESC ( I */
+char seq_roman[] = {0x1B,0x28,0x4A,0x00}; /* ESC ( J */
+char *seq[4] = {seq_ascii, seq_kanji, seq_kana, seq_roman};
+char *jisstate[5] = {"ASCII", "KANJI", "KANA", "ROMAN"};
+char SO[] = {0x0E,0x00};
+char SI[] = {0x0F,0x00};
+
 static PurpleCmdRet irc_parse_purple_cmd(PurpleConversation *conv, const gchar *cmd,
                                         gchar **args, gchar **error, void *data)
 {
@@ -227,34 +241,111 @@
 	GError *err = NULL;
 	gchar **encodings;
 	const gchar *enclist;
+	char *escpos = NULL;
+	char *temp = NULL;
+	gboolean iskana = FALSE;
+	char *pos = NULL;
+	gboolean irc_use_sosi, irc_use_8bit;
+	char *strtmp;
+	gsize strtmp_len;
 
 	enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);
 	encodings = g_strsplit(enclist, ",", 2);
 
+	irc_use_sosi = purple_account_get_bool(irc->account, "irc_use_sosi", FALSE);
+	irc_use_8bit = purple_account_get_bool(irc->account, "irc_use_8bit", FALSE);
+
 	if (encodings[0] == NULL || !g_ascii_strcasecmp("UTF-8", encodings[0])) {
 		g_strfreev(encodings);
 		return NULL;
 	}
 
-	utf8 = g_convert(string, strlen(string), encodings[0], "UTF-8", NULL, NULL, &err);
+	strtmp  = botch_utf(string, strlen(string), &strtmp_len);
+	utf8 = g_convert(strtmp, strlen(strtmp), encodings[0], "UTF-8", NULL, NULL, &err);
+
 	if (err) {
 		purple_debug(PURPLE_DEBUG_ERROR, "irc", "Send conversion error: %s\n", err->message);
 		purple_debug(PURPLE_DEBUG_ERROR, "irc", "Sending as UTF-8 instead of %s\n", encodings[0]);
-		utf8 = g_strdup(string);
+		utf8 = g_strdup(strtmp);
 		g_error_free(err);
 	}
+
+	/* yaz */
+	if (!strncasecmp("iso-2022-jp", encodings[0], strlen("iso-2022-jp"))) {
+		escpos = strrchr(utf8, 0x1B);
+		if(escpos && (!strncmp(seq_kanji, escpos, 3) || !strncmp(seq_kana, escpos, 3))){
+			char *oldutf8 = utf8;
+			utf8 = g_realloc(utf8, strlen(utf8)+1+3);
+			if(utf8)
+				strncat(utf8, seq_ascii, 3);
+			else
+				utf8 = oldutf8;
+		}
+
+		if(irc_use_sosi || irc_use_8bit){
+			/* SO/SI */
+			//find kana escape and replace with roman+SO
+			temp = g_malloc0(strlen(utf8) * 7); //XXX should be reasonable size
+			pos = utf8;
+			while(pos < utf8+strlen(utf8)){
+				escpos = strchr(pos, 0x1B);
+				if(escpos){
+					if(!strncmp(seq_kana, escpos, 3)){ /* kana found */
+						iskana = TRUE;
+						strncat(temp, pos, escpos-pos);
+						strcat(temp, seq_roman);
+						if(irc_use_sosi)
+							strcat(temp, SO);
+						pos = escpos+3;
+					} else {
+						if(iskana){
+							char *ptr;
+							ptr = temp + strlen(temp);
+							while(pos<escpos){
+								if(irc_use_8bit)
+									*ptr = *pos + 128; // convert to 8bit
+								else
+									*ptr = *pos;
+								ptr++; pos++;
+							}
+							if(irc_use_sosi)
+								strcat(temp, SI);
+							strncat(temp, escpos, 3);
+							pos = escpos+3;
+							iskana = FALSE;
+						} else {
+							strncat(temp, pos, escpos-pos+3); //include esc
+							pos = escpos+3;
+						}
+					}
+				} else { /* escpos == NULL */
+					strcat(temp, pos);
+					break;
+				}
+			}
+			g_free(utf8);
+			utf8 = temp;
+		}
+	}
+
 	g_strfreev(encodings);
-
+	g_free(strtmp);
 	return utf8;
 }
 
-static char *irc_recv_convert(struct irc_conn *irc, const char *string)
+static char *irc_recv_convert(struct irc_conn *irc, char *string)
 {
 	char *utf8 = NULL;
 	const gchar *charset, *enclist;
 	gchar **encodings;
 	gboolean autodetect;
 	int i;
+	GError *err;
+	gboolean retry;
+	gsize in_len, out_len;
+	int conv_len;
+	char *strtmp;
+	gsize strtmp_len;
 
 	enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);
 	encodings = g_strsplit(enclist, ",", -1);
@@ -278,13 +369,123 @@
 		if (!g_ascii_strcasecmp("UTF-8", charset)) {
 			if (g_utf8_validate(string, -1, NULL))
 				utf8 = g_strdup(string);
+		} else if (!strncasecmp("iso-2022-jp-2", charset, strlen("iso-2022-jp-2"))){
+			/* pre-process quirky jis */
+			unsigned char *jisstr;
+			unsigned char *ptr, *ptr2;
+			int state = ASCII;
+			int is8bit = FALSE;
+
+			jisstr = (unsigned char *)calloc(1, strlen(string)*7); /* enough? */
+			ptr = (unsigned char *)string; ptr2 = jisstr;
+
+			while(*ptr){
+				if(*ptr == 0x1B){
+					/* escape sequence. */
+					if(*(ptr+1) == 0x28 && *(ptr+2) == 0x42){
+						state = ASCII;
+
+					} else if(*(ptr+1) == 0x24 && *(ptr+2) == 0x42){
+						state = KANJI;
+
+					} else if(*(ptr+1) == 0x28 && *(ptr+2) == 0x49){
+						state = KANA;
+
+					} else if(*(ptr+1) == 0x28 && *(ptr+2) == 0x4a){
+						state = ROMAN;
+
+					}
+					purple_debug(PURPLE_DEBUG_INFO, "irc", "state %s\n", jisstate[state]);
+				}
+				if(*ptr >= 0xA1 && *ptr <= 0xDF){
+					/* raw 8bit */
+					if(!is8bit){
+						strcat((char *)jisstr, seq[KANA]);
+						ptr2 += 3;
+						is8bit = TRUE;
+						purple_debug(PURPLE_DEBUG_INFO, "irc", "8bit = TRUE\n");
+					}
+					*ptr2 = *ptr - 0x80;
+					ptr++ ; ptr2++;
+				} else {
+					/* 7bit */
+					if(*ptr == 0x0E){
+						/* SO */
+						strcat((char *)jisstr, seq[KANA]);
+						ptr++; ptr2 += 3;
+						purple_debug(PURPLE_DEBUG_INFO, "irc", "SO\n");
+						continue;
+					} else if(*ptr == 0x0F){
+						/* SI */
+						strcat((char *)jisstr, seq[state]);
+						purple_debug(PURPLE_DEBUG_INFO, "irc", "SI to %s\n", jisstate[state]);
+						ptr++; ptr2 += 3;
+						purple_debug(PURPLE_DEBUG_INFO, "irc", "SI\n");
+						continue;
+					}
+					if(is8bit){ /* the edge of 8bit -> 7bit */
+						purple_debug(PURPLE_DEBUG_INFO, "irc", "8bit to %s\n", jisstate[state]);
+						strcat((char *)jisstr, seq[state]);
+						ptr2 += 3;
+						is8bit=FALSE;
+						purple_debug(PURPLE_DEBUG_INFO, "irc", "8bit = FALSE\n");
+					}
+					/* copy str */
+					*ptr2 = *ptr;
+					ptr++; ptr2++;
+				}
+			}
+
+			/* convert & error recovery */
+			do {
+				err = NULL;
+				retry = FALSE;
+
+				conv_len = strlen((char *)jisstr);
+				utf8 = g_convert_with_fallback((char *)jisstr, conv_len, "UTF-8", charset,
+							       "?", &in_len, &out_len, &err);
+				if(err != NULL){
+					if(err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE){
+						memmove(jisstr + in_len, jisstr + in_len + 1,
+							conv_len - in_len -1);
+						conv_len--;
+						*(jisstr + conv_len) = '\0';
+						retry = TRUE;
+					}
+					g_error_free(err);
+				}
+			} while(retry);
+
+			if(jisstr)
+				free(jisstr);
+
 		} else {
-			utf8 = g_convert(string, -1, "UTF-8", charset, NULL, NULL, NULL);
+			do {
+				err = NULL;
+				retry = FALSE;
+
+				conv_len = strlen(string);
+				utf8 = g_convert_with_fallback(string, conv_len, "UTF-8", charset,
+							       "?", &in_len, &out_len, &err);
+				if(err != NULL){
+					if(err->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE){
+						memmove(string + in_len, string + in_len + 1,
+							 conv_len - in_len -1);
+						conv_len--;
+						*(string + conv_len) = '\0';
+						retry = TRUE;
+					}
+					g_error_free(err);
+				}
+			} while(retry);
 		}
 
-		if (utf8) {
-			g_strfreev(encodings);
-			return utf8;
+
+		if(utf8){
+			strtmp = sanitize_utf(utf8, strlen(utf8), &strtmp_len);
+ 			g_strfreev(encodings);
+			g_free(utf8);
+			return strtmp;
 		}
 	}
 	g_strfreev(encodings);
--- a/libpurple/protocols/jabber/google.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/jabber/google.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1,3 +1,4 @@
+/* -*- coding: utf-8 -*- */
 /**
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -1100,8 +1101,11 @@
 	if (!js->googletalk)
 		return;
 	if (jbr->status && !strncmp(jbr->status, "♫ ", strlen("♫ "))) {
+		gchar *unescaped;
+		unescaped = purple_unescape_html(jbr->status + strlen("♫ "));
 		purple_prpl_got_user_status(js->gc->account, user, "tune",
-					    PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL);
+					    PURPLE_TUNE_TITLE, unescaped, NULL);
+		g_free(unescaped);
 		jbr->status = NULL;
 	} else {
 		purple_prpl_got_user_status_deactive(js->gc->account, user, "tune");
--- a/libpurple/protocols/jabber/jabber.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Fri Apr 24 07:43:08 2009 +0000
@@ -435,8 +435,9 @@
 
 void jabber_send(JabberStream *js, xmlnode *packet)
 {
-	char *txt;
+	char *txt, *utf;
 	int len;
+	gsize utflen;
 
 	purple_signal_emit(my_protocol, "jabber-sending-xmlnode", js->gc, &packet);
 
@@ -445,8 +446,9 @@
 		return;
 
 	txt = xmlnode_to_str(packet, &len);
-	jabber_send_raw(js, txt, len);
-	g_free(txt);
+	utf = botch_utf(txt, len, &utflen); //yaz
+	jabber_send_raw(js, utf, utflen);
+	g_free(txt); g_free(utf);
 }
 
 static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
@@ -1684,13 +1686,21 @@
 	} else if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && jb->error_msg) {
 		ret = g_strdup(jb->error_msg);
 	} else {
-		char *stripped;
+		char *stripped = NULL;
 
 		if(!(stripped = purple_markup_strip_html(jabber_buddy_get_status_msg(jb)))) {
 			PurplePresence *presence = purple_buddy_get_presence(b);
 			if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-				PurpleStatus *status = purple_presence_get_status(presence, "tune");
-				stripped = g_strdup(purple_status_get_attr_string(status, PURPLE_TUNE_TITLE));
+				PurpleStatus *status;
+				const char *title, *artist;
+
+				status = purple_presence_get_status(presence, "tune");
+				title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+				artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+
+				stripped = g_strdup_printf("%s%s%s", title, artist ? " - " : "",
+							   artist ? artist : "");
+
 			}
 		}
 
@@ -1766,6 +1776,7 @@
 				const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
 				const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
 				const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
+
 				char *playing = purple_util_format_song_info(title, artist, album, NULL);
 				if (playing) {
 					purple_notify_user_info_add_pair(user_info, _("Now Listening"), playing);
--- a/libpurple/protocols/jabber/message.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/jabber/message.c	Fri Apr 24 07:43:08 2009 +0000
@@ -604,13 +604,17 @@
 				jm->thread_id = xmlnode_get_data(child);
 		} else if(!strcmp(child->name, "body") && !strcmp(xmlns,"jabber:client")) {
 			if(!jm->body) {
-				char *msg = xmlnode_to_str(child, NULL);
+				char *tmp, *msg;
+				gsize len;
+				tmp = xmlnode_to_str(child, NULL);
+				msg = sanitize_utf(tmp, strlen(tmp), &len);
 				jm->body = purple_strdup_withhtml(msg);
-				g_free(msg);
+				g_free(msg); g_free(tmp);
 			}
 		} else if(!strcmp(child->name, "html") && !strcmp(xmlns,"http://jabber.org/protocol/xhtml-im")) {
 			if(!jm->xhtml && xmlnode_get_child(child, "body")) {
 				char *c;
+				gsize len;
 
 				const PurpleConnection *gc = js->gc;
 				const gchar *who = xmlnode_get_attrib(packet, "from");
@@ -661,7 +665,9 @@
 				reformatted_xhtml =
 					jabber_message_xml_to_string_strip_img_smileys(child);
 
-				jm->xhtml = reformatted_xhtml;
+				jm->xhtml =
+					sanitize_utf(reformatted_xhtml,
+								 strlen(reformatted_xhtml), &len);
 
 				/* add known custom emoticons to the conversation */
 				/* note: if there were no smileys in the incoming message, or
--- a/libpurple/protocols/jabber/si.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/jabber/si.c	Fri Apr 24 07:43:08 2009 +0000
@@ -38,6 +38,8 @@
 
 #define STREAMHOST_CONNECT_TIMEOUT 15
 
+#include "util.h"
+
 typedef struct _JabberSIXfer {
 	JabberStream *js;
 
@@ -1238,8 +1240,17 @@
 	JabberIq *iq;
 	xmlnode *si, *file, *feature, *x, *field, *option, *value;
 	char buf[32];
+	gchar *f1 = NULL, *f2 = NULL;
+	gsize dummy;
 
-	xfer->filename = g_path_get_basename(xfer->local_filename);
+	/* yaz */
+	f1 = g_filename_display_basename(xfer->local_filename);
+	f2 = botch_utf(f1, strlen(f1), &dummy);
+	if(f2){
+		purple_xfer_set_filename(xfer, (char *)f2);
+	}
+	g_free(f1); f1 = NULL;
+	g_free(f2); f2 = NULL;
 
 	iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
 	xmlnode_set_attrib(iq->node, "to", xfer->who);
--- a/libpurple/protocols/msn/msg.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/msn/msg.c	Fri Apr 24 07:43:08 2009 +0000
@@ -112,7 +112,8 @@
 msn_message_new_plain(const char *message)
 {
 	MsnMessage *msg;
-	char *message_cr;
+	char *message_cr, *message_cr2;
+	gsize len;
 
 	msg = msn_message_new(MSN_MSG_TEXT);
 	msg->retries = 1;
@@ -124,8 +125,10 @@
 						 "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
 
 	message_cr = purple_str_add_cr(message);
-	msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
+	message_cr2 = botch_utf((gchar *)message_cr, -1, &len);
+	msn_message_set_bin_data(msg, message_cr2, len);
 	g_free(message_cr);
+	g_free(message_cr2);
 
 	return msg;
 }
@@ -825,14 +828,15 @@
 	char *body_str;
 	char *body_enc;
 	char *body_final;
-	size_t body_len;
+	char *yaz_body_final;
+	size_t body_len, new_len;
 	const char *passport;
 	const char *value;
 
 	gc = cmdproc->session->account->gc;
 
 	body = msn_message_get_bin_data(msg, &body_len);
-	body_str = g_strndup(body, body_len);
+	body_str = sanitize_utf(body, body_len, &new_len);
 	body_enc = g_markup_escape_text(body_str, -1);
 	g_free(body_str);
 
@@ -869,23 +873,30 @@
 		body_final = body_enc;
 	}
 
+	/* yaz */
+	/* replace 0D 0A with <br> */
+	yaz_body_final = purple_strreplace(body_final, "\r\n", "<br>");
+//	purple_debug_info("yaz msn", "yaz_body_final=%s\n", yaz_body_final);
+	g_free(body_final);
+	body_final = yaz_body_final;
+
 	if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
 		MsnSwitchBoard *swboard = cmdproc->data;
 
 		swboard->flag |= MSN_SB_FLAG_IM;
 
 		if (swboard->current_users > 1 ||
-			((swboard->conv != NULL) &&
-			 purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+		    ((swboard->conv != NULL) &&
+		     purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
 		{
 			/* If current_users is always ok as it should then there is no need to
 			 * check if this is a chat. */
 			if (swboard->current_users <= 1)
 				purple_debug_misc("msn", "plain_msg: current_users(%d)\n",
-								swboard->current_users);
+						  swboard->current_users);
 
 			serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final,
-							 time(NULL));
+					 time(NULL));
 			if (swboard->conv == NULL)
 			{
 				swboard->conv = purple_find_chat(gc, swboard->chat_id);
@@ -898,7 +909,7 @@
 			if (swboard->conv == NULL)
 			{
 				swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-										passport, purple_connection_get_account(gc));
+										      passport, purple_connection_get_account(gc));
 				swboard->flag |= MSN_SB_FLAG_IM;
 			}
 		}
--- a/libpurple/protocols/msn/msn.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/msn/msn.c	Fri Apr 24 07:43:08 2009 +0000
@@ -173,13 +173,18 @@
 	MsnSession *session;
 	PurpleAccount *account;
 	const char *alias;
+	gchar *tmp;
+	gsize dummy;
 
 	session = gc->proto_data;
 	cmdproc = session->notification->cmdproc;
 	account = purple_connection_get_account(gc);
 
-	if(entry && strlen(entry))
-		alias = purple_url_encode(entry);
+	if(entry && strlen(entry)) {
+		tmp = botch_utf(entry, strlen(entry), &dummy);
+		alias = purple_url_encode(tmp);
+		g_free(tmp);
+	}
 	else
 		alias = "";
 
@@ -195,6 +200,8 @@
 	}
 
 	msn_cmdproc_send(cmdproc, "PRP", "MFN %s", alias);
+	// propagate change on server side to local --yaz
+	purple_account_set_alias(account, entry); //oct16 <-- XXX questionable. Sep19.
 
 }
 
@@ -323,6 +330,23 @@
 }
 
 static void
+msn_ipc_init(PurplePlugin *plugin)
+{
+	purple_plugin_ipc_register(plugin, "msn_set_friendly_name",
+				   PURPLE_CALLBACK(msn_act_id),
+				   purple_marshal_VOID__POINTER_POINTER,
+				   purple_value_new(PURPLE_TYPE_UNKNOWN),2,
+				   purple_value_new(PURPLE_TYPE_POINTER),
+				   purple_value_new(PURPLE_TYPE_POINTER));
+}
+
+static void
+msn_ipc_end(PurplePlugin *plugin)
+{
+	purple_plugin_ipc_unregister_all(plugin);
+}
+
+static void
 msn_show_set_home_phone(PurplePluginAction *action)
 {
 	PurpleConnection *gc;
@@ -1089,13 +1113,18 @@
 msn_send_emoticons(MsnSwitchBoard *swboard, GString *body)
 {
 	MsnMessage *msg;
+	gchar *tmp;
+	gsize len;
 
 	g_return_if_fail(body != NULL);
 
 	msg = msn_message_new(MSN_MSG_SLP);
 	msn_message_set_content_type(msg, "text/x-mms-emoticon");
 	msn_message_set_flag(msg, 'N');
-	msn_message_set_bin_data(msg, body->str, body->len);
+
+	tmp = botch_utf(body->str, -1, &len);
+	msn_message_set_bin_data(msg, tmp, len);
+	g_free(tmp);
 
 	msn_switchboard_send_msg(swboard, msg, TRUE);
 	msn_message_destroy(msg);
@@ -2463,6 +2492,9 @@
 	msn_switchboard_init();
 	msn_sync_init();
 
+	// yaz
+	msn_ipc_init(plugin);
+
 	return TRUE;
 }
 
@@ -2472,6 +2504,9 @@
 	msn_switchboard_end();
 	msn_sync_end();
 
+	// yaz
+	msn_ipc_end(plugin);
+
 	return TRUE;
 }
 
--- a/libpurple/protocols/msnp9/msg.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/msnp9/msg.c	Fri Apr 24 07:43:08 2009 +0000
@@ -525,9 +525,7 @@
 
 	if (data != NULL && len > 0)
 	{
-		msg->body = g_malloc0(len + 1);
-		memcpy(msg->body, data, len);
-		msg->body_len = len;
+		msg->body = botch_utf((gchar *)data, len, &msg->body_len); /* yaz */
 	}
 	else
 	{
--- a/libpurple/protocols/msnp9/msn.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/msnp9/msn.c	Fri Apr 24 07:43:08 2009 +0000
@@ -174,13 +174,18 @@
 	MsnSession *session;
 	PurpleAccount *account;
 	const char *alias;
+	gchar *tmp;
+	gsize dummy;
 
 	session = gc->proto_data;
 	cmdproc = session->notification->cmdproc;
 	account = purple_connection_get_account(gc);
 
-	if(entry && strlen(entry))
-		alias = purple_url_encode(entry);
+	if(entry && strlen(entry)) {
+		tmp = botch_utf(entry, strlen(entry), &dummy);
+		alias = purple_url_encode(tmp);
+		g_free(tmp);
+	}
 	else
 		alias = "";
 
--- a/libpurple/protocols/msnp9/switchboard.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/msnp9/switchboard.c	Fri Apr 24 07:43:08 2009 +0000
@@ -837,7 +837,7 @@
 	char *body_str;
 	char *body_enc;
 	char *body_final;
-	size_t body_len;
+	size_t body_len, new_len;
 	const char *passport;
 	const char *value;
 
@@ -845,7 +845,7 @@
 	swboard = cmdproc->data;
 
 	body = msn_message_get_bin_data(msg, &body_len);
-	body_str = g_strndup(body, body_len);
+	body_str = sanitize_utf(body, body_len, &new_len);
 	body_enc = g_markup_escape_text(body_str, -1);
 	g_free(body_str);
 
--- a/libpurple/protocols/oscar/family_icbm.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Fri Apr 24 07:43:08 2009 +0000
@@ -52,8 +52,8 @@
 #endif
 
 #include "util.h"
-
-
+/* yaz */
+#include "debug.h"
 /**
  * Add a standard ICBM header to the given bstream with the given
  * information.
@@ -461,6 +461,9 @@
 	guchar cookie[8];
 	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
+	// yaz
+	char *ucs = NULL;
+	gsize bytes;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
@@ -499,15 +502,51 @@
 	 * raw data, followed by a series of TLVs.
 	 *
 	 */
+#if 0
 	byte_stream_new(&hdrbs, 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2);
 
 	byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */
 	byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
-
+#endif
+	//yaz
+	// convert msg to ascii first. if it succeed, send as plain ascii.
+	// if it fails, convert msg into UTF-16BE, and send it. 
+	ucs = g_convert(msg, strlen(msg), "ASCII", "UTF-8", NULL, &bytes, NULL);
+	if(ucs){
+		byte_stream_new(&hdrbs, 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2);
+
+		byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */
+		byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
+		byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
+
+		aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
+		aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, strlen(msg), (guint8 *)msg);
+		free(ucs);
+	} else {
+		byte_stream_new(&hdrbs, 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2+4+11);
+
+		byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */
+		byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
+		byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
+
+		aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 11, (guint8 *)"unicode-2-0");
+		aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+		//yaz
+		ucs = g_convert(msg, strlen(msg), "UTF-16BE", "UTF-8", NULL, &bytes, NULL);
+		if(ucs){
+			botch_ucs(ucs, bytes);
+			aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, bytes, (guint8 *)ucs);
+			free(ucs);
+		}
+	}
+#if 0
 	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
 	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
 	aim_tlvlist_add_str(&inner_tlvlist, 0x000c, msg);
+#endif
 	aim_tlvlist_add_chatroom(&inner_tlvlist, 0x2711, exchange, roomname, instance);
 	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
 
--- a/libpurple/protocols/oscar/odc.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/oscar/odc.c	Fri Apr 24 07:43:08 2009 +0000
@@ -101,18 +101,22 @@
 	byte_stream_new(&bs, length + frame->payload.len);
 	byte_stream_putraw(&bs, conn->magic, 4);
 	byte_stream_put16(&bs, length);
+
 	byte_stream_put16(&bs, frame->type);
 	byte_stream_put16(&bs, frame->subtype);
 	byte_stream_put16(&bs, 0x0000);
+
 	byte_stream_putraw(&bs, frame->cookie, 8);
 	byte_stream_put16(&bs, 0x0000);
 	byte_stream_put16(&bs, 0x0000);
 	byte_stream_put16(&bs, 0x0000);
 	byte_stream_put16(&bs, 0x0000);
+
 	byte_stream_put32(&bs, frame->payload.len);
-	byte_stream_put16(&bs, 0x0000);
 	byte_stream_put16(&bs, frame->encoding);
 	byte_stream_put16(&bs, 0x0000);
+	byte_stream_put16(&bs, 0x0000);
+
 	byte_stream_put16(&bs, frame->flags);
 	byte_stream_put16(&bs, 0x0000);
 	byte_stream_put16(&bs, 0x0000);
@@ -496,11 +500,14 @@
 	frame->type = byte_stream_get16(bs);
 	frame->subtype = byte_stream_get16(bs);
 	byte_stream_advance(bs, 2);
+
 	byte_stream_getrawbuf(bs, frame->cookie, 8);
 	byte_stream_advance(bs, 8);
+
 	frame->payload.len = byte_stream_get32(bs);
 	frame->encoding = byte_stream_get16(bs);
 	byte_stream_advance(bs, 4);
+
 	frame->flags = byte_stream_get16(bs);
 	byte_stream_advance(bs, 4);
 	byte_stream_getrawbuf(bs, frame->bn, 32);
--- a/libpurple/protocols/oscar/oft.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/oscar/oft.c	Fri Apr 24 07:43:08 2009 +0000
@@ -642,6 +642,8 @@
 {
 	PeerConnection *conn;
 	size_t size;
+	gchar *f1 = NULL, *f2 = NULL;
+	gsize dummy;
 
 	conn = xfer->data;
 	conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
@@ -679,7 +681,16 @@
 	strncpy((gchar *)conn->xferdata.idstring, "Cool FileXfer", 31);
 	conn->xferdata.modtime = 0;
 	conn->xferdata.cretime = 0;
-	xfer->filename = g_path_get_basename(xfer->local_filename);
+
+	/* yaz */
+	f1 = g_filename_display_basename(xfer->local_filename);
+	f2 = botch_utf(f1, strlen(f1), &dummy);
+	if(f2){
+		purple_xfer_set_filename(xfer, (char *)f2);
+	}
+	g_free(f1); f1 = NULL;
+	g_free(f2); f2 = NULL;
+
 	conn->xferdata.name_length = MAX(64, strlen(xfer->filename) + 1);
 	conn->xferdata.name = (guchar *)g_strndup(xfer->filename, conn->xferdata.name_length - 1);
 
--- a/libpurple/protocols/oscar/oscar.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Apr 24 07:43:08 2009 +0000
@@ -306,7 +306,25 @@
 	gchar *utf8 = NULL;
 
 	if ((encoding == NULL) || encoding[0] == '\0') {
-		purple_debug_info("oscar", "Empty encoding, assuming UTF-8\n");
+		purple_debug_info("yaz oscar", "Empty encoding, validate as UTF-8\n");
+		if(g_utf8_validate(text, textlen, NULL)){
+			gsize newlen;
+			utf8 = sanitize_utf(text, textlen, &newlen);
+			goto done;
+		}
+		// not UTF-8
+		purple_debug_info("yaz oscar", "Empty encoding, assuming UTF-16BE\n");
+		sanitize_ucs((gchar *)text, textlen);
+		utf8 = g_convert(text, textlen, "UTF-8", "UTF-16BE", NULL, NULL, NULL);
+		if(utf8){
+			if(!g_utf8_validate(utf8, strlen(utf8), NULL)){
+				purple_debug_info("yaz oscar", "Invalid conversion\n");
+				g_free(utf8);
+				utf8 = NULL;
+			}
+		} else {
+			purple_debug_info("yaz oscar", "Conversion failed\n");
+		}
 	} else if (!g_ascii_strcasecmp(encoding, "iso-8859-1")) {
 		utf8 = g_convert(text, textlen, "UTF-8", "iso-8859-1", NULL, NULL, NULL);
 	} else if (!g_ascii_strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1") ||
@@ -321,6 +339,7 @@
 		 * and do something (un)reasonable with that, and not
 		 * mess up too much else. */
 		const gchar *charset = purple_account_get_string(account, "encoding", NULL);
+		sanitize_ucs((gchar *)text, textlen);
 		if (charset) {
 			gsize len;
 			utf8 = g_convert(text, textlen, charset, "UTF-16BE", &len, NULL, NULL);
@@ -352,7 +371,7 @@
 		else
 			utf8 = g_strndup(text, textlen);
 	}
-
+done:
 	return utf8;
 }
 
@@ -377,7 +396,7 @@
 static gchar *
 purple_plugin_oscar_convert_to_utf8(const gchar *data, gsize datalen, const char *charsetstr, gboolean fallback)
 {
-	gchar *ret = NULL;
+	gchar *ret = NULL, *ret2 = NULL;
 	GError *err = NULL;
 
 	if ((charsetstr == NULL) || (*charsetstr == '\0'))
@@ -400,7 +419,9 @@
 			purple_debug_warning("oscar", "String is not valid UTF-8.\n");
 	}
 
-	return ret;
+	ret2 = sanitize_utf(ret, -1, NULL);
+	g_free(ret);
+	return ret2;
 }
 
 /**
@@ -436,11 +457,11 @@
 	} else if (charset == AIM_CHARSET_ASCII) {
 		/* Should just be "ASCII" */
 		charsetstr1 = "ASCII";
-		charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-	} else if (charset == 0x000d) {
+		charsetstr2 = "UTF-8";
+	} else if (charset == AIM_CHARSET_QUIRKUTF8) {
 		/* Mobile AIM client on a Nokia 3100 and an LG VX6000 */
-		charsetstr1 = "ISO-8859-1";
-		charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+		charsetstr1 = "UTF-8";  //iChat use 0x000d when it sends UTF-8. --yaz
+		charsetstr2 = "ISO-8859-1";
 	} else {
 		/* Unknown, hope for valid UTF-8... */
 		charsetstr1 = "UTF-8";
@@ -509,6 +530,7 @@
 		if ((b != NULL) && (PURPLE_BUDDY_IS_ONLINE(b)))
 		{
 			*msg = g_convert(from, -1, "UTF-16BE", "UTF-8", NULL, &msglen, &err);
+			botch_ucs(*msg, msglen);
 			if (*msg != NULL)
 			{
 				*charset = AIM_CHARSET_UNICODE;
@@ -536,6 +558,10 @@
 	 * XXX - We need a way to only attempt to convert if we KNOW "from"
 	 * can be converted to "charsetstr"
 	 */
+#ifndef _WIN32
+	/* nosuke reported that this portion caused unexpected
+	 * conversion from utf-8 fullwidth tilde/numbers/alphabets to
+	 * halfwidth ones on windows environment. --yaz */
 	*msg = g_convert(from, -1, charsetstr, "UTF-8", NULL, &msglen, &err);
 	if (*msg != NULL) {
 		*charset = AIM_CHARSET_CUSTOM;
@@ -548,11 +574,13 @@
 					  charsetstr, err->message);
 	g_error_free(err);
 	err = NULL;
+#endif
 
 	/*
 	 * Nothing else worked, so send as UTF-16BE.
 	 */
-	*msg = g_convert(from, -1, "UTF-16BE", "UTF-8", NULL, &msglen, &err);
+	*msg = g_convert(from, strlen(from), "UTF-16BE", "UTF-8", NULL, &msglen, &err);
+	botch_ucs(*msg, msglen);
 	if (*msg != NULL) {
 		*charset = AIM_CHARSET_UNICODE;
 		*charsubset = 0x0000;
@@ -2320,6 +2348,8 @@
 		tmp = purple_plugin_oscar_decode_im_part(account, userinfo->bn, curpart->charset,
 				curpart->charsubset, curpart->data, curpart->datalen);
 		if (tmp != NULL) {
+			purple_str_strip_char(tmp, 0x0d); // yaz: strip CR
+//			purple_debug_info("yaz oscar", "tmp=%s",tmp);
 			g_string_append(message, tmp);
 			g_free(tmp);
 		}
@@ -2422,6 +2452,7 @@
 		char *encoding, *utf8name, *tmp;
 		GHashTable *components;
 
+//		purple_debug_info("yaz oscar", "chat request %s\n", args->msg);
 		if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange) {
 			g_free(message);
 			return 1;
@@ -2444,6 +2475,8 @@
 		g_hash_table_replace(components, g_strdup("room"), utf8name);
 		g_hash_table_replace(components, g_strdup("exchange"),
 				g_strdup_printf("%d", args->info.chat.roominfo.exchange));
+		purple_debug_info("yaz oscar", "about to call serv_got_chat_invite\n");
+//		purple_debug_info("yaz oscar", "name=%s message=%s\n", name ? name : args->info.chat.roominfo.name, message);
 		serv_got_chat_invite(gc,
 				     utf8name,
 				     userinfo->bn,
@@ -2668,7 +2701,7 @@
 	 * for this suck-ass part of the protocol by splitting the string into at
 	 * most 1 baby string.
 	 */
-	msg1 = g_strsplit(args->msg, "\376", (args->type == 0x01 ? 1 : 0));
+	msg1 = g_strsplit(args->msg, "\376", (args->type == 0x01 ? 1 : 0)); // \376 is 0xfe
 	for (numtoks=0; msg1[numtoks]; numtoks++);
 	msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *));
 	for (i=0; msg1[i]; i++) {
@@ -4357,9 +4390,7 @@
 {
 	GString *msg;
 	GString *data;
-	gchar *tmp;
-	int tmplen;
-	guint16 charset, charsubset;
+	guint16 charset;
 	GData *attribs;
 	const char *start, *end, *last;
 	int oscar_id = 0;
@@ -4419,12 +4450,9 @@
 
 	g_string_append(msg, "</BODY></HTML>");
 
-	/* Convert the message to a good encoding */
-	purple_plugin_oscar_convert_to_best_encoding(conn->od->gc,
-			conn->bn, msg->str, &tmp, &tmplen, &charset, &charsubset);
-	g_string_free(msg, TRUE);
-	msg = g_string_new_len(tmp, tmplen);
-	g_free(tmp);
+	/* iChat and AIM6 use 0x000d to send UTF8.
+       moreover, AIM6 persists only to UTF8! --yaz */
+	charset = AIM_CHARSET_QUIRKUTF8;
 
 	/* Append any binary data that we may have */
 	if (oscar_id) {
@@ -4666,7 +4694,8 @@
 
 	charset = oscar_charset_check(str);
 	if (charset == AIM_CHARSET_UNICODE) {
-		encoded = g_convert(str, -1, "UTF-16BE", "UTF-8", NULL, ret_len, NULL);
+		encoded = g_convert(str, strlen(str), "UTF-16BE", "UTF-8", NULL, ret_len, NULL);
+		botch_ucs(encoded, *ret_len);
 		*encoding = "unicode-2-0";
 	} else if (charset == AIM_CHARSET_CUSTOM) {
 		encoded = g_convert(str, -1, "ISO-8859-1", "UTF-8", NULL, ret_len, NULL);
@@ -5825,7 +5854,7 @@
 		charsetstr = "unicode-2-0";
 	else if (charset == AIM_CHARSET_CUSTOM)
 		charsetstr = "iso-8859-1";
-	aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en");
+	aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "JA");
 	g_free(buf2);
 	g_free(buf);
 
--- a/libpurple/protocols/oscar/oscar.h	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Fri Apr 24 07:43:08 2009 +0000
@@ -776,6 +776,7 @@
 #define AIM_CHARSET_ASCII		0x0000
 #define AIM_CHARSET_UNICODE	0x0002 /* UTF-16BE */
 #define AIM_CHARSET_CUSTOM	0x0003
+#define AIM_CHARSET_QUIRKUTF8	0x000d /* iChat and AIM6 use this in the meaning of UTF-8 in ODC. --yaz */
 
 /*
  * Multipart message structures.
--- a/libpurple/protocols/yahoo/util.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/util.c	Fri Apr 24 07:43:08 2009 +0000
@@ -29,6 +29,7 @@
 #include "prpl.h"
 
 #include "yahoo.h"
+#include "util.h"
 
 #include <string.h>
 
@@ -119,14 +120,13 @@
 char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8)
 {
 	struct yahoo_data *yd = gc->proto_data;
-	char *ret;
+	char *ret = NULL;
+	gsize newlen;
 	const char *to_codeset;
 
-	if (yd->jp)
-		return g_strdup(str);
-
-	if (utf8 && *utf8) /* FIXME: maybe don't use utf8 if it'll fit in latin1 */
-		return g_strdup(str);
+	if (utf8 && *utf8) {
+		return botch_utf((gchar *)str, strlen((gchar *)str), &newlen);
+	}
 
 	to_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset",  "ISO-8859-1");
 	ret = g_convert_with_fallback(str, -1, to_codeset, "UTF-8", "?", NULL, NULL, NULL);
@@ -148,23 +148,29 @@
 char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8)
 {
 	struct yahoo_data *yd = gc->proto_data;
-	char *ret;
+	char *ret, *tmp;
 	const char *from_codeset;
+	gsize newlen;
 
 	if (utf8) {
-		if (g_utf8_validate(str, -1, NULL))
-			return g_strdup(str);
+		ret = sanitize_utf((gchar *)str, strlen((gchar *)str), &newlen);
+		if (g_utf8_validate(ret, -1, NULL))
+			return ret;
 	}
 
-	if (yd->jp)
+	if (yd->jp && !utf8)
 		from_codeset = "SHIFT_JIS";
 	else
 		from_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset",  "ISO-8859-1");
 
 	ret = g_convert_with_fallback(str, -1, "UTF-8", from_codeset, NULL, NULL, NULL, NULL);
 
-	if (ret)
+	if (ret) {
+		tmp = ret;
+		ret = sanitize_utf((gchar *)tmp, strlen((gchar *)tmp), &newlen);
+		g_free(tmp);
 		return ret;
+	}
 	else
 		return g_strdup("");
 }
--- a/libpurple/protocols/yahoo/yahoo.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1430,8 +1430,9 @@
 
 #define OUT_CHARSET "utf-8"
 
-static char *yahoo_decode(const char *text)
+static char *yahoo_decode(PurpleConnection *gc, const char *text)
 {
+	struct yahoo_data *yd = gc->proto_data;
 	char *converted = NULL;
 	char *n, *new;
 	const char *end, *p;
@@ -1472,11 +1473,16 @@
 
 	*n = '\0';
 
-	if (strstr(text, "\033$B"))
-		converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL);
-	if (!converted)
-		converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);
-	g_free(new);
+	if (yd->jp) {
+		converted = g_convert(new, n - new, OUT_CHARSET, "UTF-8", NULL, NULL, NULL);
+	}
+	if (!yd->jp || !converted) {
+		if (strstr(text, "\033$B"))
+			converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL);
+		if (!converted)
+			converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);
+		g_free(new);
+	}
 
 	return converted;
 }
@@ -1509,8 +1515,8 @@
 	}
 
 	if (who && subj && email && *email) {
-		char *dec_who = yahoo_decode(who);
-		char *dec_subj = yahoo_decode(subj);
+		char *dec_who = yahoo_decode(gc, who);
+		char *dec_subj = yahoo_decode(gc, subj);
 		char *from = g_strdup_printf("%s (%s)", dec_who, email);
 
 		purple_notify_email(gc, dec_subj, from, purple_account_get_username(account),
@@ -1667,11 +1673,12 @@
 	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP,	YAHOO_STATUS_AVAILABLE, 0);
 
 	if(yd->jp) {
-		yahoo_packet_hash(pack, "sssss",
+		yahoo_packet_hash(pack, "ssssss",
 						  0, name,
 						  6, result6,
 						  96, result96,
 						  1, name,
+						  244, YAHOOJP_CLIENT_VERSION_ID,
 						  135, YAHOOJP_CLIENT_VERSION);
 	} else {
 		yahoo_packet_hash(pack, "ssssss",
@@ -2130,11 +2137,12 @@
 	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP,	yd->current_status, 0);
 
 	if(yd->jp) {
-		yahoo_packet_hash(pack, "sssss",
+		yahoo_packet_hash(pack, "ssssss",
 						  0, name,
 						  6, resp_6,
 						  96, resp_96,
 						  1, name,
+						  244, YAHOOJP_CLIENT_VERSION_ID,
 						  135, YAHOOJP_CLIENT_VERSION);
 	} else {
 		yahoo_packet_hash(pack, "ssssss",
@@ -4264,7 +4272,10 @@
 		use_whole_url ? base_url : "",
 		yd->cookie_t, yd->cookie_y);
 
-	url_data = purple_util_fetch_url_request(base_url, use_whole_url,
+	if (yd->jp)
+		url_data = NULL;
+	else
+		url_data = purple_util_fetch_url_request(base_url, use_whole_url,
 			"Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, request, FALSE,
 			yahoo_get_inbox_token_cb, gc);
 
@@ -4688,6 +4699,11 @@
 	}
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, 0);
+	if(!pkt) { // yaz
+		purple_debug_info("yahoo", "yahoo_set_idle: pkt == NULL\n");
+		return;
+	}
+
 	yahoo_packet_hash_int(pkt, 10, yd->current_status);
 
 	if (yd->current_status == YAHOO_STATUS_CUSTOM) {
@@ -4732,20 +4748,27 @@
 	}
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, 0);
+	if(!pkt) {
+		purple_debug_info("yahoo", "yahoo_set_idle: pkt == NULL\n");
+		return;
+	}
 
 	yahoo_packet_hash_int(pkt, 10, yd->current_status);
 	if (yd->current_status == YAHOO_STATUS_CUSTOM) {
 		const char *tmp;
+		gboolean utf8 = TRUE;
 		if (status == NULL)
 			status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
 		tmp = purple_status_get_attr_string(status, "message");
 		if (tmp != NULL) {
-			msg = yahoo_string_encode(gc, tmp, NULL);
+			msg = yahoo_string_encode(gc, tmp, &utf8);
 			msg2 = purple_markup_strip_html(msg);
-			yahoo_packet_hash_str(pkt, 19, msg2);
+			yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
+			yahoo_packet_hash_str(pkt, 19, msg2); // yaz: pkt may be NULL.
 		} else {
 			/* get_yahoo_status_from_purple_status() returns YAHOO_STATUS_CUSTOM for
 			 * the generic away state (YAHOO_STATUS_TYPE_AWAY) with no message */
+			yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
 			yahoo_packet_hash_str(pkt, 19, _("Away"));
 		}
 	} else {
@@ -5484,11 +5507,11 @@
 	option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
-	option = purple_account_option_string_new(_("Encoding"), "local_charset", "ISO-8859-1");
+	option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
 
-#if 0
+#if 1
 	option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
--- a/libpurple/protocols/yahoo/yahoo.h	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo.h	Fri Apr 24 07:43:08 2009 +0000
@@ -83,7 +83,7 @@
 #define YAHOO_CLIENT_VERSION "8.1.0.421"
 
 #define YAHOOJP_CLIENT_VERSION_ID "524223"
-#define YAHOOJP_CLIENT_VERSION "7,0,1,1"
+#define YAHOOJP_CLIENT_VERSION "7,0,1,3"
 
 /* Index into attention types list. */
 #define YAHOO_BUZZ 0
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo_filexfer.c	Fri Apr 24 07:43:08 2009 +0000
@@ -226,7 +226,7 @@
 	PurpleXfer *xfer;
 	struct yahoo_xfer_data *xd;
 	struct yahoo_packet *pkt;
-	gchar *size, *filename, *encoded_filename, *header;
+	gchar *size, *filename, *encoded_filename, *header, *tmp = NULL;
 	guchar *pkt_buf;
 	const char *host;
 	int port;
@@ -234,6 +234,7 @@
 	PurpleConnection *gc;
 	PurpleAccount *account;
 	struct yahoo_data *yd;
+	gsize dummy;
 
 	purple_debug(PURPLE_DEBUG_INFO, "yahoo",
 			   "AAA - in yahoo_sendfile_connected\n");
@@ -260,8 +261,12 @@
 		YAHOO_STATUS_AVAILABLE, yd->session_id);
 
 	size = g_strdup_printf("%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
-	filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-	encoded_filename = yahoo_string_encode(gc, filename, NULL);
+
+	/* yaz */
+	tmp = g_filename_display_basename(purple_xfer_get_local_filename(xfer));
+	filename = botch_utf(tmp, strlen(tmp), &dummy);
+	g_free(tmp);
+	encoded_filename = yahoo_string_encode(gc, filename, NULL); // this takes utf8 as input. --yaz
 
 	yahoo_packet_hash(pkt, "sssss", 0, purple_connection_get_display_name(gc),
 	  5, xfer->who, 14, "", 27, encoded_filename, 28, size);
@@ -981,8 +986,8 @@
 	struct yahoo_xfer_data *xd;
 	struct sockaddr_in *addr;
 	struct yahoo_packet *pkt;
-	long actaddr;
-	long a,b,c,d;
+	unsigned long actaddr;
+	unsigned long a,b,c,d;
 	PurpleConnection *gc;
 	PurpleAccount *account;
 	struct yahoo_data *yd;
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Fri Apr 24 07:43:08 2009 +0000
@@ -42,6 +42,7 @@
 {
 	struct yahoo_pair *pair;
 
+	g_return_if_fail(pkt != NULL);
 	g_return_if_fail(value != NULL);
 
 	pair = g_new0(struct yahoo_pair, 1);
@@ -54,6 +55,8 @@
 {
 	struct yahoo_pair *pair;
 
+	g_return_if_fail(pkt != NULL);
+
 	pair = g_new0(struct yahoo_pair, 1);
 	pair->key = key;
 	pair->value = g_strdup_printf("%d", value);
@@ -389,6 +392,9 @@
 {
 	int ret;
 
+	g_return_val_if_fail(pkt != NULL, 0);
+	g_return_val_if_fail(yd != NULL, 0);
+
 	ret = yahoo_packet_send(pkt, yd);
 	yahoo_packet_free(pkt);
 	return ret;
--- a/libpurple/protocols/yahoo/yahoo_packet.h	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.h	Fri Apr 24 07:43:08 2009 +0000
@@ -126,7 +126,7 @@
 
 #define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
 #define YAHOO_PROTO_VER 0x000f
-#define YAHOO_PROTO_VER_JAPAN 0x000f
+#define YAHOO_PROTO_VER_JAPAN 0x000d
 
 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
 
--- a/libpurple/protocols/yahoo/yahoo_profile.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoo_profile.c	Fri Apr 24 07:43:08 2009 +0000
@@ -22,6 +22,7 @@
  */
 
 #define PHOTO_SUPPORT 1
+//original is 1 --yaz
 
 #include "internal.h"
 #include "debug.h"
@@ -670,6 +671,7 @@
 	},
 };
 
+#if 0
 static char *yahoo_info_date_reformat(const char *field, size_t len)
 {
 	char *tmp = g_strndup(field, len);
@@ -678,6 +680,7 @@
 	g_free(tmp);
 	return g_strdup(purple_date_format_short(localtime(&t)));
 }
+#endif
 
 static char *yahoo_remove_nonbreaking_spaces(char *str)
 {
@@ -763,6 +766,7 @@
 
 #endif /* PHOTO_SUPPORT */
 
+#define PROF_LEN (1024 * 10)
 static void yahoo_got_info(PurpleUtilFetchUrlData *url_data, gpointer user_data,
 		const gchar *url_text, size_t len, const gchar *error_message)
 {
@@ -1011,6 +1015,9 @@
 			g_free(stripped);
 			stripped = purple_utf8_ncr_decode(p);
 			stripped_len = strlen(stripped);
+
+			purple_debug_misc("yahoo", "after utf8 conversion: stripped@1 = (%s)\n",
+                              stripped); //payload --yaz
 			g_free(p);
 		}
 	}
@@ -1022,7 +1029,7 @@
 				strings->charset, NULL, NULL, NULL);
 		yahoo_remove_nonbreaking_spaces(last_updated_utf8_string);
 
-		purple_debug_misc("yahoo", "after utf8 conversion: stripped = (%s)\n", stripped);
+		purple_debug_misc("yahoo", "after utf8 conversion: stripped = (%s)\n", stripped); //payload --yaz
 	}
 
 	if (profile_state == PROFILE_STATE_DEFAULT) {
@@ -1055,16 +1062,17 @@
 		}
 	}
 #endif /* PHOTO_SUPPORT */
+	purple_debug_info("yahoo", "email = %s\n", strings->my_email_string);
 
 	/* extract their Email address and put it in */
 	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
 			strings->my_email_string, (yd->jp ? 4 : 1), " ", 0,
 			strings->private_string, _("Email"), 0, NULL, NULL);
-
+#if 0
 	/* extract the Nickname if it exists */
 	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
 			"Nickname:", 1, "\n", '\n',
-			NULL, _("Nickname"), 0, NULL, NULL);
+			 NULL, _("Nickname"), 0, NULL, NULL);
 
 	/* extract their RealName and put it in */
 	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
@@ -1095,7 +1103,7 @@
 	found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
 			strings->occupation_string, 2, "\n", '\n',
 			NULL, _("Occupation"), 0, NULL, NULL);
-
+#endif
 	/* Hobbies, Latest News, and Favorite Quote are a bit different, since
 	 * the values can contain embedded newlines... but any or all of them
 	 * can also not appear.  The way we delimit them is to successively
@@ -1104,7 +1112,7 @@
 	 * next thing to follow this bunch.  (For Yahoo Japan, we check for
 	 * the "Description" ("Self PR") heading instead of "Links".)
 	 */
-
+#if 0
 	if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
 			strings->hobbies_string, (yd->jp ? 3 : 1), strings->latest_news_string,
 			'\n', "\n", _("Hobbies"), 0, NULL, NULL))
@@ -1190,6 +1198,7 @@
 				last_updated_utf8_string, (yd->jp ? 2 : 1), (yd->jp ? "\n" : " "), (yd->jp ? 0 : '\n'), NULL,
 				_("Last Update"), 0, NULL, (yd->jp ? NULL : yahoo_info_date_reformat));
 	}
+#endif
 	} /* if (profile_state == PROFILE_STATE_DEFAULT) */
 
 	if(!found)
--- a/libpurple/protocols/yahoo/yahoochat.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Fri Apr 24 07:43:08 2009 +0000
@@ -916,7 +916,7 @@
 	g_free(msg1);
 	msg1 = yahoo_string_encode(gc, msg2, &utf8);
 	g_free(msg2);
-	room2 = yahoo_string_encode(gc, room, NULL);
+	room2 = yahoo_string_encode(gc, room, &utf8);
 
 	pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, 0);
 
@@ -1555,6 +1555,7 @@
 	char *url;
 	char *id;
 	const char *rll;
+	gboolean jp = purple_account_get_bool(list->account, "yahoojp", FALSE);
 
 	if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
 		return;
@@ -1564,17 +1565,12 @@
 		return;
 	}
 
-	rll = purple_account_get_string(list->account, "room_list_locale",
-								  YAHOO_ROOMLIST_LOCALE);
+	rll = jp ? YAHOOJP_ROOMLIST_LOCALE : purple_account_get_string(list->account, "room_list_locale", YAHOO_ROOMLIST_LOCALE);
 
 	if (rll != NULL && *rll != '\0') {
-		url = g_strdup_printf("%s?chatroom_%s=0&intl=%s",
-	       purple_account_get_string(list->account,"room_list",
-	       YAHOO_ROOMLIST_URL), id, rll);
+		url = g_strdup_printf("%s?chatroom_%s=0&intl=%s", jp ? YAHOOJP_ROOMLIST_URL : purple_account_get_string(list->account,"room_list", YAHOO_ROOMLIST_URL), id, rll);
 	} else {
-		url = g_strdup_printf("%s?chatroom_%s=0",
-	       purple_account_get_string(list->account,"room_list",
-	       YAHOO_ROOMLIST_URL), id);
+		url = g_strdup_printf("%s?chatroom_%s=0", jp ? YAHOOJP_ROOMLIST_URL : purple_account_get_string(list->account,"room_list", YAHOO_ROOMLIST_URL), id);
 	}
 
 	yrl = g_new0(struct yahoo_roomlist, 1);
--- a/libpurple/server.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/server.c	Fri Apr 24 07:43:08 2009 +0000
@@ -241,6 +241,8 @@
 	GSList *buddies;
 	PurpleBuddy *b;
 	PurpleConversation *conv;
+	gsize dummy;
+	gchar *alias2 = NULL;
 
 	account = purple_connection_get_account(gc);
 	buddies = purple_find_buddies(account, who);
@@ -257,13 +259,16 @@
 		if (purple_strequal(server_alias, alias))
 			continue;
 
-		purple_blist_server_alias_buddy(b, alias);
+		if(alias)
+			alias2 = sanitize_utf(alias, strlen(alias), &dummy);
+
+		purple_blist_server_alias_buddy(b, alias2);
 
 		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), account);
-		if (conv != NULL && alias != NULL && purple_strequal(alias, who))
+		if (conv != NULL && alias2 != NULL && !purple_strequal(alias2, who))
 		{
 			char *escaped = g_markup_escape_text(who, -1);
-			char *escaped2 = g_markup_escape_text(alias, -1);
+			char *escaped2 = g_markup_escape_text(alias2, -1);
 			char *tmp = g_strdup_printf(_("%s is now known as %s.\n"),
 										escaped, escaped2);
 
@@ -275,6 +280,8 @@
 			g_free(escaped2);
 			g_free(escaped);
 		}
+		g_free(alias2);
+		alias2 = NULL;
 	}
 }
 
@@ -284,6 +291,8 @@
 	PurpleAccount *account = NULL;
 	GSList *buddies = NULL;
 	PurpleBuddy *b = NULL;
+	gsize dummy;
+	gchar *alias2 = NULL;
 
 	account = purple_connection_get_account(gc);
 	buddies = purple_find_buddies(account, who);
@@ -298,11 +307,13 @@
 		if (purple_strequal(balias, alias))
 			continue;
 
-		purple_blist_alias_buddy(b, alias);
+		alias2 = sanitize_utf(alias, strlen(alias), &dummy);
+		purple_blist_alias_buddy(b, alias2);
+		g_free(alias2);
+		alias2 = NULL;
 	}
 }
 
-
 PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code)
 {
 	PurplePlugin *prpl;
--- a/libpurple/util.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/util.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1223,6 +1223,8 @@
 		return FALSE;
 
 	q = strstr(p, end_token);
+	if(q == NULL) //yaz
+		return FALSE;
 
 	/* Trim leading blanks */
 	while (*p != '\n' && g_ascii_isspace(*p)) {
@@ -1235,7 +1237,7 @@
 	}
 
 	/* Don't bother with null strings */
-	if (p == q)
+	if (p >= q)
 		return FALSE;
 
 	if (q != NULL && (!no_value_token ||
@@ -2006,6 +2008,20 @@
 }
 
 static gboolean
+is_zenkaku_space(const char *c)
+{
+    gboolean rv = FALSE;
+    const guchar *u = (guchar *)c;
+
+    if(!c || !strcmp(c, "") || strlen(c) < 3)
+        rv = FALSE;
+    else if(*u == 0xe3 && *(u+1) == 0x80 && *(u+2) == 0x80)
+        rv = TRUE;
+
+    return rv;
+}
+
+static gboolean
 badchar(char c)
 {
 	switch (c) {
@@ -2043,6 +2059,7 @@
 	gunichar g;
 	gboolean inside_html = FALSE;
 	int inside_paren = 0;
+	int inside_bracket = 0;
 	GString *ret;
 
 	if (text == NULL)
@@ -2059,6 +2076,12 @@
 			c++;
 		}
 
+		if(*c == '[' && !inside_html) {
+			inside_bracket++;
+			ret = g_string_append_c(ret, *c);
+			c++;
+		}
+
 		if(inside_html) {
 			if(*c == '>') {
 				inside_html = FALSE;
@@ -2086,7 +2109,7 @@
 					(!g_ascii_strncasecmp(c, "https://", 8)))) {
 			t = c;
 			while (1) {
-				if (badchar(*t) || badentity(t)) {
+				if (badchar(*t) || badentity(t) || is_zenkaku_space(t)) {
 
 					if ((!g_ascii_strncasecmp(c, "http://", 7) && (t - c == 7)) ||
 						(!g_ascii_strncasecmp(c, "https://", 8) && (t - c == 8))) {
@@ -2103,6 +2126,9 @@
 					if ((*(t - 1) == ')' && (inside_paren > 0))) {
 						t--;
 					}
+					if ((*(t - 1) == ']' && (inside_bracket > 0))) {
+						t--;
+					}
 
 					url_buf = g_strndup(c, t - c);
 					tmpurlbuf = purple_unescape_html(url_buf);
@@ -2120,7 +2146,7 @@
 			if (c[4] != '.') {
 				t = c;
 				while (1) {
-					if (badchar(*t) || badentity(t)) {
+					if (badchar(*t) || badentity(t) || is_zenkaku_space(t)) {
 						if (t - c == 4) {
 							break;
 						}
@@ -2135,6 +2161,9 @@
 						if ((*(t - 1) == ')' && (inside_paren > 0))) {
 							t--;
 						}
+						if ((*(t - 1) == ']' && (inside_bracket > 0))) {
+							t--;
+						}
 						url_buf = g_strndup(c, t - c);
 						tmpurlbuf = purple_unescape_html(url_buf);
 						g_string_append_printf(ret,
@@ -2151,7 +2180,7 @@
 		} else if (!g_ascii_strncasecmp(c, "ftp://", 6) || !g_ascii_strncasecmp(c, "sftp://", 7)) {
 			t = c;
 			while (1) {
-				if (badchar(*t) || badentity(t)) {
+				if (badchar(*t) || badentity(t) || is_zenkaku_space(t)) {
 
 					if ((!g_ascii_strncasecmp(c, "ftp://", 6) && (t - c == 6)) ||
 						(!g_ascii_strncasecmp(c, "sftp://", 7) && (t - c == 7))) {
@@ -2163,6 +2192,9 @@
 					if ((*(t - 1) == ')' && (inside_paren > 0))) {
 						t--;
 					}
+					if ((*(t - 1) == ']' && (inside_bracket > 0))) {
+						t--;
+					}
 					url_buf = g_strndup(c, t - c);
 					tmpurlbuf = purple_unescape_html(url_buf);
 					g_string_append_printf(ret, "<A HREF=\"%s\">%s</A>",
@@ -2181,7 +2213,7 @@
 			if (c[4] != '.') {
 				t = c;
 				while (1) {
-					if (badchar(*t) || badentity(t)) {
+					if (badchar(*t) || badentity(t) || is_zenkaku_space(t)) {
 						if (t - c == 4) {
 							break;
 						}
@@ -2190,6 +2222,9 @@
 						if ((*(t - 1) == ')' && (inside_paren > 0))) {
 							t--;
 						}
+						if ((*(t - 1) == ']' && (inside_bracket > 0))) {
+							t--;
+						}
 						url_buf = g_strndup(c, t - c);
 						tmpurlbuf = purple_unescape_html(url_buf);
 						g_string_append_printf(ret,
@@ -2208,7 +2243,7 @@
 		} else if (!g_ascii_strncasecmp(c, "mailto:", 7)) {
 			t = c;
 			while (1) {
-				if (badchar(*t) || badentity(t)) {
+				if (badchar(*t) || badentity(t) || is_zenkaku_space(t)) {
 					char *d;
 					if (t - c == 7) {
 						break;
@@ -2242,7 +2277,7 @@
 				   (c == text || badchar(c[-1]) || badentity(c-1))) {
 			t = c;
 			while (1) {
-				if (badchar(*t) || badentity(t)) {
+				if (badchar(*t) || badentity(t) || is_zenkaku_space(t)) {
 
 					if (t - c == 5) {
 						break;
@@ -2258,6 +2293,9 @@
 					if ((*(t - 1) == ')' && (inside_paren > 0))) {
 						t--;
 					}
+					if ((*(t - 1) == ']' && (inside_bracket > 0))) {
+						t--;
+					}
 
 					url_buf = g_strndup(c, t - c);
 					tmpurlbuf = purple_unescape_html(url_buf);
@@ -2345,6 +2383,11 @@
 			ret = g_string_append_c(ret, *c);
 			c++;
 		}
+		if(*c == ']' && !inside_html) {
+			inside_bracket--;
+			ret = g_string_append_c(ret, *c);
+			c++;
+		}
 
 		if (*c == 0)
 			break;
@@ -4849,3 +4892,296 @@
 	}
 #endif
 }
+
+#ifdef _WIN32
+void botch_ucs(gchar *ucs_src, gsize len)
+{
+	/* no operation */
+}
+#else
+void botch_ucs(gchar *ucs_src, gsize len)
+{
+	gint i;
+	guchar *ucs = (guchar *)ucs_src;
+
+	g_return_if_fail(ucs_src != NULL);
+	g_return_if_fail(len > 0);
+
+ 	for(i=0;i<len;i+=2){
+ 		switch(*(ucs+i)){
+ 		case 0x00:
+ 			switch(*(ucs+i+1)){
+ 			case 0xa2:	// ¢
+ 				*(ucs+i) = 0xff;
+ 				*(ucs+i+1) = 0xe0;
+ 				break;
+ 			case 0xa3:	// £
+ 				*(ucs+i) = 0xff;
+				*(ucs+i+1) = 0xe1;
+ 				break;
+ 			case 0xac:	// ¬
+ 				*(ucs+i) = 0xff;
+ 				*(ucs+i+1) = 0xe2;
+ 				break;
+ 			}
+ 			break;
+ 		case 0x20:	// ‖
+ 			if(*(ucs+i+1) == 0x16){
+ 				*(ucs+i) = 0x22;
+				*(ucs+i+1) = 0x25;
+ 			}
+ 			break;
+ 		case 0x22:	// −
+ 			if(*(ucs+i+1) == 0x12){
+ 				*(ucs+i) = 0xff;
+ 				*(ucs+i+1) = 0x0d;
+ 			}
+ 			break;
+ 		case 0x30:	// 〜
+ 			if(*(ucs+i+1) == 0x1c){
+ 				*(ucs+i) = 0xff;
+ 				*(ucs+i+1) = 0x5e;
+ 			}
+ 			break;
+ 		}
+ 	}
+
+}
+#endif
+
+#ifdef _WIN32
+void sanitize_ucs(gchar *ucs, gsize len)
+{
+	/* no operation */
+}
+#else
+void sanitize_ucs(gchar *ucs_src, gsize len)
+{
+	gint i;
+	guchar *ucs = (guchar *)ucs_src;
+
+	g_return_if_fail(ucs_src != NULL);
+	g_return_if_fail(len > 0);
+
+	for(i=0;i<len;i+=2){
+		switch(*(ucs+i)){
+		case 0x22:
+			switch(*(ucs+i+1)){
+			case 0x25:	// ‖
+				*(ucs+i) = 0x20;
+				*(ucs+i+1) = 0x16;
+				break;
+			}
+			break;
+		case 0xff:
+			switch(*(ucs+i+1)){
+			case 0x0d:	// −
+				*(ucs+i) = 0x22;
+				*(ucs+i+1) = 0x12;
+				break;
+			case 0x5e:	// 〜
+				*(ucs+i) = 0x30;
+				*(ucs+i+1) = 0x1c;
+				break;
+			case 0xe0:	// ¢
+				*(ucs+i) = 0x00;
+				*(ucs+i+1) = 0xa2;
+				break;
+			case 0xe1:	// £
+				*(ucs+i) = 0x00;
+				*(ucs+i+1) = 0xa3;
+				break;
+			case 0xe2:	// ¬
+				*(ucs+i) = 0x00;
+				*(ucs+i+1) = 0xac;
+				break;
+			}
+			break;
+		}
+	}
+}
+#endif
+
+#ifdef _WIN32
+gchar *sanitize_utf(const gchar *msg, gsize len, gsize *newlen)
+{
+	g_return_val_if_fail(msg != NULL, NULL);
+	if(len == -1)
+		len = strlen(msg);
+	g_return_val_if_fail(len > 0, NULL);
+
+	if(newlen)
+		*newlen = len;
+
+	return g_strndup(msg, len);
+}
+#else
+gchar *sanitize_utf(const gchar *msg, gsize len, gsize *newlen)
+{
+	gint i;
+	size_t bytes;
+	guchar *utf;
+
+	g_return_val_if_fail(msg != NULL, NULL);
+	if(len == -1)
+		len = strlen(msg);
+	g_return_val_if_fail(len > 0, NULL);
+
+	utf = (guchar *)g_strndup(msg, len);
+
+	bytes = len;
+
+	for(i=0;i<len;i++){
+		switch(*(utf+i)){
+		case 0xe2:
+			if(*(utf+i+1) == 0x88) {
+				if(*(utf+i+2) == 0xa5) {	// ‖
+					*(utf+i) = 0xe2;
+					*(utf+i+1) = 0x80;
+					*(utf+i+2) = 0x96;
+				}
+			}
+			break;
+		case 0xef:
+			switch(*(utf+i+1)){
+			case 0xbc:
+				if(*(utf+i+2) == 0x8d) {	// −
+					*(utf+i) = 0xe2;
+					*(utf+i+1) = 0x88;
+					*(utf+i+2) = 0x92;
+				}
+				break;
+			case 0xbd:
+				if(*(utf+i+2) == 0x9e) {	// 〜
+					*(utf+i) = 0xe3;
+					*(utf+i+1) = 0x80;
+					*(utf+i+2) = 0x9c;
+				}
+				break;
+			case 0xbf:
+				switch(*(utf+i+2)){
+			       case 0xa0:	// ¢
+				       *(utf+i) = 0xc2;
+				       *(utf+i+1) = 0xa2;
+				       memmove(utf+i+2, utf+i+3,
+					       len-i-3); //shorten by 1byte
+				       bytes--;
+				       break;
+			       case 0xa1:	// £
+				       *(utf+i) = 0xc2;
+				       *(utf+i+1) = 0xa3;
+				       memmove(utf+i+2, utf+i+3,
+					       len-i-3); //shorten by 1byte
+				       bytes--;
+				       break;
+			       case 0xa2:	// ¬
+				       *(utf+i) = 0xc2;
+				       *(utf+i+1) = 0xac;
+				       memmove(utf+i+2, utf+i+3,
+					       len-i-3); //shorten by 1byte
+				       bytes--;
+				       break;
+			       }
+			       break;
+			}
+			break;
+		}
+	}
+	*(utf+bytes)= 0x00; //terminate
+	if(newlen)
+		*newlen = bytes;
+	return (gchar *)utf;
+}
+#endif
+
+#ifdef _WIN32
+gchar *botch_utf(const gchar *msg, gsize len, gsize *newlen)
+{
+	g_return_val_if_fail(msg != NULL, NULL);
+	if(len == -1)
+		len = strlen(msg);
+	g_return_val_if_fail(len > 0, NULL);
+
+	if(newlen)
+		*newlen = len;
+
+	return g_strndup(msg, len);
+}
+#else
+gchar *botch_utf(const gchar *msg, gsize len, gsize *newlen)
+{
+ 	int i,bytes;
+	unsigned char *utf;
+
+	g_return_val_if_fail(msg != NULL, NULL);
+	if(len == -1)
+		len = strlen(msg);
+	g_return_val_if_fail(len > 0, NULL);
+
+	bytes = len;
+
+	utf = g_malloc0(bytes*3/2+1); /* new length might be 3/2 in the worst case */
+	memcpy(utf, msg, bytes);
+
+ 	for(i=0;i<bytes;i++){
+ 		switch(*(utf+i)){
+ 		case 0xc2:
+ 			switch(*(utf+i+1)){
+ 			case 0xa2:	// ¢
+ 				*(utf+i) = 0xef;
+ 				*(utf+i+1) = 0xbf;
+				memmove(utf+i+3, utf+i+2, bytes-i-2);
+				*(utf+i+2) = 0xa0;
+				bytes++;
+ 				break;
+ 			case 0xa3:	// £
+ 				*(utf+i) = 0xef;
+ 				*(utf+i+1) = 0xbf;
+				memmove(utf+i+3, utf+i+2, bytes-i-2);
+				*(utf+i+2) = 0xa1;
+				bytes++;
+ 				break;
+ 			case 0xac:	// ¬
+ 				*(utf+i) = 0xef;
+ 				*(utf+i+1) = 0xbf;
+				memmove(utf+i+3, utf+i+2, bytes-i-2);
+				*(utf+i+2) = 0xa2;
+				bytes++;
+ 				break;
+ 			}
+ 			break;
+ 		case 0xe2:
+			switch(*(utf+i+1)){
+			case 0x80:	// ‖
+				if(*(utf+i+2) == 0x96){
+					*(utf+i) = 0xe2;
+					*(utf+i+1) = 0x88;
+					*(utf+i+2) = 0xa5;
+				}
+				break;
+			case 0x88:	// −
+				if(*(utf+i+1) == 0x92){
+					*(utf+i) = 0xef;
+					*(utf+i+1) = 0xbc;
+					*(utf+i+2) = 0x8d;
+				}
+				break;
+			}
+			break;
+ 		case 0xe3:	// 〜
+ 			if(*(utf+i+1) == 0x80){
+				if(*(utf+i+2) == 0x9c){
+					*(utf+i) = 0xef;
+					*(utf+i+1) = 0xbd;
+					*(utf+i+2) = 0x9e;
+				}
+ 			}
+ 			break;
+ 		} //switch
+ 	}
+	*(utf+bytes) = 0x00; //terminate
+	if(newlen)
+		*newlen = bytes;
+	return (gchar *)utf;
+}
+#endif
--- a/libpurple/util.h	Thu Apr 23 20:05:26 2009 +0000
+++ b/libpurple/util.h	Fri Apr 24 07:43:08 2009 +0000
@@ -1340,4 +1340,10 @@
 }
 #endif
 
+/* to address incompatibility with cp932. */
+void botch_ucs(gchar *ucs, gsize len);
+void sanitize_ucs(gchar *ucs, gsize len);
+gchar *botch_utf(const gchar *utf, gsize len, gsize *newlen);
+gchar *sanitize_utf(const gchar *msg, gsize len, gsize *newlen);
+
 #endif /* _PURPLE_UTIL_H_ */
--- a/pidgin/gtkblist.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkblist.c	Fri Apr 24 07:43:08 2009 +0000
@@ -72,6 +72,11 @@
 
 #define HEADLINE_CLOSE_SIZE 11
 
+/* I noticed that some of short cuts are very annoying.
+   If you really want to use them, change this to 1. --yaz
+*/
+#define ENABLE_SHORTCUT 0
+
 typedef struct
 {
 	PurpleAccount *account;
@@ -3384,6 +3389,7 @@
 	{ N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 3, "<Item>", NULL },
 	{ "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Tools/Mute _Sounds"), NULL, pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
+
 	/* Help */
 	{ N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL },
 	{ N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP },
--- a/pidgin/gtkconv.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkconv.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1,3 +1,4 @@
+/* -*- coding: utf-8 -*- */
 /**
  * @file gtkconv.c GTK+ Conversation API
  * @ingroup pidgin
@@ -120,6 +121,10 @@
 static GdkColor *nick_colors = NULL;
 static guint nbr_nick_colors;
 
+/* yaz. If you want to use shortcut keys that may conflict with
+   inputmethods, change this to 1. */
+#define ENABLE_SHORTCUT 0
+
 typedef struct {
 	GtkWidget *window;
 
@@ -274,6 +279,43 @@
 	return FALSE;
 }
 
+static gboolean
+size_allocate_cb(GtkWidget *w, GtkAllocation *allocation, PidginConversation *gtkconv)
+{
+	PurpleConversation *conv = gtkconv->active_conv;
+
+	if (!GTK_WIDGET_VISIBLE(w))
+		return FALSE;
+
+	if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
+		return FALSE;
+	if (gtkconv->auto_resize) {
+		return FALSE;
+	}
+
+	if (gdk_window_get_state(gtkconv->win->window->window) & GDK_WINDOW_STATE_MAXIMIZED) {
+		return FALSE;
+	}
+
+	/* I find that I resize the window when it has a bunch of conversations in it, mostly so that the
+	 * tab bar will fit, but then I don't want new windows taking up the entire screen.  I check to see
+	 * if there is only one conversation in the window.  This way we'll be setting new windows to the
+	 * size of the last resized new window. */
+	/* I think that the above justification is not the majority, and that the new tab resizing should
+	 * negate it anyway.  --luke */
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
+	{
+		if (w == gtkconv->lower_hbox)
+			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", allocation->height);
+	}
+	else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
+	{
+		if (w == gtkconv->lower_hbox)
+			purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", allocation->height);
+	}
+	return FALSE;
+}
+
 static void
 default_formatize(PidginConversation *c)
 {
@@ -424,6 +466,20 @@
 	gtkconv->send_history = g_list_prepend(first, NULL);
 }
 
+#if 0
+static void
+reset_default_size(PidginConversation *gtkconv)
+{
+	PurpleConversation *conv = gtkconv->active_conv;
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
+		gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
+					    purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height"));
+	else
+		gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
+					    purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
+}
+#endif
+
 static gboolean
 check_for_and_do_command(PurpleConversation *conv)
 {
@@ -3122,13 +3178,21 @@
 
 	{ "/Conversation/sep0", NULL, NULL, 0, "<Separator>", NULL },
 
+#if ENABLE_SHORTCUT
 	{ N_("/Conversation/_Find..."), NULL, menu_find_cb, 0,
 			"<StockItem>", GTK_STOCK_FIND },
+#else
+	{ N_("/Conversation/_Find..."), NULL, menu_find_cb, 0,
+      "<Item>", NULL },
+#endif
 	{ N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "<Item>", NULL },
 	{ N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0,
 			"<StockItem>", GTK_STOCK_SAVE_AS },
+#if ENABLE_SHORTCUT
 	{ N_("/Conversation/Clea_r Scrollback"), "<CTL>L", menu_clear_cb, 0, "<StockItem>", GTK_STOCK_CLEAR },
-
+#else
+	{ N_("/Conversation/Clea_r Scrollback"), NULL, menu_clear_cb, 0, "<Item>", NULL },
+#endif
 	{ "/Conversation/sep1", NULL, NULL, 0, "<Separator>", NULL },
 
 #ifdef USE_VV
@@ -3145,8 +3209,13 @@
 	{ N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "<StockItem>", PIDGIN_STOCK_TOOLBAR_SEND_FILE },
 	{ N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb,
 			0, "<Item>", NULL },
+#if ENABLE_SHORTCUT
 	{ N_("/Conversation/_Get Info"), "<CTL>O", menu_get_info_cb, 0,
 			"<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO },
+#else
+	{ N_("/Conversation/_Get Info"), NULL, menu_get_info_cb, 0,
+			"<StockItem>", PIDGIN_STOCK_TOOLBAR_USER_INFO },
+#endif
 	{ N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0,
 			"<Item>", NULL },
 	{ N_("/Conversation/M_ore"), NULL, NULL, 0, "<Branch>", NULL },
@@ -3871,7 +3940,11 @@
 		gtk_widget_destroy(win->menu.send_to);
 
 	/* Build the Send To menu */
+#if ENABLE_SHORTCUT
 	win->menu.send_to = gtk_menu_item_new_with_mnemonic(_("S_end To"));
+#else
+	win->menu.send_to = gtk_menu_item_new_with_mnemonic(_("Send To")); //to free Alt-s. intentional. --yaz
+#endif
 	gtk_widget_show(win->menu.send_to);
 
 	menu = gtk_menu_new();
@@ -4301,6 +4374,7 @@
 	PidginChatPane *gtkchat;
 	char *new_topic;
 	const char *current_topic;
+	char dummy[] = "No Topic";
 
 	gc      = purple_conversation_get_gc(conv);
 
@@ -4320,7 +4394,7 @@
 		return;
 	}
 
-	gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), current_topic);
+	gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), current_topic ? current_topic : dummy);
 	prpl_info->set_chat_topic(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
 			new_topic);
 
@@ -4596,12 +4670,10 @@
 	height = CLAMP(height, MIN(min_height, max_height), max_height);
 
 	diff = height - gtkconv->entry->allocation.height;
-	if (ABS(diff) < oneline.height / 2)
+	if (diff == 0 || (diff < 0 && -diff < oneline.height / 2))
 		return FALSE;
-
 	gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
-		diff + gtkconv->lower_hbox->allocation.height);
-
+				    diff + gtkconv->lower_hbox->allocation.height);
 	return FALSE;
 }
 
@@ -4816,7 +4888,7 @@
 static GtkWidget *
 setup_common_pane(PidginConversation *gtkconv)
 {
-	GtkWidget *vbox, *frame, *imhtml_sw, *event_box;
+	GtkWidget *paned, *vbox, *frame, *imhtml_sw, *event_box;
 	GtkCellRenderer *rend;
 	GtkTreePath *path;
 	PurpleConversation *conv = gtkconv->active_conv;
@@ -4825,8 +4897,12 @@
 	GtkPolicyType imhtml_sw_hscroll;
 	int buddyicon_size = 0;
 
+	paned = gtk_vpaned_new();
+	gtk_widget_show(paned);
+
 	/* Setup the top part of the pane */
 	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
 	gtk_widget_show(vbox);
 
 	/* Setup the info pane */
@@ -4930,18 +5006,30 @@
 	g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event",
 	                 G_CALLBACK(refocus_entry_cb), gtkconv);
 
+	/* Setup the bottom half of the conversation window */
+	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_paned_pack2(GTK_PANED(paned), vbox, FALSE, TRUE);
+	gtk_widget_show(vbox);
+
 	gtkconv->lower_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), gtkconv->lower_hbox, TRUE, TRUE, 0);
 	gtk_widget_show(gtkconv->lower_hbox);
 
+	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
+	gtk_box_pack_end(GTK_BOX(gtkconv->lower_hbox), vbox, TRUE, TRUE, 0);
+	gtk_widget_show(vbox);
+
 	/* Setup the toolbar, entry widget and all signals */
 	frame = pidgin_create_imhtml(TRUE, &gtkconv->entry, &gtkconv->toolbar, NULL);
-	gtk_box_pack_start(GTK_BOX(gtkconv->lower_hbox), frame, TRUE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 	gtk_widget_show(frame);
 
 	gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
 	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
 			purple_account_get_protocol_name(conv->account));
+	gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
+			chat ? purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height") :
+			purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height"));
 
 	g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
 	                 G_CALLBACK(entry_popup_menu_cb), gtkconv);
@@ -4951,6 +5039,8 @@
 	                       G_CALLBACK(send_cb), gtkconv);
 	g_signal_connect_after(G_OBJECT(gtkconv->entry), "button_press_event",
 	                       G_CALLBACK(entry_stop_rclick_cb), NULL);
+	g_signal_connect(G_OBJECT(gtkconv->lower_hbox), "size-allocate",
+	                 G_CALLBACK(size_allocate_cb), gtkconv);
 
 	gtkconv->entry_buffer =
 		gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
@@ -4975,7 +5065,7 @@
 	default_formatize(gtkconv);
 	g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear",
 	                       G_CALLBACK(clear_formatting_cb), gtkconv);
-	return vbox;
+	return paned;
 }
 
 static void
@@ -6666,6 +6756,9 @@
 		AtkObject *accessibility_obj;
 		/* I think this is a little longer than it needs to be but I'm lazy. */
 		char *style;
+		gboolean ellipsis;
+		int side;
+		char *tab_title = NULL;
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 			im = PURPLE_CONV_IM(conv);
@@ -6760,8 +6853,26 @@
 			style = NULL;
 		}
 
+		// nosuke's tab width patch
+		side = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side");
+		side &= ~8; 
+		if ( (side == GTK_POS_LEFT || side == GTK_POS_RIGHT) &&
+		     purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/trim_vertical_tabs") )
+			ellipsis = TRUE;
+		else
+			ellipsis = FALSE;
+
+		if (ellipsis) {
+			tab_title = pidgin_gtk_ellipsis_text(gtkconv->tab_label, title, 60, "...");
+		}
+		else {
+			tab_title = g_strdup(title);
+		}
+
 		gtk_widget_set_name(gtkconv->tab_label, style);
-		gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title);
+		gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), tab_title);
+		g_free(tab_title); tab_title = NULL;
+
 		gtk_widget_set_state(gtkconv->tab_label, GTK_STATE_ACTIVE);
 
 		if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT ||
@@ -7180,6 +7291,24 @@
 	return page_num;
 }
 
+//nosuke
+static void
+trim_vertical_tabs_pref_cb(const char *name, PurplePrefType type,
+						   gconstpointer value, gpointer data)
+{
+	GList *l;
+	PurpleConversation *conv;
+
+	for (l = purple_get_conversations(); l != NULL; l = l->next) {
+		conv = (PurpleConversation *)l->data;
+
+		if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv))
+			continue;
+
+		pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE);
+	}
+}
+
 static void
 close_on_tabs_pref_cb(const char *name, PurplePrefType type,
 					  gconstpointer value, gpointer data)
@@ -7249,6 +7378,7 @@
 			pidgin_conv_tab_pack(gtkwin, gtkconvs->data);
 		}
 	}
+	trim_vertical_tabs_pref_cb(name, type, value, data);
 }
 
 static void
@@ -7307,7 +7437,7 @@
 		else
 			gtk_widget_hide(gtkconv->toolbar);
 
-		g_idle_add((GSourceFunc)resize_imhtml_cb,gtkconv);
+//		g_idle_add((GSourceFunc)resize_imhtml_cb,gtkconv);
 	}
 }
 
@@ -7814,6 +7944,7 @@
 	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations");
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE);
+	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/trim_vertical_tabs", FALSE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE);
@@ -7868,6 +7999,8 @@
 	/* Connect callbacks. */
 	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/close_on_tabs",
 								close_on_tabs_pref_cb, NULL);
+	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/trim_vertical_tabs",
+								  trim_vertical_tabs_pref_cb, NULL);
 	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_timestamps",
 								show_timestamps_pref_cb, NULL);
 	purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar",
--- a/pidgin/gtkimhtml.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkimhtml.c	Fri Apr 24 07:43:08 2009 +0000
@@ -111,6 +111,10 @@
                            gint              y,
                            guint             time);
 
+/* yaz. If you want to use shortcut keys that may conflict with
+   inputmethods, change this to 1. */
+#define ENABLE_SHORTCUT 0
+
 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml);
 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml);
 static void delete_cb(GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextIter *end, GtkIMHtml *imhtml);
@@ -504,10 +508,11 @@
 static gint
 gtk_imhtml_tip (gpointer data)
 {
-	GtkIMHtml *imhtml = data;
+	GtkIMHtml *imhtml = (GtkIMHtml *)data;
 	PangoFontMetrics *font_metrics;
 	PangoLayout *layout;
 	PangoFont *font;
+	PangoLanguage *lang;
 
 	gint gap, x, y, h, w, scr_w, baseline_skip;
 
@@ -553,7 +558,9 @@
 		return FALSE;
 	}
 
-	font_metrics = pango_font_get_metrics(font, NULL);
+	lang = pango_context_get_language (pango_layout_get_context(layout));
+	font_metrics = pango_font_get_metrics(font, lang); //it's ok.
+//	font_metrics = pango_font_get_metrics(font, NULL); //crash!
 
 	pango_layout_get_pixel_size(layout, &scr_w, NULL);
 	gap = PANGO_PIXELS((pango_font_metrics_get_ascent(font_metrics) +
@@ -666,14 +673,12 @@
 		tip = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_tiptext");
 		hand = FALSE;
 	}
-
 	if (tip && *tip) {
 		if (!GTK_IMHTML(imhtml)->editable && hand)
 			gdk_window_set_cursor(win, GTK_IMHTML(imhtml)->hand_cursor);
 		GTK_IMHTML(imhtml)->tip_timer = g_timeout_add (TOOLTIP_TIMEOUT,
 							       gtk_imhtml_tip, imhtml);
 	}
-
 	GTK_IMHTML(imhtml)->tip = tip;
 	g_slist_free(tags);
 	return FALSE;
@@ -1029,18 +1034,25 @@
 	if (info == TARGET_HTML) {
 		char *selection;
 #ifndef _WIN32
-		gsize len;
 		if (primary) {
 			text = gtk_imhtml_get_markup_range(imhtml, &start, &end);
 		} else
 			text = html_clipboard;
 
-		/* Mozilla asks that we start our text/html with the Unicode byte order mark */
-		selection = g_convert(text, -1, "UTF-16", "UTF-8", NULL, &len, NULL);
-		gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE), 16, (const guchar *)selection, len);
-#else
+		selection = NULL;
+		if (primary) {
+			text = gtk_imhtml_get_markup_range(imhtml, &start, &end);
+		} else {
+			text = html_clipboard;
+		}
+		/* xxx should remove following line --yaz */
+		purple_debug_info("imhtml clipboard", "html_clipboard: %s len = %d\n", text, strlen(text));
+		gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE),
+				       8, (const guchar *)text, strlen(text)+1); // include trailing '\0' --yaz
+#else /*_WIN32 */
 		selection = clipboard_html_to_win32(html_clipboard);
-		gtk_selection_data_set(selection_data, gdk_atom_intern("HTML Format", FALSE), 8, (const guchar *)selection, strlen(selection));
+		gtk_selection_data_set(selection_data, gdk_atom_intern("HTML Format", FALSE),
+				       8, (const guchar *)selection, strlen(selection));
 #endif
 		g_free(selection);
 	} else {
@@ -1191,7 +1203,8 @@
 	if (selection_data->length >= 2 &&
 		(*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe)) {
 		/* This is UTF-16 */
-		char *utf8 = utf16_to_utf8_with_bom_check(text, selection_data->length);
+//		char *utf8 = utf16_to_utf8_with_bom_check(text, selection_data->length);
+		char *utf8 = g_convert(text, selection_data->length, "UTF-8", "UTF-16", NULL, NULL, NULL);
 		g_free(text);
 		text = utf8;
 		if (!text) {
@@ -1926,7 +1939,8 @@
 			 * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html
 			 */
 			if (sd->length >= 2 && !g_utf8_validate(text, sd->length - 1, NULL)) {
-				utf8 = utf16_to_utf8_with_bom_check(text, sd->length);
+//				utf8 = utf16_to_utf8_with_bom_check(text, sd->length);
+				utf8 = g_convert(text, sd->length, "UTF-8", "UTF-16", NULL, NULL, NULL);
 
 				if (!utf8) {
 					purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in drag_rcv_cb\n");
@@ -3361,6 +3375,7 @@
 			break;
 		}
 	}
+	ws[wpos] = '\0'; // chop ws at wpos. due to bug of gtk_text_buffer_insert() --yaz
 	gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos);
 	ws[0] = '\0'; wpos = 0;
 
--- a/pidgin/gtkimhtmltoolbar.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1432,7 +1432,7 @@
 	gtk_container_add(GTK_CONTAINER(smiley_button), bbox);
 	image = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
 	gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0);
-	label = gtk_label_new_with_mnemonic(_("_Smile!"));
+	label = gtk_label_new_with_mnemonic(_("Smile!"));
 	gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(box), smiley_button, FALSE, FALSE, 0);
 	g_signal_connect_swapped(G_OBJECT(smiley_button), "clicked", G_CALLBACK(gtk_button_clicked), toolbar->smiley);
--- a/pidgin/gtkimhtmltoolbar.h	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkimhtmltoolbar.h	Fri Apr 24 07:43:08 2009 +0000
@@ -30,7 +30,7 @@
 extern "C" {
 #endif
 
-#define DEFAULT_FONT_FACE "Helvetica 12"
+#define DEFAULT_FONT_FACE "Sans 12"
 
 #define GTK_TYPE_IMHTMLTOOLBAR            (gtk_imhtmltoolbar_get_type())
 #define GTK_IMHTMLTOOLBAR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_IMHTMLTOOLBAR, GtkIMHtmlToolbar))
--- a/pidgin/gtknotify.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtknotify.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1175,12 +1175,15 @@
 pidgin_notify_uri(const char *uri)
 {
 #ifndef _WIN32
-	char *escaped = g_shell_quote(uri);
+	char *tmp = g_shell_quote(uri);
+	char *escaped = g_locale_from_utf8(tmp, -1, NULL, NULL, NULL);
 	char *command = NULL;
 	char *remote_command = NULL;
 	const char *web_browser;
 	int place;
 
+	g_free(tmp);
+
 	web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser");
 	place = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/browsers/place");
 
--- a/pidgin/gtkprefs.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkprefs.c	Fri Apr 24 07:43:08 2009 +0000
@@ -1263,6 +1263,9 @@
 	pidgin_prefs_checkbox(_("Show close b_utton on tabs"),
 				PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", vbox2);
 
+	pidgin_prefs_checkbox(_("Trim names on vertical tabs"),
+				PIDGIN_PREFS_ROOT "/conversations/trim_vertical_tabs", vbox2);
+
 	label = pidgin_prefs_dropdown(vbox2, _("_Placement:"), PURPLE_PREF_INT,
 					PIDGIN_PREFS_ROOT "/conversations/tab_side",
 					_("Top"), GTK_POS_TOP,
@@ -1349,7 +1352,7 @@
 #endif
 
 	pidgin_prefs_checkbox(_("Use smooth-scrolling"), PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", vbox);
-
+	pidgin_prefs_checkbox(_("Use msn messenger style"), "/purple/conversations/msnstyle", vbox);//yaz
 #ifdef _WIN32
 	pidgin_prefs_checkbox(_("F_lash window when IMs are received"), PIDGIN_PREFS_ROOT "/win32/blink_im", vbox);
 
--- a/pidgin/gtkutils.c	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkutils.c	Fri Apr 24 07:43:08 2009 +0000
@@ -3677,3 +3677,61 @@
 	gtk_imhtml_class_register_protocol("gopher://", NULL, NULL);
 }
 
+gchar *
+pidgin_gtk_ellipsis_text(GtkWidget *widget, const char *text, gint min_width, gchar *ellipsis)
+{
+	PangoLayout *layout;
+	gint width, height;
+	gint ewidth;
+	glong len0, len1, len2;
+	gchar *buf, *buf_tmp;
+	gboolean with_ellipsis = FALSE;
+	const gchar default_ellipsis[] = "...";
+
+	if(!ellipsis)
+		ellipsis = default_ellipsis;
+
+	/* allocate buf */
+	buf = g_malloc0(strlen(text) * 2);
+
+	/* create layout */
+	layout = gtk_widget_create_pango_layout(widget, ellipsis);
+	pango_layout_get_pixel_size(layout, &width, &height);
+	ewidth = width; /* length of ellipsis text. */
+
+	len0 = 0;
+	len1 = g_utf8_strlen(text, -1);
+	len2 = len1;
+
+	while (1) {
+
+		if (len2 == len0)
+			break;
+
+		g_utf8_strncpy(buf, text, len2);
+		pango_layout_set_text(layout, buf, -1);
+		pango_layout_get_pixel_size(layout, &width, &height);
+
+		if(!with_ellipsis && width <= min_width)
+			break;
+		else
+			with_ellipsis = TRUE;
+
+		if (width + ewidth > min_width)
+			len1 = len2;
+		else
+			len0 = len2;
+
+		len2 = (len0 + len1) / 2;
+	}
+
+	g_object_unref(layout);
+
+	if (with_ellipsis) {
+		buf_tmp = buf;
+		buf = g_strdup_printf("%s%s", buf_tmp, ellipsis);
+		g_free(buf_tmp);
+	}
+
+	return buf;
+}
--- a/pidgin/gtkutils.h	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/gtkutils.h	Fri Apr 24 07:43:08 2009 +0000
@@ -838,5 +838,7 @@
  */
 void pidgin_utils_uninit(void);
 
+gchar *pidgin_gtk_ellipsis_text(GtkWidget *widget, const char *text, gint min_width, gchar *ellipsis);
+
 #endif /* _PIDGINUTILS_H_ */
 
--- a/pidgin/pixmaps/icons/hicolor/48x48/apps/scalable/pidgin.svg	Thu Apr 23 20:05:26 2009 +0000
+++ b/pidgin/pixmaps/icons/hicolor/48x48/apps/scalable/pidgin.svg	Fri Apr 24 07:43:08 2009 +0000
@@ -23,12 +23,55 @@
   <defs
      id="defs4347">
     <linearGradient
+       inkscape:collect="always"
+       id="linearGradient9905">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop9907" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop9909" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient9893">
+      <stop
+         style="stop-color:#ff2de9;stop-opacity:1;"
+         offset="0"
+         id="stop9895" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.498"
+         offset="1"
+         id="stop9897" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9689"
+       inkscape:collect="always">
+      <stop
+         id="stop9691"
+         offset="0"
+         style="stop-color:#ffb547;stop-opacity:1" />
+      <stop
+         id="stop9693"
+         offset="1"
+         style="stop-color:#e56600;stop-opacity:1" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective100" />
+    <linearGradient
        id="linearGradient8744"
        inkscape:collect="always">
       <stop
          id="stop8746"
          offset="0"
-         style="stop-color:#7a1d90;stop-opacity:1" />
+         style="stop-color:#162c5e;stop-opacity:1" />
       <stop
          id="stop8748"
          offset="1"
@@ -38,7 +81,7 @@
        inkscape:collect="always"
        id="linearGradient8732">
       <stop
-         style="stop-color:#6b3678;stop-opacity:1;"
+         style="stop-color:#262f65;stop-opacity:1"
          offset="0"
          id="stop8734" />
       <stop
@@ -50,11 +93,11 @@
        inkscape:collect="always"
        id="linearGradient8904">
       <stop
-         style="stop-color:#729fcf;stop-opacity:1;"
+         style="stop-color:#649fdd;stop-opacity:1"
          offset="0"
          id="stop8906" />
       <stop
-         style="stop-color:#25486d;stop-opacity:1"
+         style="stop-color:#184779;stop-opacity:1"
          offset="1"
          id="stop8908" />
     </linearGradient>
@@ -66,7 +109,7 @@
          offset="0"
          id="stop8886" />
       <stop
-         style="stop-color:#6b3e75;stop-opacity:1"
+         style="stop-color:#3c2375;stop-opacity:1"
          offset="1"
          id="stop8888" />
     </linearGradient>
@@ -78,24 +121,12 @@
          offset="0"
          id="stop8878" />
       <stop
-         style="stop-color:#744380;stop-opacity:1"
+         style="stop-color:#472d7e;stop-opacity:1"
          offset="1"
          id="stop8880" />
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       id="linearGradient8868">
-      <stop
-         style="stop-color:#3b1941;stop-opacity:1;"
-         offset="0"
-         id="stop8870" />
-      <stop
-         style="stop-color:#a646b7;stop-opacity:1"
-         offset="1"
-         id="stop8872" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
        id="linearGradient8860">
       <stop
          style="stop-color:#3b1941;stop-opacity:1;"
@@ -107,18 +138,6 @@
          id="stop8864" />
     </linearGradient>
     <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8848">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop8850" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1"
-         offset="1"
-         id="stop8852" />
-    </linearGradient>
-    <linearGradient
        id="linearGradient8820"
        inkscape:collect="always">
       <stop
@@ -170,7 +189,7 @@
        inkscape:collect="always"
        id="linearGradient2826">
       <stop
-         style="stop-color:#3b1941;stop-opacity:1;"
+         style="stop-color:#552b72;stop-opacity:1"
          offset="0"
          id="stop2828" />
       <stop
@@ -186,7 +205,7 @@
          offset="0"
          id="stop2818" />
       <stop
-         style="stop-color:#eeeeec;stop-opacity:0;"
+         style="stop-color:#b077ee;stop-opacity:1"
          offset="1"
          id="stop2820" />
     </linearGradient>
@@ -198,7 +217,7 @@
          offset="0"
          id="stop6539" />
       <stop
-         style="stop-color:#d3e1f1;stop-opacity:1"
+         style="stop-color:#cce1f9;stop-opacity:1"
          offset="1"
          id="stop6541" />
     </linearGradient>
@@ -206,7 +225,7 @@
        inkscape:collect="always"
        id="linearGradient6506">
       <stop
-         style="stop-color:#ffffff;stop-opacity:0.95477384"
+         style="stop-color:#ffffff;stop-opacity:1"
          offset="0"
          id="stop6508" />
       <stop
@@ -214,26 +233,16 @@
          offset="1"
          id="stop6510" />
     </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6506"
-       id="linearGradient6512"
-       x1="15.645709"
-       y1="40.668503"
-       x2="15.645709"
-       y2="47.022106"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1,0,0,0.988192,1.5624997,-2.39645)" />
     <radialGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2816"
        id="radialGradient2824"
-       cx="14.930223"
-       cy="25.801632"
-       fx="14.930223"
-       fy="25.801632"
+       cx="14.914475"
+       cy="26.467632"
+       fx="14.914475"
+       fy="26.467632"
        r="16.390338"
-       gradientTransform="matrix(1.3364897,0,0,1.3894845,-0.759152,-10.711989)"
+       gradientTransform="matrix(0.6426095,-5.3927465e-3,6.3214714e-3,0.753278,9.3247223,4.0470884)"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
@@ -242,7 +251,7 @@
        x1="13.191773"
        y1="41.606163"
        x2="13.191773"
-       y2="49.067719"
+       y2="48.688236"
        gradientUnits="userSpaceOnUse"
        gradientTransform="matrix(1,0,0,0.988192,1.4473537,-2.486208)" />
     <linearGradient
@@ -257,7 +266,7 @@
        gradientTransform="matrix(1,0,0,0.988192,1.4473537,-2.486208)" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient8686"
+       xlink:href="#linearGradient9689"
        id="linearGradient8692"
        x1="18.5"
        y1="29.911009"
@@ -305,24 +314,6 @@
        y2="30.188351" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient8848"
-       id="linearGradient8854"
-       x1="10.48653"
-       y1="25.21174"
-       x2="9.7512932"
-       y2="23.675837"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8848"
-       id="linearGradient8858"
-       gradientUnits="userSpaceOnUse"
-       x1="10.498732"
-       y1="24.936121"
-       x2="9.6415968"
-       y2="23.675837" />
-    <linearGradient
-       inkscape:collect="always"
        xlink:href="#linearGradient8860"
        id="linearGradient8866"
        x1="13.061977"
@@ -333,31 +324,21 @@
        gradientTransform="matrix(1.50247,0,0,1,-6.5946403,-2.139701)" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient8868"
-       id="linearGradient8874"
-       x1="12.409452"
-       y1="10.602999"
-       x2="16.140554"
-       y2="13.895189"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.236264,0,0,0.549587,-5.4828863,3.775206)" />
-    <linearGradient
-       inkscape:collect="always"
        xlink:href="#linearGradient8876"
        id="linearGradient8882"
        x1="10.46875"
-       y1="25.3125"
-       x2="9.53125"
-       y2="19.6875"
+       y1="26.726713"
+       x2="9.7964153"
+       y2="19.333946"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient8884"
        id="linearGradient8890"
-       x1="23.881994"
-       y1="24.343237"
+       x1="24.973602"
+       y1="24.961956"
        x2="24.973602"
-       y2="19.216713"
+       y2="18.863159"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
@@ -396,6 +377,323 @@
        y1="4.8871226"
        x2="30.5"
        y2="22.781603" />
+    <inkscape:perspective
+       id="perspective7946"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8860"
+       id="radialGradient8780"
+       cx="12.809438"
+       cy="7.5702162"
+       fx="12.809438"
+       fy="7.5702162"
+       r="5.140625"
+       gradientTransform="matrix(1,0,0,0.4138305,0,5.4390103)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.4138305,0,5.4390103)"
+       r="5.140625"
+       fy="7.5702162"
+       fx="12.809438"
+       cy="7.5702162"
+       cx="12.809438"
+       id="radialGradient9297"
+       xlink:href="#linearGradient8860"
+       inkscape:collect="always" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective9295" />
+    <linearGradient
+       y2="22.781603"
+       x2="30.5"
+       y1="4.8871226"
+       x1="30.5"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient9293"
+       xlink:href="#linearGradient6537"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(-1,0,0,1,37.022732,0)"
+       y2="43.352409"
+       x2="4.0852318"
+       y1="40.416641"
+       x1="4.0852318"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient9291"
+       xlink:href="#linearGradient8732"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="44.321774"
+       x2="4.0852318"
+       y1="39.097038"
+       x1="4.0852318"
+       id="linearGradient9289"
+       xlink:href="#linearGradient8744"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="33.678783"
+       x2="41.875"
+       y1="1.8037834"
+       x1="26.125"
+       id="linearGradient9287"
+       xlink:href="#linearGradient8904"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="18.863159"
+       x2="24.973602"
+       y1="24.961956"
+       x1="24.973602"
+       id="linearGradient9285"
+       xlink:href="#linearGradient8884"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="19.333946"
+       x2="9.7964153"
+       y1="26.726713"
+       x1="10.46875"
+       id="linearGradient9283"
+       xlink:href="#linearGradient8876"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.50247,0,0,1,-6.5946403,-2.139701)"
+       gradientUnits="userSpaceOnUse"
+       y2="12.891665"
+       x2="16.545418"
+       y1="10.027351"
+       x1="13.061977"
+       id="linearGradient9281"
+       xlink:href="#linearGradient8860"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="23.675837"
+       x2="9.6415968"
+       y1="24.936121"
+       x1="10.498732"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient8858"
+       xlink:href="#linearGradient8848"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="23.675837"
+       x2="9.7512932"
+       y1="25.21174"
+       x1="10.48653"
+       id="linearGradient8854"
+       xlink:href="#linearGradient8848"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="30.188351"
+       x2="18.143806"
+       y1="29.494703"
+       x1="17.969458"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient9277"
+       xlink:href="#linearGradient8808"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="30.431053"
+       x2="18.031723"
+       y1="29.338558"
+       x1="18.339697"
+       id="linearGradient9275"
+       xlink:href="#linearGradient8820"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.0769231,0,0,1.1428571,-0.905101,-4.6800586)"
+       gradientUnits="userSpaceOnUse"
+       y2="29.853554"
+       x2="19.985121"
+       y1="29.911009"
+       x1="18.5"
+       id="linearGradient9265"
+       xlink:href="#linearGradient8686"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1,0,0,0.988192,1.4473537,-2.486208)"
+       gradientUnits="userSpaceOnUse"
+       y2="47.757988"
+       x2="11.373499"
+       y1="43.444576"
+       x1="11.373499"
+       id="linearGradient9263"
+       xlink:href="#linearGradient2834"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1,0,0,0.988192,1.4473537,-2.486208)"
+       gradientUnits="userSpaceOnUse"
+       y2="49.067719"
+       x2="13.191773"
+       y1="41.606163"
+       x1="13.191773"
+       id="linearGradient9261"
+       xlink:href="#linearGradient2826"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.6426095,-5.3927465e-3,6.3214714e-3,0.753278,9.3247223,4.0470884)"
+       r="16.390338"
+       fy="26.467632"
+       fx="14.914475"
+       cy="26.467632"
+       cx="14.914475"
+       id="radialGradient9259"
+       xlink:href="#linearGradient2816"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1,0,0,0.988192,1.5624997,-2.39645)"
+       gradientUnits="userSpaceOnUse"
+       y2="47.022106"
+       x2="15.645709"
+       y1="40.668503"
+       x1="15.645709"
+       id="linearGradient9257"
+       xlink:href="#linearGradient6506"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient8848"
+       inkscape:collect="always">
+      <stop
+         id="stop8850"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop8852"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:1" />
+    </linearGradient>
+    <inkscape:perspective
+       id="perspective9168"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 24 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8860"
+       id="radialGradient9363"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.4138305,0,5.4390103)"
+       cx="12.809438"
+       cy="7.5702162"
+       fx="12.809438"
+       fy="7.5702162"
+       r="5.140625" />
+    <linearGradient
+       gradientTransform="matrix(0.6875001,0,0,0.6767003,-0.4687499,-0.5159997)"
+       y2="37.801281"
+       x2="42.829762"
+       y1="6.8962817"
+       x1="29.466667"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient8280"
+       xlink:href="#linearGradient8904"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8820"
+       id="linearGradient9520"
+       x1="18.097515"
+       y1="29.72571"
+       x2="18.031723"
+       y2="30.431053"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8808"
+       id="linearGradient9518"
+       gradientUnits="userSpaceOnUse"
+       x1="18.097515"
+       y1="29.72571"
+       x2="18.143806"
+       y2="30.188351" />
+    <inkscape:perspective
+       id="perspective9485"
+       inkscape:persp3d-origin="16 : 10.666667 : 1"
+       inkscape:vp_z="32 : 16 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 16 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6506"
+       id="linearGradient9651"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.988192,1.5624997,-2.39645)"
+       x1="24.027578"
+       y1="2.4785707"
+       x2="16.983839"
+       y2="70.046394" />
+    <filter
+       inkscape:collect="always"
+       id="filter9685"
+       x="-0.29886015"
+       width="1.5977203"
+       y="-0.49649348"
+       height="1.992987">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1336762"
+         id="feGaussianBlur9687" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9811"
+       x="-0.81284236"
+       width="2.6256847"
+       y="-0.52522121"
+       height="2.0504424">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.2573014"
+         id="feGaussianBlur9813" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9889"
+       x="-0.24442129"
+       width="1.4888426"
+       y="-0.20170113"
+       height="1.4034023">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.4272566"
+         id="feGaussianBlur9891" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient9893"
+       id="linearGradient9899"
+       x1="17.854447"
+       y1="23.295456"
+       x2="21.566757"
+       y2="23.295456"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient9905"
+       id="linearGradient9911"
+       x1="5.90625"
+       y1="23"
+       x2="11.291513"
+       y2="20.405081"
+       gradientUnits="userSpaceOnUse" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -404,16 +702,16 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="2.828427"
-     inkscape:cx="63.722923"
-     inkscape:cy="33.120105"
+     inkscape:zoom="5.6568543"
+     inkscape:cx="73.497233"
+     inkscape:cy="20.402636"
      inkscape:current-layer="layer1"
-     showgrid="true"
+     showgrid="false"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
-     inkscape:window-width="1434"
-     inkscape:window-height="840"
-     inkscape:window-x="-2"
+     inkscape:window-width="1440"
+     inkscape:window-height="848"
+     inkscape:window-x="0"
      inkscape:window-y="0"
      showguides="true"
      inkscape:guide-bbox="true"
@@ -463,25 +761,39 @@
        rx="0.81387848"
        ry="0.93014681" />
     <path
-       style="fill:url(#linearGradient8866);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 10.968089,7.6821669 C 13.825874,5.8764931 18.683474,9.095739 19.201853,10.751964 L 15.25649,10.751964 C 15.19399,8.408214 10.968089,7.6821669 10.968089,7.6821669 z"
-       id="rect5189"
-       sodipodi:nodetypes="cccc" />
-    <path
-       style="fill:url(#linearGradient8874);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 8.9209727,9.9271812 C 10.543462,8.0699992 15.5336,9.5097671 15.5336,10.860297 L 11.743475,11.411821 C 12.958815,9.7987339 8.9209727,9.9271812 8.9209727,9.9271812 z"
-       id="path5192"
-       sodipodi:nodetypes="cccc" />
+       style="fill:url(#radialGradient8780);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 12.75 7.15625 C 12.115339 7.1849256 11.504585 7.3489361 10.96875 7.6875 C 10.96875 7.6875 14.502372 8.292676 15.15625 10.1875 C 13.96441 9.115271 10.258623 8.3895059 8.90625 9.9375 C 8.90625 9.9375 12.96534 9.7931625 11.75 11.40625 L 15.53125 10.875 C 15.53125 10.837265 15.507609 10.787801 15.5 10.75 L 19.1875 10.75 C 18.766317 9.4043172 15.500198 7.0319893 12.75 7.15625 z "
+       id="rect5189" />
     <path
        style="opacity:1;fill:url(#linearGradient2840);fill-opacity:1;stroke:url(#linearGradient2832);stroke-width:0.99999994000000003;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        d="M 16.447354,10.481822 C 9.8233516,10.481822 3.9308558,15.93012 4.5098537,22.712688 C 5.7768579,37.554787 1.9403503,35.543378 1.5,42.316391 C 1.5,44.375904 2.4854201,45.355587 4.5920502,45.355587 C 5.7795388,45.355587 30.807389,45.5 33.498388,45.5 C 35.612515,45.5 35.447354,43.46472 35.447354,43.46472 C 35.447354,40.830782 29.045256,38.620654 27.260807,36.687231 C 25.432389,34.709838 27.447354,27.653648 27.447354,27.653648 C 28.08866,26.141912 28.447354,24.466812 28.447354,22.712688 C 28.447354,15.894164 23.071356,10.481822 16.447354,10.481822 z"
        id="path5176"
        sodipodi:nodetypes="cscccszcsc" />
     <path
-       style="opacity:0.55000000000000004;fill:url(#radialGradient2824);fill-opacity:1;stroke:url(#linearGradient6512);stroke-width:0.99999994000000003;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 16.25,11.5 C 10.237704,11.5 5.0276636,16.611038 5.4999997,22.834065 C 6.0644244,30.27036 5.8175038,32.821583 4.0236672,37.541192 C 1.1437418,42.286379 3.1235207,44.533069 5.4658637,44.533069 C 7.4024447,44.533069 25.520621,44.503627 31.346594,44.503627 C 32.513801,44.503627 34.5,45.001748 34.5,43.554478 C 34.5,43.335354 34.300249,42.923343 33.75,42.411881 C 33.199751,41.90042 32.37676,41.351214 31.46875,40.806069 C 30.56074,40.260924 29.59071,39.709456 28.71875,39.169376 C 27.84679,38.629297 27.074154,38.125147 26.53125,37.409159 C 25.921245,36.604678 25.641306,35.658991 25.586842,34.629869 C 25.532378,33.600747 25.670221,32.49665 25.787061,31.449126 C 26.020741,29.354077 26.53125,27.527239 26.53125,27.527239 C 26.54624,27.4637 26.567163,27.401673 26.59375,27.341953 C 27.181231,25.957097 27.5,24.414481 27.5,22.802446 C 27.5,16.531779 22.272436,11.5 16.25,11.5 z"
+       style="opacity:0.55000000000000004;fill:url(#radialGradient2824);fill-opacity:1;stroke:url(#linearGradient9651);stroke-width:0.99999994000000003;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 16.25,11.5 C 10.237704,11.5 5.0276636,16.611038 5.4999997,22.834065 C 5.5006447,22.842563 5.5012886,22.851054 5.5019315,22.85954 C 6.063858,30.276194 5.8154539,32.826976 4.0236672,37.541192 C 1.1437418,42.286379 3.1235207,44.533069 5.4658637,44.533069 C 7.4024447,44.533069 25.520621,44.503627 31.346594,44.503627 C 32.513801,44.503627 34.5,45.001748 34.5,43.554478 C 34.5,43.335354 34.300249,42.923343 33.75,42.411881 C 33.199751,41.90042 32.37676,41.351214 31.46875,40.806069 C 30.56074,40.260924 29.59071,39.709456 28.71875,39.169376 C 27.84679,38.629297 27.074154,38.125147 26.53125,37.409159 C 25.921245,36.604678 25.641306,35.658991 25.586842,34.629869 C 25.532378,33.600747 25.670221,32.49665 25.787061,31.449126 C 26.020741,29.354077 26.53125,27.527239 26.53125,27.527239 C 26.54624,27.4637 26.567163,27.401673 26.59375,27.341953 C 27.181231,25.957097 27.5,24.414481 27.5,22.802446 C 27.5,16.531779 22.272436,11.5 16.25,11.5 z"
        id="path5241"
-       sodipodi:nodetypes="cscccssssssscssc" />
+       sodipodi:nodetypes="csscccssssssscssc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:#b87bf7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9685);enable-background:accumulate"
+       id="path8782"
+       sodipodi:cx="18.075417"
+       sodipodi:cy="17.064077"
+       sodipodi:rx="4.552"
+       sodipodi:ry="2.7400389"
+       d="M 22.627417,17.064077 A 4.552,2.7400389 0 1 1 13.523417,17.064077 A 4.552,2.7400389 0 1 1 22.627417,17.064077 z"
+       transform="matrix(1.1235721,0,0,1.2773541,-2.423533,-4.2968681)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.25;fill:url(#linearGradient9899);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9889);enable-background:accumulate"
+       id="path9815"
+       sodipodi:cx="19.710602"
+       sodipodi:cy="23.295456"
+       sodipodi:rx="1.8561553"
+       sodipodi:ry="2.8726213"
+       d="M 21.566757,23.295456 A 1.8561553,2.8726213 0 1 1 17.854447,23.295456 A 1.8561553,2.8726213 0 1 1 21.566757,23.295456 z"
+       transform="matrix(8.4928046e-8,4.9721706,2.9846154,0,-50.922233,-71.70382)" />
     <path
        sodipodi:type="inkscape:offset"
        inkscape:radius="1.0174263"
@@ -489,7 +801,7 @@
        style="opacity:1;fill:url(#linearGradient8882);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
        id="path8838"
        d="M 9.96875,17.96875 C 8.6328774,17.96875 7.5286409,18.753017 6.875,19.71875 C 6.2213591,20.684483 5.9062499,21.848884 5.90625,23 C 5.90625,25.694817 7.8977844,28.03125 10.46875,28.03125 C 11.539674,28.03125 12.596335,27.527372 13.46875,26.71875 C 14.341165,25.910128 15.03125,24.709464 15.03125,23.28125 C 15.03125,22.003744 14.362496,20.808851 13.46875,19.8125 C 12.575004,18.816149 11.384009,17.96875 9.96875,17.96875 z"
-       transform="translate(1.09375,-0.96875)" />
+       transform="translate(1.09375,-0.9687531)" />
     <path
        style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
        d="M 15.09375,22.321339 C 15.09375,24.52934 12.987869,26.03125 11.567428,26.03125 C 9.6208995,26.03125 8.0411075,24.239249 8.0411075,22.031249 C 8.0411075,20.112462 9.1240375,18.03125 11.070566,18.03125 C 13.017097,18.03125 15.09375,20.576941 15.09375,22.321339 z"
@@ -507,7 +819,7 @@
        transform="matrix(1.237779,0,0,1.544828,-1.0301916,-15.38768)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;fill:url(#linearGradient8854);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        id="path5164"
        sodipodi:cx="10.169642"
        sodipodi:cy="24.3125"
@@ -522,10 +834,10 @@
        style="opacity:1;fill:url(#linearGradient8890);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
        id="path8846"
        d="M 24.6875,17.96875 C 23.636213,18.009185 22.683031,18.409233 22.03125,19.125 C 20.466122,20.843786 20.678782,23.580894 22.3125,25.375 C 23.011072,26.142154 23.917332,26.724837 24.9375,26.9375 C 25.957668,27.150163 27.151401,26.89759 27.96875,26 C 28.842555,25.04041 29.039766,23.753975 28.96875,22.53125 C 28.897734,21.308525 28.565932,20.111716 27.78125,19.25 C 26.906665,18.289553 25.728905,17.928695 24.6875,17.96875 z"
-       transform="translate(1.0348213,-0.9657729)" />
+       transform="translate(1.0348213,-0.9657741)" />
     <path
        style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 28.07086,18.984912 C 26.766398,17.552385 24.644242,17.934034 23.811326,18.848719 C 22.669923,20.102179 22.802261,22.282108 24.106725,23.714636 C 25.240323,24.959524 27.104889,25.612445 28.246292,24.358987 C 29.387696,23.105527 29.101434,20.116659 28.07086,18.984912 z"
+       d="M 28.088692,18.950685 C 26.78423,17.518158 24.662074,17.899807 23.829158,18.814492 C 22.687755,20.067952 22.820093,22.247881 24.124557,23.680409 C 25.258155,24.925297 27.122721,25.578218 28.264124,24.32476 C 29.405528,23.0713 29.119266,20.082432 28.088692,18.950685 z"
        id="path5169"
        sodipodi:nodetypes="csssc" />
     <path
@@ -545,15 +857,25 @@
        id="path8696"
        sodipodi:nodetypes="cssscccsccccsssc" />
     <path
+       sodipodi:type="arc"
+       style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter9811);enable-background:accumulate"
+       id="path9701"
+       sodipodi:cx="19.710602"
+       sodipodi:cy="23.295456"
+       sodipodi:rx="1.8561553"
+       sodipodi:ry="2.8726213"
+       d="M 21.566757,23.295456 A 1.8561553,2.8726213 0 1 1 17.854447,23.295456 A 1.8561553,2.8726213 0 1 1 21.566757,23.295456 z"
+       transform="matrix(1.6864563,0,0,1.5538462,-14.149186,-11.929827)" />
+    <path
        sodipodi:type="inkscape:offset"
        inkscape:radius="0.36336106"
        inkscape:original="M 15.8125 27 C 15.361611 27 15 27.422198 15 27.9375 C 15 28.452801 15.361612 28.874999 15.8125 28.875 L 21.1875 28.875 C 21.638389 28.875 22 28.452801 22 27.9375 C 22 27.422199 21.638389 27 21.1875 27 L 15.8125 27 z "
        style="opacity:1;fill:#5c3566;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter8792)"
        id="path8738"
        d="M 15.8125,26.625 C 15.134785,26.625 14.625,27.252207 14.625,27.9375 C 14.625,28.622793 15.134785,29.249998 15.8125,29.25 L 21.1875,29.25 C 21.865216,29.25 22.375,28.622793 22.375,27.9375 C 22.375,27.252207 21.865216,26.625 21.1875,26.625 L 15.8125,26.625 z"
-       transform="translate(1.0492259,-0.5907729)" />
+       transform="matrix(1.0403226,0,0,1.1666667,0.1470082,-5.4657729)" />
     <rect
-       style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:#f8eaba;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        id="rect5215"
        width="7"
        height="1.8602936"
@@ -568,27 +890,27 @@
        sodipodi:nodetypes="czccc" />
     <path
        sodipodi:type="arc"
-       style="opacity:0.61111109;fill:url(#linearGradient8814);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       style="opacity:1;fill:url(#linearGradient8814);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        id="path8806"
        sodipodi:cx="18.097515"
        sodipodi:cy="29.72571"
        sodipodi:rx="0.28726214"
        sodipodi:ry="0.6408155"
        d="M 18.384777,29.72571 A 0.28726214,0.6408155 0 1 1 17.810253,29.72571 A 0.28726214,0.6408155 0 1 1 18.384777,29.72571 z"
-       transform="matrix(-1.0945752,0.9356227,0.6067766,1.5209514,23.290203,-33.120817)" />
+       transform="matrix(-1.0945752,0.9356227,0.6067766,1.5209514,23.272227,-33.155044)" />
     <path
        sodipodi:type="arc"
-       style="opacity:0.61111109;fill:url(#linearGradient8818);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       style="opacity:1;fill:url(#linearGradient8818);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        id="path8816"
        sodipodi:cx="18.097515"
        sodipodi:cy="29.72571"
        sodipodi:rx="0.28726214"
        sodipodi:ry="0.6408155"
        d="M 18.384777,29.72571 A 0.28726214,0.6408155 0 1 1 17.810253,29.72571 A 0.28726214,0.6408155 0 1 1 18.384777,29.72571 z"
-       transform="matrix(1.0945741,0.9356227,-0.606776,1.5209514,16.745752,-33.098342)" />
+       transform="matrix(1.0945741,0.9356227,-0.606776,1.5209514,16.727776,-33.132569)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;fill:url(#linearGradient8858);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        id="path8856"
        sodipodi:cx="10.169642"
        sodipodi:cy="24.3125"
@@ -606,5 +928,38 @@
        d="M 33.647731,44.9375 C 35.272732,44.5625 36.772732,42.5625 28.772731,38.5625 C 29.124668,42.695473 26.022731,44.375 26.022731,44.375 L 33.647731,44.9375 z"
        id="path8740"
        sodipodi:nodetypes="cccc" />
+    <image
+       y="-12"
+       x="50"
+       id="image7948"
+       height="69.54084"
+       width="69.54084"
+       sodipodi:absref="/home/hbons/Bureaublad/pidgin-oxygen.png"
+       xlink:href="/home/hbons/Bureaublad/pidgin-oxygen.png" />
+    <path
+       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.55"
+       d="M 19.999895,26.990381 C 20.503282,27.702861 21.154686,31.031198 21.018582,33.998949 C 19.248555,31.850235 20.467226,29.772496 19.999895,26.990381 z"
+       id="rect9034"
+       sodipodi:nodetypes="ccc" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.7;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path9045"
+       sodipodi:cx="10.169642"
+       sodipodi:cy="24.3125"
+       sodipodi:rx="1.2410715"
+       sodipodi:ry="1.2946428"
+       d="M 11.410714,24.3125 A 1.2410715,1.2946428 0 1 1 8.928571,24.3125 A 1.2410715,1.2946428 0 1 1 11.410714,24.3125 z"
+       transform="matrix(0.4028774,0,0,0.3862069,7.4028807,12.110344)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.7;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path9047"
+       sodipodi:cx="10.169642"
+       sodipodi:cy="24.3125"
+       sodipodi:rx="1.2410715"
+       sodipodi:ry="1.2946428"
+       d="M 11.410714,24.3125 A 1.2410715,1.2946428 0 1 1 8.928571,24.3125 A 1.2410715,1.2946428 0 1 1 11.410714,24.3125 z"
+       transform="matrix(0.4028775,0,0,0.3862069,21.40288,12.110344)" />
   </g>
 </svg>