Mercurial > pidgin.yaz
comparison gtk/gtkimhtml.c @ 15359:7c41ecf41614
[gaim-migrate @ 18151]
Revert GtkIMHtml hacks that tried to fix gtkimhtml bugs, replace it with
heuristic workaround. If you receive a message with more than 100 HTML tags
strip all formatting before displaying it. Hopefully nobody has any legitimate
uses for 100 HTML tags in a message. I guess we'll see in beta6... which I think
we're good for now.
I think that post-2.0.0 we'll wind up replacing GtkIMHtml with a legitimate
HTML widget and do the Adium/Kopete "chat theme" thing. An HTML widget should
be able to handle formatting more efficiently than GtkTextView.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Thu, 18 Jan 2007 02:35:14 +0000 |
parents | 635cc5247696 |
children |
comparison
equal
deleted
inserted
replaced
15358:b49e2327088a | 15359:7c41ecf41614 |
---|---|
1213 | 1213 |
1214 if (imhtml->clipboard_text_string) { | 1214 if (imhtml->clipboard_text_string) { |
1215 g_free(imhtml->clipboard_text_string); | 1215 g_free(imhtml->clipboard_text_string); |
1216 g_free(imhtml->clipboard_html_string); | 1216 g_free(imhtml->clipboard_html_string); |
1217 } | 1217 } |
1218 | 1218 |
1219 for (l = imhtml->anchors; l; l = l->next) { | |
1220 GtkIMHtmlAnchor *anchor = l->data; | |
1221 gtk_imhtml_anchor_free(anchor); | |
1222 } | |
1223 | |
1224 g_slist_free(imhtml->anchors); | |
1225 g_list_free(imhtml->scalables); | 1219 g_list_free(imhtml->scalables); |
1226 g_slist_free(imhtml->im_images); | 1220 g_slist_free(imhtml->im_images); |
1227 g_free(imhtml->protocol_name); | 1221 g_free(imhtml->protocol_name); |
1228 g_free(imhtml->search_string); | 1222 g_free(imhtml->search_string); |
1229 g_object_unref(imhtml->empty_buffer); | |
1230 g_object_unref(imhtml->text_buffer); | |
1231 G_OBJECT_CLASS(parent_class)->finalize (object); | 1223 G_OBJECT_CLASS(parent_class)->finalize (object); |
1232 } | 1224 } |
1233 | 1225 |
1234 /* Boring GTK+ stuff */ | 1226 /* Boring GTK+ stuff */ |
1235 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) | 1227 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) |
1323 | 1315 |
1324 static void gtk_imhtml_init (GtkIMHtml *imhtml) | 1316 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
1325 { | 1317 { |
1326 GtkTextIter iter; | 1318 GtkTextIter iter; |
1327 imhtml->text_buffer = gtk_text_buffer_new(NULL); | 1319 imhtml->text_buffer = gtk_text_buffer_new(NULL); |
1328 imhtml->empty_buffer = gtk_text_buffer_new(NULL); | |
1329 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | 1320 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); |
1330 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | 1321 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); |
1331 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); | 1322 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
1332 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); | 1323 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
1333 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); | 1324 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); |
2362 imhtml->scroll_time = NULL; | 2353 imhtml->scroll_time = NULL; |
2363 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, imhtml, NULL); | 2354 imhtml->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, imhtml, NULL); |
2364 } | 2355 } |
2365 } | 2356 } |
2366 | 2357 |
2367 static gboolean | |
2368 set_adj_idle_cb(gpointer data) | |
2369 { | |
2370 GtkIMHtml *imhtml = data; | |
2371 | |
2372 gtk_adjustment_set_value(GTK_TEXT_VIEW(imhtml)->vadjustment, imhtml->adj); | |
2373 return FALSE; | |
2374 } | |
2375 | |
2376 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, | 2358 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, |
2377 const gchar *text, | 2359 const gchar *text, |
2378 GtkIMHtmlOptions options, | 2360 GtkIMHtmlOptions options, |
2379 GtkTextIter *iter) | 2361 GtkTextIter *iter) |
2380 { | 2362 { |
2381 GdkRectangle rect; | 2363 GdkRectangle rect; |
2382 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; | |
2383 GSList *anchors; | |
2384 gint pos = 0; | 2364 gint pos = 0; |
2385 gchar *ws; | 2365 gchar *ws; |
2386 gchar *tag; | 2366 gchar *tag; |
2387 gchar *bg = NULL; | 2367 gchar *bg = NULL; |
2388 gint len; | 2368 gint len; |
2389 gint tlen, smilelen, wpos=0; | 2369 gint tlen, smilelen, wpos=0; |
2390 gint type; | 2370 gint type; |
2391 const gchar *c; | 2371 const gchar *c; |
2392 gchar *amp; | 2372 gchar *amp; |
2393 gint len_protocol; | 2373 gint len_protocol; |
2394 gboolean refocus = GTK_WIDGET_HAS_FOCUS(imhtml); | |
2395 | |
2396 | 2374 |
2397 guint bold = 0, | 2375 guint bold = 0, |
2398 italics = 0, | 2376 italics = 0, |
2399 underline = 0, | 2377 underline = 0, |
2400 strike = 0, | 2378 strike = 0, |
2402 sup = 0, | 2380 sup = 0, |
2403 title = 0, | 2381 title = 0, |
2404 pre = 0; | 2382 pre = 0; |
2405 | 2383 |
2406 gboolean br = FALSE; | 2384 gboolean br = FALSE; |
2385 | |
2407 GSList *fonts = NULL; | 2386 GSList *fonts = NULL; |
2408 GObject *object; | 2387 GObject *object; |
2409 GtkIMHtmlScalable *scalable = NULL; | 2388 GtkIMHtmlScalable *scalable = NULL; |
2410 | 2389 |
2411 g_return_if_fail (imhtml != NULL); | 2390 g_return_if_fail (imhtml != NULL); |
2413 g_return_if_fail (text != NULL); | 2392 g_return_if_fail (text != NULL); |
2414 c = text; | 2393 c = text; |
2415 len = strlen(text); | 2394 len = strlen(text); |
2416 ws = g_malloc(len + 1); | 2395 ws = g_malloc(len + 1); |
2417 ws[0] = 0; | 2396 ws[0] = 0; |
2418 | |
2419 imhtml->adj = gtk_adjustment_get_value(adj); | |
2420 | |
2421 for (anchors = imhtml->anchors; anchors; anchors = anchors->next) { | |
2422 GtkIMHtmlAnchor *anchor = anchors->data; | |
2423 if (gtk_text_child_anchor_get_deleted(anchor->anchor)) { | |
2424 imhtml->anchors = g_slist_remove(imhtml->anchors, anchor); | |
2425 gtk_imhtml_anchor_free(anchor); | |
2426 continue; | |
2427 } | |
2428 gtk_container_remove(GTK_CONTAINER(imhtml), anchor->widget); | |
2429 | |
2430 } | |
2431 gtk_widget_hide(GTK_WIDGET(imhtml)); | |
2432 gtk_widget_unrealize(GTK_WIDGET(imhtml)); | |
2433 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->empty_buffer); | |
2434 | 2397 |
2435 while (pos < len) { | 2398 while (pos < len) { |
2436 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { | 2399 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
2437 c++; | 2400 c++; |
2438 pos++; | 2401 pos++; |
3086 g_free(bg); | 3049 g_free(bg); |
3087 | 3050 |
3088 if (!imhtml->wbfo) | 3051 if (!imhtml->wbfo) |
3089 gtk_imhtml_close_tags(imhtml, iter); | 3052 gtk_imhtml_close_tags(imhtml, iter); |
3090 | 3053 |
3091 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | |
3092 for (anchors = imhtml->anchors; anchors; anchors = anchors->next) { | |
3093 GtkIMHtmlAnchor *anchor = anchors->data; | |
3094 gtk_imhtml_add_anchor(imhtml, anchor); | |
3095 } | |
3096 object = g_object_ref(G_OBJECT(imhtml)); | 3054 object = g_object_ref(G_OBJECT(imhtml)); |
3097 gtk_widget_realize(GTK_WIDGET(imhtml)); | |
3098 gtk_widget_show_all(GTK_WIDGET(imhtml)); | |
3099 g_idle_add_full(G_PRIORITY_HIGH_IDLE, set_adj_idle_cb, imhtml, NULL); | |
3100 if (refocus) | |
3101 gtk_widget_grab_focus(GTK_WIDGET(imhtml)); | |
3102 g_signal_emit(object, signals[UPDATE_FORMAT], 0); | 3055 g_signal_emit(object, signals[UPDATE_FORMAT], 0); |
3103 g_object_unref(object); | 3056 g_object_unref(object); |
3057 | |
3104 } | 3058 } |
3105 | 3059 |
3106 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) | 3060 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
3107 { | 3061 { |
3108 g_hash_table_destroy(imhtml->smiley_data); | 3062 g_hash_table_destroy(imhtml->smiley_data); |
3489 g_free(scale); | 3443 g_free(scale); |
3490 } | 3444 } |
3491 | 3445 |
3492 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | 3446 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) |
3493 { | 3447 { |
3494 GtkIMHtmlAnchor *ianchor; | |
3495 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | 3448 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
3496 GtkWidget *box = gtk_event_box_new(); | 3449 GtkWidget *box = gtk_event_box_new(); |
3497 char *tag; | 3450 char *tag; |
3498 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | 3451 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
3499 | 3452 |
3507 | 3460 |
3508 tag = g_strdup_printf("<IMG ID=\"%d\">", image->id); | 3461 tag = g_strdup_printf("<IMG ID=\"%d\">", image->id); |
3509 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free); | 3462 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free); |
3510 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]"); | 3463 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]"); |
3511 | 3464 |
3512 ianchor = gtk_imhtml_anchor_new(anchor, box); | 3465 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); |
3513 imhtml->anchors = g_slist_append(imhtml->anchors, ianchor); | |
3514 | |
3515 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | 3466 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); |
3516 } | 3467 } |
3517 | 3468 |
3518 GtkIMHtmlScalable *gtk_imhtml_hr_new() | 3469 GtkIMHtmlScalable *gtk_imhtml_hr_new() |
3519 { | 3470 { |
3535 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width - 2, 2); | 3486 gtk_widget_set_size_request(((GtkIMHtmlHr *)scale)->sep, width - 2, 2); |
3536 } | 3487 } |
3537 | 3488 |
3538 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | 3489 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) |
3539 { | 3490 { |
3540 GtkIMHtmlAnchor *ianchor; | |
3541 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; | 3491 GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale; |
3542 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | 3492 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
3543 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>"); | 3493 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>"); |
3544 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n"); | 3494 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n"); |
3545 ianchor = gtk_imhtml_anchor_new(anchor, hr->sep); | 3495 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor); |
3546 imhtml->anchors = g_slist_append(imhtml->anchors, ianchor); | |
3547 } | 3496 } |
3548 | 3497 |
3549 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) | 3498 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale) |
3550 { | 3499 { |
3551 g_free(scale); | 3500 g_free(scale); |
3552 } | |
3553 | |
3554 GtkIMHtmlAnchor *gtk_imhtml_anchor_new(GtkTextChildAnchor *anchor, GtkWidget *widget) | |
3555 { | |
3556 GtkIMHtmlAnchor *a = g_new0(GtkIMHtmlAnchor, 1); | |
3557 a->anchor = anchor; | |
3558 a->widget = widget; | |
3559 | |
3560 g_object_ref(anchor); | |
3561 g_object_ref(widget); | |
3562 | |
3563 return a; | |
3564 } | |
3565 | |
3566 void gtk_imhtml_anchor_free(GtkIMHtmlAnchor *anchor) | |
3567 { | |
3568 g_object_unref(anchor->anchor); | |
3569 g_object_unref(anchor->widget); | |
3570 g_free(anchor); | |
3571 } | |
3572 | |
3573 void gtk_imhtml_add_anchor(GtkIMHtml *imhtml, GtkIMHtmlAnchor *anchor) | |
3574 { | |
3575 if (gtk_text_child_anchor_get_deleted(anchor->anchor)) { | |
3576 imhtml->anchors = g_slist_remove(imhtml->anchors, anchor); | |
3577 gtk_imhtml_anchor_free(anchor); | |
3578 return; | |
3579 } | |
3580 | |
3581 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), anchor->widget, anchor->anchor); | |
3582 } | 3501 } |
3583 | 3502 |
3584 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) | 3503 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text) |
3585 { | 3504 { |
3586 GtkTextIter iter, start, end; | 3505 GtkTextIter iter, start, end; |
4528 } | 4447 } |
4529 } | 4448 } |
4530 } | 4449 } |
4531 | 4450 |
4532 if (icon) { | 4451 if (icon) { |
4533 GtkIMHtmlAnchor *ianchor; | |
4534 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | 4452 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
4535 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); | 4453 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free); |
4536 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); | 4454 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free); |
4537 | 4455 |
4538 /* This catches the expose events generated by animated | 4456 /* This catches the expose events generated by animated |
4540 * itself, without propagating to the textview and causing | 4458 * itself, without propagating to the textview and causing |
4541 * a complete refresh */ | 4459 * a complete refresh */ |
4542 g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL); | 4460 g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL); |
4543 | 4461 |
4544 gtk_widget_show(icon); | 4462 gtk_widget_show(icon); |
4545 ianchor = gtk_imhtml_anchor_new(anchor, icon); | 4463 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); |
4546 imhtml->anchors = g_slist_append(imhtml->anchors, ianchor); | |
4547 if (imhtml->text_buffer == GTK_TEXT_VIEW(imhtml)->buffer) | |
4548 gtk_imhtml_add_anchor(imhtml, ianchor); | |
4549 } else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) { | 4464 } else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) { |
4550 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | 4465 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
4551 imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor); | 4466 imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor); |
4552 } else { | 4467 } else { |
4553 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); | 4468 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); |