# HG changeset patch # User Yoshiki Yazawa # Date 1225442262 0 # Node ID 45ce87f9a07fa2a329976444e077e3f537355918 # Parent 18711b62ec27006332cfb0622f7bb2eb851c77dc# Parent b5e2be33a17ac1043345b15650a6cadefc2e0c44 propagate from branch 'im.pidgin.pidgin' (head 7821a3549d7d99473e999dc067afc4218addcc1e) to branch 'im.pidgin.pidgin.yaz' (head a23f8b0bf428af45a81e2d1baa0305cca0ad2a59) diff -r 18711b62ec27 -r 45ce87f9a07f autogen.sh --- a/autogen.sh Fri Oct 31 04:03:44 2008 +0000 +++ b/autogen.sh Fri Oct 31 08:37:42 2008 +0000 @@ -149,4 +149,4 @@ # Run configure ############################################################################### echo "running ./configure ${CONFIGURE_FLAGS} $@" -./configure ${CONFIGURE_FLAGS} $@ +#./configure ${CONFIGURE_FLAGS} $@ diff -r 18711b62ec27 -r 45ce87f9a07f configure.ac --- a/configure.ac Fri Oct 31 04:03:44 2008 +0000 +++ b/configure.ac Fri Oct 31 08:37:42 2008 +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 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 diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/certificate.c --- a/libpurple/certificate.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/certificate.c Fri Oct 31 08:37:42 2008 +0000 @@ -1327,20 +1327,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, @@ -1398,21 +1400,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")) { + + 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); - + 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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/conversation.c --- a/libpurple/conversation.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/conversation.c Fri Oct 31 08:37:42 2008 +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 @@ -1160,17 +1164,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("
%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) diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/notify.c --- a/libpurple/notify.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/notify.c Fri Oct 31 08:37:42 2008 +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) { diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/gg/lib/http.c --- a/libpurple/protocols/gg/lib/http.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/gg/lib/http.c Fri Oct 31 08:37:42 2008 +0000 @@ -44,6 +44,7 @@ #include "compat.h" #include "libgadu.h" +#include /* * gg_http_connect() // funkcja pomocnicza diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/gg/lib/pubdir50.c --- a/libpurple/protocols/gg/lib/pubdir50.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/gg/lib/pubdir50.c Fri Oct 31 08:37:42 2008 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include "libgadu.h" diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/irc/irc.c --- a/libpurple/protocols/irc/irc.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/irc/irc.c Fri Oct 31 08:37:42 2008 +0000 @@ -992,6 +992,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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/irc/parse.c --- a/libpurple/protocols/irc/parse.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/irc/parse.c Fri Oct 31 08:37:42 2008 +0000 @@ -35,7 +35,7 @@ #include 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(posaccount, "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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/jabber/google.c Fri Oct 31 08:37:42 2008 +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 @@ -512,8 +513,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"); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Oct 31 08:37:42 2008 +0000 @@ -367,8 +367,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); @@ -377,8 +378,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 void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused) @@ -1499,7 +1501,7 @@ { char *ret = NULL; JabberBuddy *jb = NULL; - + if (b->account->gc && b->account->gc->proto_data) jb = jabber_buddy_find(b->account->gc->proto_data, b->name, FALSE); @@ -1508,13 +1510,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 : ""); + } } @@ -1585,6 +1595,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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/jabber/message.c Fri Oct 31 08:37:42 2008 +0000 @@ -584,13 +584,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"); @@ -605,7 +609,7 @@ smiley_refs = jabber_message_get_refs_from_xmlnode(child); purple_debug_info("jabber", "found %d smileys\n", g_list_length(smiley_refs)); - + if (jm->type == JABBER_MESSAGE_GROUPCHAT) { JabberID *jid = jabber_id_new(jm->from); JabberChat *chat = NULL; @@ -638,7 +642,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 @@ -649,7 +655,7 @@ const gchar *cid = ref->cid; const gchar *alt = ref->alt; - purple_debug_info("jabber", + purple_debug_info("jabber", "about to add custom smiley %s to the conv\n", alt); if (purple_conv_custom_smiley_add(conv, alt, "cid", cid, TRUE)) { @@ -657,8 +663,8 @@ jabber_data_find_remote_by_cid(cid); /* if data is already known, we add write it immediatly */ if (data) { - purple_debug_info("jabber", - "data is already known\n"); + purple_debug_info("jabber", + "data is already known\n"); purple_conv_custom_smiley_write(conv, alt, jabber_data_get_data(data), jabber_data_get_size(data)); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/jabber/si.c Fri Oct 31 08:37:42 2008 +0000 @@ -38,6 +38,8 @@ #define STREAMHOST_CONNECT_TIMEOUT 15 +#include "util.h" + typedef struct _JabberSIXfer { JabberStream *js; @@ -898,8 +900,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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/msn/msg.c --- a/libpurple/protocols/msn/msg.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/msn/msg.c Fri Oct 31 08:37:42 2008 +0000 @@ -111,7 +111,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; @@ -123,8 +124,10 @@ "FN=MS%20Sans%20Serif; EF=; CO=0; CS=86;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; } diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/msn/msn.c Fri Oct 31 08:37:42 2008 +0000 @@ -176,13 +176,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 = ""; @@ -198,6 +203,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. } @@ -326,6 +333,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; @@ -1059,13 +1083,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); @@ -2402,6 +2431,9 @@ msn_switchboard_init(); msn_sync_init(); + // yaz + msn_ipc_init(plugin); + return TRUE; } @@ -2411,6 +2443,9 @@ msn_switchboard_end(); msn_sync_end(); + // yaz + msn_ipc_end(plugin); + return TRUE; } diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/msn/switchboard.c --- a/libpurple/protocols/msn/switchboard.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/msn/switchboard.c Fri Oct 31 08:37:42 2008 +0000 @@ -888,7 +888,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; @@ -896,7 +896,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); @@ -955,13 +955,17 @@ } else { - serv_got_im(gc, passport, body_final, 0, time(NULL)); + char *yaz_body_final; + yaz_body_final = purple_strreplace(body_final, "\r\n", "
"); // replace 0D 0A with
+ purple_debug_info("yaz msn", "yaz_body_final=%s\n", yaz_body_final); + serv_got_im(gc, passport, yaz_body_final, 0, time(NULL)); if (swboard->conv == NULL) { swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, passport, purple_connection_get_account(gc)); swboard->flag |= MSN_SB_FLAG_IM; } + g_free(yaz_body_final); } g_free(body_final); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/msnp9/msg.c --- a/libpurple/protocols/msnp9/msg.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/msnp9/msg.c Fri Oct 31 08:37:42 2008 +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 { diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/msnp9/msn.c --- a/libpurple/protocols/msnp9/msn.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/msnp9/msn.c Fri Oct 31 08:37:42 2008 +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 = ""; diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/msnp9/switchboard.c --- a/libpurple/protocols/msnp9/switchboard.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/msnp9/switchboard.c Fri Oct 31 08:37:42 2008 +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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/oscar/family_icbm.c --- a/libpurple/protocols/oscar/family_icbm.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/oscar/family_icbm.c Fri Oct 31 08:37:42 2008 +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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/oscar/odc.c --- a/libpurple/protocols/oscar/odc.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/oscar/odc.c Fri Oct 31 08:37:42 2008 +0000 @@ -101,22 +101,28 @@ 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); + byte_stream_putraw(&bs, frame->sn, 32); + byte_stream_putraw(&bs, frame->payload.data, frame->payload.len); peer_connection_send(conn, &bs); @@ -496,13 +502,17 @@ 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->sn, 32); purple_debug_info("oscar", "Incoming ODC frame from %s with " diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/oscar/oft.c --- a/libpurple/protocols/oscar/oft.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/oscar/oft.c Fri Oct 31 08:37:42 2008 +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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Oct 31 08:37:42 2008 +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; @@ -543,6 +569,7 @@ *msglen_int = msglen; return; } +#endif purple_debug_info("oscar", "Conversion from UTF-8 to %s failed (%s), falling back to unicode.\n", charsetstr, err->message); @@ -552,7 +579,8 @@ /* * 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; @@ -2241,6 +2269,8 @@ tmp = purple_plugin_oscar_decode_im_part(account, userinfo->sn, 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); } @@ -2343,6 +2373,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; @@ -2365,6 +2396,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->sn, @@ -2586,7 +2619,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++) { @@ -4263,9 +4296,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; @@ -4325,12 +4356,8 @@ g_string_append(msg, ""); - /* Convert the message to a good encoding */ - purple_plugin_oscar_convert_to_best_encoding(conn->od->gc, - conn->sn, 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) { @@ -4572,7 +4599,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); @@ -5698,7 +5726,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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/oscar/oscar.h --- a/libpurple/protocols/oscar/oscar.h Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/oscar/oscar.h Fri Oct 31 08:37:42 2008 +0000 @@ -770,6 +770,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. diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/util.c --- a/libpurple/protocols/yahoo/util.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/util.c Fri Oct 31 08:37:42 2008 +0000 @@ -29,6 +29,7 @@ #include "prpl.h" #include "yahoo.h" +#include "util.h" #include @@ -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(""); } diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Fri Oct 31 08:37:42 2008 +0000 @@ -1243,8 +1243,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; @@ -1285,11 +1286,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; } @@ -1322,8 +1328,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), @@ -1480,11 +1486,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", @@ -1943,11 +1950,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", @@ -3549,7 +3557,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); @@ -3744,6 +3755,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) { @@ -3788,20 +3804,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 { @@ -4489,11 +4512,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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoo.h --- a/libpurple/protocols/yahoo/yahoo.h Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Fri Oct 31 08:37:42 2008 +0000 @@ -78,7 +78,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. */ diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoo_filexfer.c --- a/libpurple/protocols/yahoo/yahoo_filexfer.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Fri Oct 31 08:37:42 2008 +0000 @@ -217,7 +217,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; @@ -225,6 +225,7 @@ PurpleConnection *gc; PurpleAccount *account; struct yahoo_data *yd; + gsize dummy; purple_debug(PURPLE_DEBUG_INFO, "yahoo", "AAA - in yahoo_sendfile_connected\n"); @@ -251,8 +252,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); @@ -948,8 +953,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; @@ -1044,6 +1049,10 @@ if(yf && yf->version_id > 500000 && !yd->jp) ver = 15; + /* recent yahoo japan --yaz */ + if(yd->jp && yf && yf->version_id > 500000) + ver = 15; + g_return_if_fail(xfer != NULL); if(ver == 15) { diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoo_packet.c --- a/libpurple/protocols/yahoo/yahoo_packet.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Fri Oct 31 08:37:42 2008 +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); @@ -387,6 +390,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; diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoo_packet.h --- a/libpurple/protocols/yahoo/yahoo_packet.h Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.h Fri Oct 31 08:37:42 2008 +0000 @@ -123,7 +123,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) diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoo_profile.c --- a/libpurple/protocols/yahoo/yahoo_profile.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_profile.c Fri Oct 31 08:37:42 2008 +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) { @@ -762,6 +765,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) { @@ -1010,6 +1014,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); } } @@ -1021,7 +1028,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) { @@ -1054,16 +1061,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, @@ -1094,7 +1102,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 @@ -1103,7 +1111,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)) @@ -1189,6 +1197,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) diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/protocols/yahoo/yahoochat.c --- a/libpurple/protocols/yahoo/yahoochat.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Fri Oct 31 08:37:42 2008 +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); diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/server.c --- a/libpurple/server.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/server.c Fri Oct 31 08:37:42 2008 +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); @@ -250,19 +252,23 @@ b = buddies->data; buddies = g_slist_delete_link(buddies, buddies); + /* alias may be NULL */ if((b->server_alias == NULL && alias == NULL) || (b->server_alias && alias && !strcmp(b->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, b->name, account); - if(conv != NULL && alias != NULL && strcmp(alias, who)) + if(conv != NULL && alias2 != NULL && strcmp(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); @@ -274,6 +280,8 @@ g_free(escaped2); g_free(escaped); } + g_free(alias2); + alias2 = NULL; } } @@ -283,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); @@ -295,11 +305,13 @@ if((!b->alias && !alias) || (b->alias && alias && !strcmp(b->alias, 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; diff -r 18711b62ec27 -r 45ce87f9a07f libpurple/util.c --- a/libpurple/util.c Fri Oct 31 04:03:44 2008 +0000 +++ b/libpurple/util.c Fri Oct 31 08:37:42 2008 +0000 @@ -1219,6 +1219,8 @@ return FALSE; q = strstr(p, end_token); + if(q == NULL) //yaz + return FALSE; /* Trim leading blanks */ while (*p != '\n' && g_ascii_isspace(*p)) { @@ -1231,7 +1233,7 @@ } /* Don't bother with null strings */ - if (p == q) + if (p >= q) return FALSE; if (q != NULL && (!no_value_token || @@ -2004,6 +2006,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) { @@ -2041,6 +2057,7 @@ gunichar g; gboolean inside_html = FALSE; int inside_paren = 0; + int inside_bracket = 0; GString *ret; if (text == NULL) @@ -2057,6 +2074,12 @@ c++; } + if(*c == '[' && !inside_html) { + inside_bracket++; + ret = g_string_append_c(ret, *c); + c++; + } + if(inside_html) { if(*c == '>') { inside_html = FALSE; @@ -2084,7 +2107,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))) { @@ -2101,6 +2124,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); @@ -2118,7 +2144,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; } @@ -2133,6 +2159,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, @@ -2149,7 +2178,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))) { @@ -2161,6 +2190,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, "%s", @@ -2179,7 +2211,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; } @@ -2188,6 +2220,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, @@ -2206,7 +2241,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; @@ -2240,7 +2275,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; @@ -2256,6 +2291,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); @@ -2343,6 +2381,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; @@ -4783,3 +4826,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 0); + + for(i=0;i 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 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", NULL }, { "/Tools/sep3", NULL, NULL, 0, "", NULL }, { N_("/Tools/Mute _Sounds"), NULL, pidgin_blist_mute_sounds_cb, 0, "", NULL }, + /* Help */ { N_("/_Help"), NULL, NULL, 0, "", NULL }, { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "", GTK_STOCK_HELP }, diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkconv.c Fri Oct 31 08:37:42 2008 +0000 @@ -1,3 +1,4 @@ +/* -*- coding: utf-8 -*- */ /** * @file gtkconv.c GTK+ Conversation API * @ingroup pidgin @@ -119,6 +120,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; @@ -273,6 +278,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) { @@ -422,6 +464,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) { @@ -3108,20 +3164,33 @@ { "/Conversation/sep0", NULL, NULL, 0, "", NULL }, +#if ENABLE_SHORTCUT { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0, "", GTK_STOCK_FIND }, +#else + { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0, + "", NULL }, +#endif { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "", NULL }, { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0, "", GTK_STOCK_SAVE_AS }, +#if ENABLE_SHORTCUT { N_("/Conversation/Clea_r Scrollback"), "L", menu_clear_cb, 0, "", GTK_STOCK_CLEAR }, - +#else + { N_("/Conversation/Clea_r Scrollback"), NULL, menu_clear_cb, 0, "", NULL }, +#endif { "/Conversation/sep1", NULL, NULL, 0, "", NULL }, { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "", PIDGIN_STOCK_TOOLBAR_SEND_FILE }, { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb, 0, "", NULL }, +#if ENABLE_SHORTCUT { N_("/Conversation/_Get Info"), "O", menu_get_info_cb, 0, "", PIDGIN_STOCK_TOOLBAR_USER_INFO }, +#else + { N_("/Conversation/_Get Info"), NULL, menu_get_info_cb, 0, + "", PIDGIN_STOCK_TOOLBAR_USER_INFO }, +#endif { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0, "", NULL }, { N_("/Conversation/M_ore"), NULL, NULL, 0, "", NULL }, @@ -3834,7 +3903,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(); @@ -4259,6 +4332,7 @@ PidginChatPane *gtkchat; char *new_topic; const char *current_topic; + char dummy[] = "No Topic"; gc = purple_conversation_get_gc(conv); @@ -4278,7 +4352,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); @@ -4554,12 +4628,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; } @@ -4774,7 +4846,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; @@ -4783,8 +4855,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 */ @@ -4888,18 +4964,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, >kconv->entry, >kconv->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); @@ -4909,6 +4997,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)); @@ -4933,7 +5023,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 @@ -6556,6 +6646,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); @@ -6650,8 +6743,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 || @@ -7069,6 +7180,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) @@ -7138,6 +7267,7 @@ pidgin_conv_tab_pack(gtkwin, gtkconvs->data); } } + trim_vertical_tabs_pref_cb(name, type, value, data); } static void @@ -7196,7 +7326,7 @@ else gtk_widget_hide(gtkconv->toolbar); - g_idle_add((GSourceFunc)resize_imhtml_cb,gtkconv); +// g_idle_add((GSourceFunc)resize_imhtml_cb,gtkconv); } } @@ -7707,6 +7837,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); @@ -7761,6 +7892,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", diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkimhtml.c Fri Oct 31 08:37:42 2008 +0000 @@ -95,6 +95,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); @@ -485,10 +489,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; @@ -534,7 +539,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) + @@ -647,14 +654,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; @@ -1010,18 +1015,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 { @@ -1172,7 +1184,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) { @@ -1925,7 +1938,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"); @@ -3314,6 +3328,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; @@ -3328,7 +3343,7 @@ ws[wpos++] = 0xE2; ws[wpos++] = 0x80; ws[wpos++] = 0x8F; - + if (!rtl_direction) { /* insert LRM character to set direction */ diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkimhtmltoolbar.c --- a/pidgin/gtkimhtmltoolbar.c Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Fri Oct 31 08:37:42 2008 +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); diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkimhtmltoolbar.h --- a/pidgin/gtkimhtmltoolbar.h Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkimhtmltoolbar.h Fri Oct 31 08:37:42 2008 +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) (GTK_CHECK_CAST ((obj), GTK_TYPE_IMHTMLTOOLBAR, GtkIMHtmlToolbar)) diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtknotify.c --- a/pidgin/gtknotify.c Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtknotify.c Fri Oct 31 08:37:42 2008 +0000 @@ -1073,12 +1073,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"); diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkprefs.c Fri Oct 31 08:37:42 2008 +0000 @@ -978,6 +978,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, @@ -1064,7 +1067,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); diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkutils.c --- a/pidgin/gtkutils.c Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkutils.c Fri Oct 31 08:37:42 2008 +0000 @@ -3480,3 +3480,61 @@ return pixbuf; } +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; +} diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/gtkutils.h --- a/pidgin/gtkutils.h Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/gtkutils.h Fri Oct 31 08:37:42 2008 +0000 @@ -822,5 +822,7 @@ */ GdkPixbuf * pidgin_pixbuf_from_imgstore(PurpleStoredImage *image); +gchar *pidgin_gtk_ellipsis_text(GtkWidget *widget, const char *text, gint min_width, gchar *ellipsis); + #endif /* _PIDGINUTILS_H_ */ diff -r 18711b62ec27 -r 45ce87f9a07f pidgin/pixmaps/icons/hicolor/48x48/apps/scalable/pidgin.svg --- a/pidgin/pixmaps/icons/hicolor/48x48/apps/scalable/pidgin.svg Fri Oct 31 04:03:44 2008 +0000 +++ b/pidgin/pixmaps/icons/hicolor/48x48/apps/scalable/pidgin.svg Fri Oct 31 08:37:42 2008 +0000 @@ -23,12 +23,55 @@ + + + + + + + + + + + + + + style="stop-color:#162c5e;stop-opacity:1" /> @@ -66,7 +109,7 @@ offset="0" id="stop8886" /> @@ -78,24 +121,12 @@ offset="0" id="stop8878" /> - - - - - - - - @@ -198,7 +217,7 @@ offset="0" id="stop6539" /> @@ -206,7 +225,7 @@ inkscape:collect="always" id="linearGradient6506"> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + 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" /> + sodipodi:nodetypes="csscccssssssscssc" /> + + + transform="translate(1.09375,-0.9687531)" /> + transform="translate(1.0348213,-0.9657741)" /> + + transform="matrix(1.0403226,0,0,1.1666667,0.1470082,-5.4657729)" /> + transform="matrix(-1.0945752,0.9356227,0.6067766,1.5209514,23.272227,-33.155044)" /> + transform="matrix(1.0945741,0.9356227,-0.606776,1.5209514,16.727776,-33.132569)" /> + + + +