aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk/empathy-theme-adium.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy-gtk/empathy-theme-adium.c')
-rw-r--r--libempathy-gtk/empathy-theme-adium.c216
1 files changed, 126 insertions, 90 deletions
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
index a41cbd6c0..a83b8da86 100644
--- a/libempathy-gtk/empathy-theme-adium.c
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -191,33 +191,107 @@ theme_adium_open_address_cb (GtkMenuItem *menuitem,
g_free (uri);
}
-static gchar *
-theme_adium_parse_body (EmpathyThemeAdium *theme,
- const gchar *text)
+static void
+theme_adium_parser_escape (GString *string,
+ const gchar *text,
+ gssize len)
{
- EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
- gboolean use_smileys = FALSE;
- GSList *smileys, *l;
- GString *string;
- gint i;
- GRegex *uri_regex;
- GMatchInfo *match_info;
- gboolean match;
- gchar *ret = NULL;
- gint prev;
+ gchar *escaped;
+
+ escaped = g_markup_escape_text (text, len);
+ g_string_append (string, escaped);
+ g_free (escaped);
+}
+
+static void
+theme_adium_parser_newline (GString *string,
+ const gchar *text,
+ gssize len)
+{
+ gint i;
+ gint prev = 0;
+
+ if (len < 0) {
+ len = G_MAXSSIZE;
+ }
+
+ /* Replace \n by <br/> */
+ for (i = 0; i < len && text[i] != '\0'; i++) {
+ if (text[i] == '\n') {
+ theme_adium_parser_escape (string, text + prev, i - prev);
+ g_string_append (string, "<br/>");
+ prev = i + 1;
+ }
+ }
+ theme_adium_parser_escape (string, text + prev, i - prev);
+}
+
+static void
+theme_adium_parser_smiley (GString *string,
+ const gchar *text,
+ gssize len)
+{
+ gboolean use_smileys = FALSE;
+ gint last = 0;
empathy_conf_get_bool (empathy_conf_get (),
EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
&use_smileys);
+ if (use_smileys) {
+ EmpathySmileyManager *smiley_manager;
+ GSList *hits, *l;
+
+ smiley_manager = empathy_smiley_manager_dup_singleton ();
+ hits = empathy_smiley_manager_parse_len (smiley_manager, text, len);
+
+ for (l = hits; l; l = l->next) {
+ EmpathySmileyHit *hit = l->data;
+
+ if (hit->start > last) {
+ /* Append the text between last smiley (or the
+ * start of the message) and this smiley */
+ theme_adium_parser_newline (string, text + last,
+ hit->start - last);
+ }
+
+ /* Replace smileys by a <img/> tag */
+ g_string_append (string, "<abbr title=\"");
+ g_string_append_len (string, text + hit->start,
+ hit->end - hit->start);
+ g_string_append_printf (string, "\"><img src=\"%s\" alt=\"",
+ hit->path);
+ g_string_append_len (string, text + hit->start,
+ hit->end - hit->start);
+ g_string_append (string, "\"/></abbr>");
+
+ last = hit->end;
+
+ empathy_smiley_hit_free (hit);
+ }
+ g_slist_free (hits);
+ g_object_unref (smiley_manager);
+ }
+
+ theme_adium_parser_newline (string, text + last, len - last);
+}
+
+static void
+theme_adium_parser_url (GString *string,
+ const gchar *text,
+ gssize len)
+{
+ GRegex *uri_regex;
+ GMatchInfo *match_info;
+ gboolean match;
+ gint last = 0;
+
/* Add <a href></a> arround links */
uri_regex = empathy_uri_regex_dup_singleton ();
- match = g_regex_match (uri_regex, text, 0, &match_info);
+ match = g_regex_match_full (uri_regex, text, len, 0, 0, &match_info, NULL);
if (match) {
- gint last = 0;
gint s = 0, e = 0;
- string = g_string_sized_new (strlen (text));
do {
gchar *real_url;
@@ -226,87 +300,52 @@ theme_adium_parse_body (EmpathyThemeAdium *theme,
if (s > last) {
/* Append the text between last link (or the
* start of the message) and this link */
- gchar *str;
- str = g_markup_escape_text (text + last, s - last);
- g_string_append (string, str);
- g_free (str);
+ theme_adium_parser_smiley (string, text + last,
+ s - last);
}
/* Append the link inside <a href=""></a> tag */
real_url = empathy_make_absolute_url_len (text + s, e - s);
- g_string_append (string, "<a href=\"");
- g_string_append (string, real_url);
- g_string_append (string, "\">");
+ g_string_append_printf (string, "<a href=\"%s\">",
+ real_url);
g_string_append_len (string, text + s, e - s);
g_string_append (string, "</a>");
g_free (real_url);
last = e;
} while (g_match_info_next (match_info, NULL));
-
- if (e < (gint) strlen (text)) {
- /* Append the text after the last link */
- gchar *str;
- str = g_markup_escape_text (text + e, strlen (text) - e);
- g_string_append (string, str);
- g_free (str);
- }
-
- g_free (ret);
- text = ret = g_string_free (string, FALSE);
- } else if (use_smileys) {
- /* Replace smileys by a <img/> tag */
- string = g_string_sized_new (strlen (text));
- smileys = empathy_smiley_manager_parse (priv->smiley_manager, text);
- for (l = smileys; l; l = l->next) {
- EmpathySmiley *smiley;
-
- smiley = l->data;
- if (smiley->path) {
- g_string_append_printf (string,
- "<abbr title='%s'><img src=\"%s\"/ alt=\"%s\"/></abbr>",
- smiley->str, smiley->path, smiley->str);
- } else {
- gchar *str;
-
- str = g_markup_escape_text (smiley->str, -1);
- g_string_append (string, str);
- g_free (str);
- }
- empathy_smiley_free (smiley);
- }
- g_slist_free (smileys);
-
- g_free (ret);
- text = ret = g_string_free (string, FALSE);
- } else {
- text = ret = g_markup_escape_text (text, -1);
}
+ theme_adium_parser_smiley (string, text + last, len - last);
+
g_match_info_free (match_info);
g_regex_unref (uri_regex);
+}
- /* Replace \n by <br/> */
- string = NULL;
- prev = 0;
- for (i = 0; text[i] != '\0'; i++) {
- if (text[i] == '\n') {
- if (!string ) {
- string = g_string_sized_new (strlen (text));
- }
- g_string_append_len (string, text + prev, i - prev);
- g_string_append (string, "<br/>");
- prev = i + 1;
- }
- }
- if (string) {
- g_string_append (string, text + prev);
- g_free (ret);
- text = ret = g_string_free (string, FALSE);
- }
-
- return ret;
+static gchar *
+theme_adium_parse_body (const gchar *text)
+{
+ GString *string;
+
+ /* We parse text in 4 steps: url, smiley, newline, escape.
+ * For each step, we detect the position of tokens in the text, and
+ * we give text between each token to the next level parser.
+ *
+ * For example the string "Hello :)\n www.test.com"
+ * 1) The url parser detects "www.test.com" and gives "Hello :)\n " to
+ * the smiley parser, then insert the <a> tag for the link.
+ * 2) The smiley parser will detect ":)". It first gives "Hello "
+ * to the newline parser, then insert the <img/> tag for the smiley,
+ * and finally give "\n " to the newline parser.
+ * 3a) The newline parser gets "Hello " and escape it.
+ * 3b) The newline parser gets "\n " and replace to "<br/> ".
+ */
+
+ string = g_string_sized_new (strlen (text));
+ theme_adium_parser_url (string, text, -1);
+
+ return g_string_free (string, FALSE);
}
static void
@@ -442,7 +481,7 @@ theme_adium_append_message (EmpathyChatView *view,
EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
EmpathyContact *sender;
TpAccount *account;
- gchar *dup_body = NULL;
+ gchar *body_escaped;
const gchar *body;
const gchar *name;
const gchar *contact_id;
@@ -472,10 +511,7 @@ theme_adium_append_message (EmpathyChatView *view,
service_name = tp_account_get_protocol (account);
timestamp = empathy_message_get_timestamp (msg);
body = empathy_message_get_body (msg);
- dup_body = theme_adium_parse_body (theme, body);
- if (dup_body) {
- body = dup_body;
- }
+ body_escaped = theme_adium_parse_body (body);
name = empathy_contact_get_name (sender);
contact_id = empathy_contact_get_id (sender);
@@ -483,10 +519,10 @@ theme_adium_append_message (EmpathyChatView *view,
if (empathy_message_get_tptype (msg) == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION) {
gchar *str;
- str = g_strdup_printf ("%s %s", name, body);
+ str = g_strdup_printf ("%s %s", name, body_escaped);
empathy_chat_view_append_event (view, str);
g_free (str);
- g_free (dup_body);
+ g_free (body_escaped);
return;
}
@@ -607,7 +643,7 @@ theme_adium_append_message (EmpathyChatView *view,
}
if (html != NULL) {
- theme_adium_append_html (theme, func, html, len, body,
+ theme_adium_append_html (theme, func, html, len, body_escaped,
avatar_filename, name, contact_id,
service_name, message_classes->str,
timestamp);
@@ -623,7 +659,7 @@ theme_adium_append_message (EmpathyChatView *view,
priv->last_timestamp = timestamp;
priv->last_is_backlog = is_backlog;
- g_free (dup_body);
+ g_free (body_escaped);
g_string_free (message_classes, TRUE);
}