# HG changeset patch # User Sean Egan # Date 1170545563 0 # Node ID ccbdf500f13ae1597d57e8d2d01aa86351a43a8b # Parent aa0c1aa85fd3c4d27460f575f3ed0fe87bf46523 Google Talk uses structured text formatting where *this* is bold and _this_ is italic. If you're using Google Talk and receive a message, do that conversion. I admit this is proably the silliest Google Talk extension to add support for. But it seemed like it might be fun (turns out I was wrong). diff -r aa0c1aa85fd3 -r ccbdf500f13a libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Sat Feb 03 21:16:07 2007 +0000 +++ b/libpurple/protocols/jabber/disco.c Sat Feb 03 23:32:43 2007 +0000 @@ -257,7 +257,7 @@ return; } - for (child = xmlnode_get_child(query, "category"); child; + for (child = xmlnode_get_child(query, "identity"); child; child = xmlnode_get_next_twin(child)) { const char *category, *type, *name; category = xmlnode_get_attrib(child, "category"); @@ -273,8 +273,10 @@ g_free(js->server_name); js->server_name = g_strdup(name); - if (!strcmp(name, "Google Talk")) - js->googletalk = TRUE; + if (!strcmp(name, "Google Talk")) { + printf("ADSFADFAFAFADF !!!!\n"); + js->googletalk = TRUE; + } } for (child = xmlnode_get_child(query, "feature"); child; diff -r aa0c1aa85fd3 -r ccbdf500f13a libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Sat Feb 03 21:16:07 2007 +0000 +++ b/libpurple/protocols/jabber/google.c Sat Feb 03 23:32:43 2007 +0000 @@ -21,6 +21,7 @@ #include "internal.h" #include "debug.h" +#include "util.h" #include "privacy.h" #include "buddy.h" @@ -368,3 +369,119 @@ /* See if he's online */ jabber_presence_subscription_set(js, who, "probe"); } + +/* This does two passes on the string. The first pass goes through + * and determine if all the structured text is properly balanced, and + * how many instances of each there is. The second pass goes and converts + * everything to HTML, depending on what's figured out by the first pass. + * It will short circuit once it knows it has no more replacements to make + */ +char *jabber_google_format_to_html(const char *text) +{ + const char *p; + + /* The start of the screen may be consdiered a space for this purpose */ + gboolean preceding_space = TRUE; + + gboolean in_bold = FALSE, in_italic = FALSE; + gboolean in_tag = FALSE; + + gint bold_count = 0, italic_count = 0; + + GString *str; + + for (p = text; *p != '\0'; p = g_utf8_next_char(p)) { + gunichar c = g_utf8_get_char(p); + if (c == '*' && !in_tag) { + if (in_bold && (g_unichar_isspace(*(p+1)) || + *(p+1) == '\0' || + *(p+1) == '<')) { + bold_count++; + in_bold = FALSE; + } else if (preceding_space && !in_bold) { + bold_count++; + in_bold = TRUE; + } + preceding_space = TRUE; + } else if (c == '_' && !in_tag) { + if (in_italic && (g_unichar_isspace(*(p+1)) || + *(p+1) == '\0' || + *(p+1) == '<')) { + italic_count++; + in_italic = FALSE; + } else if (preceding_space && !in_italic) { + italic_count++; + in_italic = TRUE; + } + preceding_space = TRUE; + } else if (c == '<' && !in_tag) { + in_tag = TRUE; + } else if (c == '>' && in_tag) { + in_tag = FALSE; + } else if (!in_tag) { + if (g_unichar_isspace(c)) + preceding_space = TRUE; + else + preceding_space = FALSE; + } + } + + str = g_string_new(NULL); + in_bold = in_italic = in_tag = FALSE; + preceding_space = TRUE; + + for (p = text; *p != '\0'; p = g_utf8_next_char(p)) { + gunichar c = g_utf8_get_char(p); + + if (bold_count < 2 && italic_count < 2 && !in_bold && !in_italic) { + g_string_append(str, p); + return g_string_free(str, FALSE); + } + + + if (c == '*' && !in_tag) { + if (in_bold && + (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { /* This is safe in UTF-8 */ + str = g_string_append(str, ""); + in_bold = FALSE; + bold_count--; + } else if (preceding_space && bold_count > 1) { + str = g_string_append(str, ""); + bold_count--; + in_bold = TRUE; + } else { + str = g_string_append_unichar(str, c); + } + preceding_space = TRUE; + } else if (c == '_' && !in_tag) { + if (in_italic && + (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { + str = g_string_append(str, ""); + italic_count--; + in_italic = FALSE; + } else if (preceding_space && italic_count > 1) { + str = g_string_append(str, ""); + italic_count--; + in_italic = TRUE; + } else { + str = g_string_append_unichar(str, c); + } + preceding_space = TRUE; + } else if (c == '<' && !in_tag) { + str = g_string_append_unichar(str, c); + in_tag = TRUE; + } else if (c == '>' && in_tag) { + str = g_string_append_unichar(str, c); + in_tag = FALSE; + } else if (!in_tag) { + str = g_string_append_unichar(str, c); + if (g_unichar_isspace(c)) + preceding_space = TRUE; + else + preceding_space = FALSE; + } else { + str = g_string_append_unichar(str, c); + } + } + return g_string_free(str, FALSE); +} diff -r aa0c1aa85fd3 -r ccbdf500f13a libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Sat Feb 03 21:16:07 2007 +0000 +++ b/libpurple/protocols/jabber/google.h Sat Feb 03 23:32:43 2007 +0000 @@ -39,6 +39,8 @@ void jabber_google_roster_add_deny(GaimConnection *gc, const char *who); void jabber_google_roster_rem_deny(GaimConnection *gc, const char *who); +char *jabber_google_format_to_html(const char *text); + #endif /* _GAIM_GOOGLE_H_ */ diff -r aa0c1aa85fd3 -r ccbdf500f13a libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Sat Feb 03 21:16:07 2007 +0000 +++ b/libpurple/protocols/jabber/message.c Sat Feb 03 23:32:43 2007 +0000 @@ -27,6 +27,7 @@ #include "buddy.h" #include "chat.h" +#include "google.h" #include "message.h" #include "xmlnode.h" @@ -99,6 +100,12 @@ g_free(jbr->thread_id); jbr->thread_id = g_strdup(jbr->thread_id); } + + if (jm->js->googletalk && jm->xhtml == NULL) { + char *tmp = jm->body; + jm->body = jabber_google_format_to_html(jm->body); + g_free(tmp); + } serv_got_im(jm->js->gc, from, jm->xhtml ? jm->xhtml : jm->body, 0, jm->sent); } @@ -255,7 +262,7 @@ if(type) { if(!strcmp(type, "normal")) jm->type = JABBER_MESSAGE_NORMAL; - else if(!strcmp(type, "chat")) + else if(!strcmp(type, "chat")) jm->type = JABBER_MESSAGE_CHAT; else if(!strcmp(type, "groupchat")) jm->type = JABBER_MESSAGE_GROUPCHAT;