Mercurial > pidgin.yaz
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 { |