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);