/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