# HG changeset patch # User Sadrul Habib Chowdhury # Date 1211951042 0 # Node ID dbde19256cab3c069f51768a9829cb9ec84500d5 # Parent bac674d6dcf58bc885c17396501dee91c234fce7 Fix the linkification. Also, remember the html-codes for a tag instead of always generating them everytime, and make sure a tag has both an opening and a closing tag. Thanks a lot to Dennis 'EvilDennisR' Ristuccia for detecting the cause of the problem. diff -r bac674d6dcf5 -r dbde19256cab pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Tue May 27 07:11:38 2008 +0000 +++ b/pidgin/gtkimhtml.c Wed May 28 05:04:02 2008 +0000 @@ -5046,6 +5046,7 @@ break; default: str += g_snprintf(str, sizeof(buf) - (str - buf), "text-decoration: underline;"); + empty = FALSE; } } @@ -5097,6 +5098,38 @@ } } +typedef struct { + GtkTextTag *tag; + char *end; + char *start; +} PidginTextTagData; + +static PidginTextTagData *text_tag_data_new(GtkTextTag *tag) +{ + const char *start, *end; + PidginTextTagData *ret = NULL; + + start = tag_to_html_start(tag); + if (!start || !*start) + return NULL; + end = tag_to_html_end(tag); + if (!end || !*end) + return NULL; + + ret = g_new0(PidginTextTagData, 1); + ret->start = g_strdup(start); + ret->end = g_strdup(end); + ret->tag = tag; + return ret; +} + +static void text_tag_data_destroy(PidginTextTagData *data) +{ + g_free(data->start); + g_free(data->end); + g_free(data); +} + static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) { return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && @@ -5117,12 +5150,11 @@ gboolean is_rtl_message = FALSE; GString *str = g_string_new(""); GSList *tags, *sl; - GQueue *q, *r; + GQueue *q; GtkTextTag *tag; + PidginTextTagData *tagdata; q = g_queue_new(); - r = g_queue_new(); - gtk_text_iter_order(start, end); non_neutral_iter = next_iter = iter = *start; @@ -5145,9 +5177,11 @@ for (sl = tags; sl; sl = sl->next) { tag = sl->data; if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { - if (strlen(tag_to_html_end(tag)) > 0) - g_string_append(str, tag_to_html_start(tag)); - g_queue_push_tail(q, tag); + PidginTextTagData *data = text_tag_data_new(tag); + if (data) { + g_string_append(str, data->start); + g_queue_push_tail(q, data); + } } } g_slist_free(tags); @@ -5159,13 +5193,14 @@ for (sl = tags; sl; sl = sl->next) { tag = sl->data; if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { - if (strlen(tag_to_html_end(tag)) > 0) - g_string_append(str, tag_to_html_start(tag)); - g_queue_push_tail(q, tag); + PidginTextTagData *data = text_tag_data_new(tag); + if (data) { + g_string_append(str, data->start); + g_queue_push_tail(q, data); + } } } - if (c == 0xFFFC) { GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); if (anchor) { @@ -5191,28 +5226,31 @@ for (sl = tags; sl; sl = sl->next) { tag = sl->data; /** don't worry about non-printing tags ending */ - if (tag_ends_here(tag, &iter, &next_iter) && strlen(tag_to_html_end(tag)) > 0) { - - GtkTextTag *tmp; - - while ((tmp = g_queue_pop_tail(q)) != tag) { - if (tmp == NULL) - break; - - if (!tag_ends_here(tmp, &iter, &next_iter) && strlen(tag_to_html_end(tmp)) > 0) + if (tag_ends_here(tag, &iter, &next_iter) && + strlen(tag_to_html_end(tag)) > 0 && + strlen(tag_to_html_start(tag)) > 0) { + + PidginTextTagData *tmp; + GQueue *r = g_queue_new(); + + while ((tmp = g_queue_pop_tail(q)) && tmp->tag != tag) { + g_string_append(str, tmp->end); + if (!tag_ends_here(tmp->tag, &iter, &next_iter)) g_queue_push_tail(r, tmp); - g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); + else + text_tag_data_destroy(tmp); } if (tmp == NULL) purple_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); else - g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); + g_string_append(str, tmp->end); while ((tmp = g_queue_pop_head(r))) { - g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); + g_string_append(str, tmp->start); g_queue_push_tail(q, tmp); } + g_queue_free(r); } } @@ -5221,15 +5259,16 @@ gtk_text_iter_forward_char(&next_iter); } - while ((tag = g_queue_pop_tail(q))) - g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); + while ((tagdata = g_queue_pop_tail(q))) { + g_string_append(str, tagdata->end); + text_tag_data_destroy(tagdata); + } /* Bi-directional text support - close tags */ if (is_rtl_message) g_string_append(str, ""); g_queue_free(q); - g_queue_free(r); return g_string_free(str, FALSE); }