changeset 15523:ccbdf500f13a

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).
author Sean Egan <seanegan@gmail.com>
date Sat, 03 Feb 2007 23:32:43 +0000
parents aa0c1aa85fd3
children 84b3ab83df35
files libpurple/protocols/jabber/disco.c libpurple/protocols/jabber/google.c libpurple/protocols/jabber/google.h libpurple/protocols/jabber/message.c
diffstat 4 files changed, 132 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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; 
--- 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, "</b>");
+				in_bold = FALSE;
+				bold_count--;
+			} else if (preceding_space && bold_count > 1) {
+				str = g_string_append(str, "<b>");
+				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, "</i>");
+				italic_count--;
+				in_italic = FALSE;
+			} else if (preceding_space && italic_count > 1) {
+				str = g_string_append(str, "<i>");
+				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);
+}
--- 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_ */
--- 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;