comparison pidgin/gtkimhtml.c @ 23224:dbde19256cab

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.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Wed, 28 May 2008 05:04:02 +0000
parents 66ccd61eaff6
children 37866b3e549c
comparison
equal deleted inserted replaced
23223:bac674d6dcf5 23224:dbde19256cab
5044 case PANGO_UNDERLINE_NONE: 5044 case PANGO_UNDERLINE_NONE:
5045 case PANGO_UNDERLINE_ERROR: 5045 case PANGO_UNDERLINE_ERROR:
5046 break; 5046 break;
5047 default: 5047 default:
5048 str += g_snprintf(str, sizeof(buf) - (str - buf), "text-decoration: underline;"); 5048 str += g_snprintf(str, sizeof(buf) - (str - buf), "text-decoration: underline;");
5049 empty = FALSE;
5049 } 5050 }
5050 } 5051 }
5051 5052
5052 g_snprintf(str, sizeof(buf) - (str - buf), "'>"); 5053 g_snprintf(str, sizeof(buf) - (str - buf), "'>");
5053 5054
5095 5096
5096 return ""; 5097 return "";
5097 } 5098 }
5098 } 5099 }
5099 5100
5101 typedef struct {
5102 GtkTextTag *tag;
5103 char *end;
5104 char *start;
5105 } PidginTextTagData;
5106
5107 static PidginTextTagData *text_tag_data_new(GtkTextTag *tag)
5108 {
5109 const char *start, *end;
5110 PidginTextTagData *ret = NULL;
5111
5112 start = tag_to_html_start(tag);
5113 if (!start || !*start)
5114 return NULL;
5115 end = tag_to_html_end(tag);
5116 if (!end || !*end)
5117 return NULL;
5118
5119 ret = g_new0(PidginTextTagData, 1);
5120 ret->start = g_strdup(start);
5121 ret->end = g_strdup(end);
5122 ret->tag = tag;
5123 return ret;
5124 }
5125
5126 static void text_tag_data_destroy(PidginTextTagData *data)
5127 {
5128 g_free(data->start);
5129 g_free(data->end);
5130 g_free(data);
5131 }
5132
5100 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) 5133 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter)
5101 { 5134 {
5102 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && 5135 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) &&
5103 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) || 5136 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) ||
5104 gtk_text_iter_is_end(niter)); 5137 gtk_text_iter_is_end(niter));
5115 gunichar c; 5148 gunichar c;
5116 GtkTextIter iter, next_iter, non_neutral_iter; 5149 GtkTextIter iter, next_iter, non_neutral_iter;
5117 gboolean is_rtl_message = FALSE; 5150 gboolean is_rtl_message = FALSE;
5118 GString *str = g_string_new(""); 5151 GString *str = g_string_new("");
5119 GSList *tags, *sl; 5152 GSList *tags, *sl;
5120 GQueue *q, *r; 5153 GQueue *q;
5121 GtkTextTag *tag; 5154 GtkTextTag *tag;
5155 PidginTextTagData *tagdata;
5122 5156
5123 q = g_queue_new(); 5157 q = g_queue_new();
5124 r = g_queue_new();
5125
5126 5158
5127 gtk_text_iter_order(start, end); 5159 gtk_text_iter_order(start, end);
5128 non_neutral_iter = next_iter = iter = *start; 5160 non_neutral_iter = next_iter = iter = *start;
5129 gtk_text_iter_forward_char(&next_iter); 5161 gtk_text_iter_forward_char(&next_iter);
5130 5162
5143 tags = gtk_text_iter_get_tags(start); 5175 tags = gtk_text_iter_get_tags(start);
5144 5176
5145 for (sl = tags; sl; sl = sl->next) { 5177 for (sl = tags; sl; sl = sl->next) {
5146 tag = sl->data; 5178 tag = sl->data;
5147 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { 5179 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) {
5148 if (strlen(tag_to_html_end(tag)) > 0) 5180 PidginTextTagData *data = text_tag_data_new(tag);
5149 g_string_append(str, tag_to_html_start(tag)); 5181 if (data) {
5150 g_queue_push_tail(q, tag); 5182 g_string_append(str, data->start);
5183 g_queue_push_tail(q, data);
5184 }
5151 } 5185 }
5152 } 5186 }
5153 g_slist_free(tags); 5187 g_slist_free(tags);
5154 5188
5155 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { 5189 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) {
5157 tags = gtk_text_iter_get_tags(&iter); 5191 tags = gtk_text_iter_get_tags(&iter);
5158 5192
5159 for (sl = tags; sl; sl = sl->next) { 5193 for (sl = tags; sl; sl = sl->next) {
5160 tag = sl->data; 5194 tag = sl->data;
5161 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { 5195 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) {
5162 if (strlen(tag_to_html_end(tag)) > 0) 5196 PidginTextTagData *data = text_tag_data_new(tag);
5163 g_string_append(str, tag_to_html_start(tag)); 5197 if (data) {
5164 g_queue_push_tail(q, tag); 5198 g_string_append(str, data->start);
5199 g_queue_push_tail(q, data);
5200 }
5165 } 5201 }
5166 } 5202 }
5167
5168 5203
5169 if (c == 0xFFFC) { 5204 if (c == 0xFFFC) {
5170 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); 5205 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter);
5171 if (anchor) { 5206 if (anchor) {
5172 char *text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_htmltext"); 5207 char *text = g_object_get_data(G_OBJECT(anchor), "gtkimhtml_htmltext");
5189 5224
5190 tags = g_slist_reverse(tags); 5225 tags = g_slist_reverse(tags);
5191 for (sl = tags; sl; sl = sl->next) { 5226 for (sl = tags; sl; sl = sl->next) {
5192 tag = sl->data; 5227 tag = sl->data;
5193 /** don't worry about non-printing tags ending */ 5228 /** don't worry about non-printing tags ending */
5194 if (tag_ends_here(tag, &iter, &next_iter) && strlen(tag_to_html_end(tag)) > 0) { 5229 if (tag_ends_here(tag, &iter, &next_iter) &&
5195 5230 strlen(tag_to_html_end(tag)) > 0 &&
5196 GtkTextTag *tmp; 5231 strlen(tag_to_html_start(tag)) > 0) {
5197 5232
5198 while ((tmp = g_queue_pop_tail(q)) != tag) { 5233 PidginTextTagData *tmp;
5199 if (tmp == NULL) 5234 GQueue *r = g_queue_new();
5200 break; 5235
5201 5236 while ((tmp = g_queue_pop_tail(q)) && tmp->tag != tag) {
5202 if (!tag_ends_here(tmp, &iter, &next_iter) && strlen(tag_to_html_end(tmp)) > 0) 5237 g_string_append(str, tmp->end);
5238 if (!tag_ends_here(tmp->tag, &iter, &next_iter))
5203 g_queue_push_tail(r, tmp); 5239 g_queue_push_tail(r, tmp);
5204 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); 5240 else
5241 text_tag_data_destroy(tmp);
5205 } 5242 }
5206 5243
5207 if (tmp == NULL) 5244 if (tmp == NULL)
5208 purple_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); 5245 purple_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n");
5209 else 5246 else
5210 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); 5247 g_string_append(str, tmp->end);
5211 5248
5212 while ((tmp = g_queue_pop_head(r))) { 5249 while ((tmp = g_queue_pop_head(r))) {
5213 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); 5250 g_string_append(str, tmp->start);
5214 g_queue_push_tail(q, tmp); 5251 g_queue_push_tail(q, tmp);
5215 } 5252 }
5253 g_queue_free(r);
5216 } 5254 }
5217 } 5255 }
5218 5256
5219 g_slist_free(tags); 5257 g_slist_free(tags);
5220 gtk_text_iter_forward_char(&iter); 5258 gtk_text_iter_forward_char(&iter);
5221 gtk_text_iter_forward_char(&next_iter); 5259 gtk_text_iter_forward_char(&next_iter);
5222 } 5260 }
5223 5261
5224 while ((tag = g_queue_pop_tail(q))) 5262 while ((tagdata = g_queue_pop_tail(q))) {
5225 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); 5263 g_string_append(str, tagdata->end);
5264 text_tag_data_destroy(tagdata);
5265 }
5226 5266
5227 /* Bi-directional text support - close tags */ 5267 /* Bi-directional text support - close tags */
5228 if (is_rtl_message) 5268 if (is_rtl_message)
5229 g_string_append(str, "</SPAN>"); 5269 g_string_append(str, "</SPAN>");
5230 5270
5231 g_queue_free(q); 5271 g_queue_free(q);
5232 g_queue_free(r);
5233 return g_string_free(str, FALSE); 5272 return g_string_free(str, FALSE);
5234 } 5273 }
5235 5274
5236 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter) 5275 void gtk_imhtml_close_tags(GtkIMHtml *imhtml, GtkTextIter *iter)
5237 { 5276 {