/pidgin/main: 8738f1797803: Smiley parser: don't replace smileys...

Tomasz Wasilczyk twasilczyk at pidgin.im
Mon Apr 7 06:48:47 EDT 2014


Changeset: 8738f1797803622fba952dba9d893496cb180902
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-07 12:48 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/8738f1797803

Description:

Smiley parser: don't replace smileys inside HTML tags

diffstat:

 libpurple/core.c                          |   3 +
 libpurple/protocols/jabber/message.c      |   2 +
 libpurple/smiley-parser.c                 |  95 +++++++++++++++++++++++-------
 libpurple/smiley-parser.h                 |  16 +++++
 pidgin/themes/Contents/Resources/main.css |   5 +
 5 files changed, 97 insertions(+), 24 deletions(-)

diffs (221 lines):

diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -42,6 +42,7 @@
 #include "savedstatuses.h"
 #include "signals.h"
 #include "smiley-custom.h"
+#include "smiley-parser.h"
 #include "smiley-theme.h"
 #include "sound.h"
 #include "sound-theme-loader.h"
@@ -204,6 +205,7 @@ purple_core_init(const char *ui)
 	purple_idle_init();
 	purple_http_init();
 	_purple_smiley_custom_init();
+	_purple_smiley_parser_init();
 
 	/*
 	 * Call this early on to try to auto-detect our IP address and
@@ -258,6 +260,7 @@ purple_core_quit(void)
 	/* Save .xml files, remove signals, etc. */
 	_purple_smiley_theme_uninit();
 	_purple_smiley_custom_uninit();
+	_purple_smiley_parser_uninit();
 	purple_http_uninit();
 	purple_idle_uninit();
 	purple_pounces_uninit();
diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c
--- a/libpurple/protocols/jabber/message.c
+++ b/libpurple/protocols/jabber/message.c
@@ -868,6 +868,8 @@ jabber_message_get_smileyfied_xhtml(cons
 			const gssize len = strlen(shortcut);
 			gchar *escaped = g_markup_escape_text(shortcut, len);
 
+			/* TODO: it doesn't take care of text inside a tag.
+			 * Use purple_smiley_parse. */
 			if (g_str_has_prefix(&(xhtml[pos]), escaped)) {
 				/* we found the current smiley at this position */
 				const JabberData *data =
diff --git a/libpurple/smiley-parser.c b/libpurple/smiley-parser.c
--- a/libpurple/smiley-parser.c
+++ b/libpurple/smiley-parser.c
@@ -28,18 +28,53 @@
 
 typedef struct
 {
-	PurpleConversation *conv;
-	PurpleSmileyParseCb cb;
-	gpointer ui_data;
+	union {
+		struct {
+			PurpleConversation *conv;
+			PurpleSmileyParseCb cb;
+			gpointer ui_data;
+		} replace;
+		struct {
+			GHashTable *found_smileys;
+		} find;
+	} job;
+
+	gboolean in_html_tag;
 } PurpleSmileyParseData;
 
-static gboolean purple_smiley_parse_cb(GString *out, const gchar *word,
-	gpointer _smiley, gpointer _parse_data)
+static PurpleTrie *html_sentry;
+
+static inline void
+purple_smiley_parse_check_html(const gchar *word,
+	PurpleSmileyParseData *parse_data)
+{
+	if (G_LIKELY(word[0] == '<'))
+		parse_data->in_html_tag = TRUE;
+	else if (G_LIKELY(word[0] == '>'))
+		parse_data->in_html_tag = FALSE;
+	else
+		g_return_if_reached();
+	g_warn_if_fail(word[1] == '\0');
+}
+
+static gboolean
+purple_smiley_parse_cb(GString *out, const gchar *word, gpointer _smiley,
+	gpointer _parse_data)
 {
 	PurpleSmileyParseData *parse_data = _parse_data;
 	PurpleSmiley *smiley = _smiley;
 
-	parse_data->cb(out, smiley, parse_data->conv, parse_data->ui_data);
+	/* a special-case for html_sentry */
+	if (smiley == NULL) {
+		purple_smiley_parse_check_html(word, parse_data);
+		return FALSE;
+	}
+
+	if (parse_data->in_html_tag)
+		return FALSE;
+
+	parse_data->job.replace.cb(out, smiley, parse_data->job.replace.conv,
+		parse_data->job.replace.ui_data);
 
 	return TRUE;
 }
@@ -57,7 +92,8 @@ purple_smiley_parse(PurpleConversation *
 	PurpleSmileyTheme *theme;
 	PurpleSmileyList *theme_smileys = NULL, *remote_smileys = NULL;
 	PurpleTrie *theme_trie = NULL, *custom_trie = NULL, *remote_trie = NULL;
-	GSList *tries = NULL, tries_theme, tries_custom, tries_remote;
+	GSList *tries = NULL;
+	GSList tries_sentry, tries_theme, tries_custom, tries_remote;
 	PurpleSmileyParseData parse_data;
 
 	if (html_message == NULL || html_message[0] == '\0')
@@ -97,30 +133,25 @@ purple_smiley_parse(PurpleConversation *
 		return g_strdup(html_message);
 
 	/* Create a tries list on the stack. */
+	tries_sentry.data = html_sentry;
 	tries_theme.data = theme_trie;
 	tries_custom.data = custom_trie;
 	tries_remote.data = remote_trie;
+	tries_sentry.next = NULL;
 	tries_theme.next = tries_custom.next = tries_remote.next = NULL;
+	tries = &tries_sentry;
 	if (remote_trie != NULL)
-		tries = &tries_remote;
-	if (custom_trie != NULL) {
-		if (tries)
-			g_slist_last(tries)->next = &tries_custom;
-		else
-			tries = &tries_custom;
-	}
-	if (theme_trie != NULL) {
-		if (tries)
-			g_slist_last(tries)->next = &tries_theme;
-		else
-			tries = &tries_theme;
-	}
+		g_slist_last(tries)->next = &tries_remote;
+	if (custom_trie != NULL)
+		g_slist_last(tries)->next = &tries_custom;
+	if (theme_trie != NULL)
+		g_slist_last(tries)->next = &tries_theme;
 
-	parse_data.conv = conv;
-	parse_data.cb = cb;
-	parse_data.ui_data = ui_data;
+	parse_data.job.replace.conv = conv;
+	parse_data.job.replace.cb = cb;
+	parse_data.job.replace.ui_data = ui_data;
+	parse_data.in_html_tag = FALSE;
 
-	/* TODO: don't replace text within tags, ie. <span style=":)"> */
 	/* TODO: parse greedily (as much as possible) when PurpleTrie
 	 * provides support for it. */
 	return purple_trie_multi_replace(tries, html_message,
@@ -162,6 +193,8 @@ purple_smiley_find(PurpleSmileyList *smi
 	found_smileys = g_hash_table_new(g_direct_hash, g_direct_equal);
 	purple_trie_find(trie, message, smiley_find_cb, found_smileys);
 
+	/* TODO: use html_sentry and purple_trie_multi_replace */
+
 	g_free(escaped_message);
 
 	found_list = g_hash_table_get_values(found_smileys);
@@ -169,3 +202,17 @@ purple_smiley_find(PurpleSmileyList *smi
 
 	return found_list;
 }
+
+void
+_purple_smiley_parser_init(void)
+{
+	html_sentry = purple_trie_new();
+	purple_trie_add(html_sentry, "<", NULL);
+	purple_trie_add(html_sentry, ">", NULL);
+}
+
+void
+_purple_smiley_parser_uninit(void)
+{
+	g_object_unref(html_sentry);
+}
diff --git a/libpurple/smiley-parser.h b/libpurple/smiley-parser.h
--- a/libpurple/smiley-parser.h
+++ b/libpurple/smiley-parser.h
@@ -89,4 +89,20 @@ GList *
 purple_smiley_find(PurpleSmileyList *smileys, const gchar *message,
 	gboolean is_html);
 
+/**
+ * _purple_smiley_parser_init: (skip)
+ *
+ * Initializes the smileys parser subsystem.
+ */
+void
+_purple_smiley_parser_init(void);
+
+/**
+ * _purple_smiley_parser_uninit: (skip)
+ *
+ * Uninitializes the smileys parser subsystem.
+ */
+void
+_purple_smiley_parser_uninit(void);
+
 #endif /* _PURPLE_SMILEY_PARSER_H_ */
diff --git a/pidgin/themes/Contents/Resources/main.css b/pidgin/themes/Contents/Resources/main.css
--- a/pidgin/themes/Contents/Resources/main.css
+++ b/pidgin/themes/Contents/Resources/main.css
@@ -77,6 +77,11 @@ img
 
 /* Emoticons */
 
+.emoticon
+{
+	vertical-align: bottom;
+}
+
 .emoticon.pending
 {
 	cursor: progress;



More information about the Commits mailing list