Mercurial > pidgin
comparison src/gtkimhtml.c @ 8677:cc2ce209cc46
[gaim-migrate @ 9430]
marv's patch for GtkIMHtml.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sat, 17 Apr 2004 13:58:29 +0000 |
parents | 44d6285a87af |
children | e2e56231023c |
comparison
equal
deleted
inserted
replaced
8676:e096d797d958 | 8677:cc2ce209cc46 |
---|---|
61 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD | 61 #define GTK_WRAP_WORD_CHAR GTK_WRAP_WORD |
62 #endif | 62 #endif |
63 | 63 |
64 #define TOOLTIP_TIMEOUT 500 | 64 #define TOOLTIP_TIMEOUT 500 |
65 | 65 |
66 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); | |
66 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); | 67 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml); |
67 static gboolean gtk_imhtml_is_amp_escape (const gchar *string, gchar **replace, gint *length); | 68 static gboolean gtk_imhtml_is_amp_escape (const gchar *string, gchar **replace, gint *length); |
68 void gtk_imhtml_close_tags(GtkIMHtml *imhtml); | 69 void gtk_imhtml_close_tags(GtkIMHtml *imhtml); |
69 static void gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml); | 70 static void gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml); |
71 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, GtkIMHtml *imhtml); | |
70 | 72 |
71 /* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a | 73 /* POINT_SIZE converts from AIM font sizes to point sizes. It probably should be redone in such a |
72 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ | 74 * way that it base the sizes off the default font size rather than using arbitrary font sizes. */ |
73 #define MAX_FONT_SIZE 7 | 75 #define MAX_FONT_SIZE 7 |
74 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) | 76 #define POINT_SIZE(x) (options & GTK_IMHTML_USE_POINTSIZE ? x : _point_sizes [MIN ((x), MAX_FONT_SIZE) - 1]) |
75 static gdouble _point_sizes [] = { .69444444, .8333333, 1, 1.2, 1.44, 1.728, 2.0736}; | 77 static gdouble _point_sizes [] = { .69444444, .8333333, 1, 1.2, 1.44, 1.728, 2.0736}; |
76 | 78 |
77 enum { | 79 enum { |
78 TARGET_HTML, | 80 TARGET_HTML, |
79 TARGET_UTF8_STRING, | 81 TARGET_UTF8_STRING, |
80 TARGET_COMPOUND_TEXT, | 82 TARGET_COMPOUND_TEXT, |
81 TARGET_STRING, | 83 TARGET_STRING, |
82 TARGET_TEXT | 84 TARGET_TEXT |
83 }; | 85 }; |
382 /* | 384 /* |
383 * I'm adding some keyboard shortcuts too. | 385 * I'm adding some keyboard shortcuts too. |
384 */ | 386 */ |
385 | 387 |
386 gboolean gtk_key_pressed_cb(GtkIMHtml *imhtml, GdkEventKey *event, gpointer data) | 388 gboolean gtk_key_pressed_cb(GtkIMHtml *imhtml, GdkEventKey *event, gpointer data) |
387 { | 389 { |
388 char buf[7]; | 390 char buf[7]; |
389 buf[0] = '\0'; | 391 buf[0] = '\0'; |
390 | 392 |
391 if (event->state & GDK_CONTROL_MASK) | 393 if (event->state & GDK_CONTROL_MASK) |
392 switch (event->keyval) { | 394 switch (event->keyval) { |
393 #if (!GTK_CHECK_VERSION(2,2,0)) | 395 #if (!GTK_CHECK_VERSION(2,2,0)) |
394 case 'a': | 396 case 'a': |
395 return TRUE; | 397 return TRUE; |
396 break; | 398 break; |
397 | 399 |
398 case GDK_Home: | 400 case GDK_Home: |
399 return TRUE; | 401 return TRUE; |
400 break; | 402 break; |
401 | 403 |
402 case GDK_End: | 404 case GDK_End: |
458 case '+': | 460 case '+': |
459 if (imhtml->format_functions & GTK_IMHTML_GROW) | 461 if (imhtml->format_functions & GTK_IMHTML_GROW) |
460 gtk_imhtml_font_grow(imhtml); | 462 gtk_imhtml_font_grow(imhtml); |
461 return TRUE; | 463 return TRUE; |
462 break; | 464 break; |
463 | 465 |
464 case '1': strcpy(buf, ":-)"); break; | 466 case '1': strcpy(buf, ":-)"); break; |
465 case '2': strcpy(buf, ":-("); break; | 467 case '2': strcpy(buf, ":-("); break; |
466 case '3': strcpy(buf, ";-)"); break; | 468 case '3': strcpy(buf, ";-)"); break; |
467 case '4': strcpy(buf, ":-P"); break; | 469 case '4': strcpy(buf, ":-P"); break; |
468 case '5': strcpy(buf, "=-O"); break; | 470 case '5': strcpy(buf, "=-O"); break; |
479 case '*': strcpy(buf, ":-D"); break; | 481 case '*': strcpy(buf, ":-D"); break; |
480 } | 482 } |
481 if (*buf && imhtml->smiley_shortcuts) { | 483 if (*buf && imhtml->smiley_shortcuts) { |
482 gtk_imhtml_insert_smiley(imhtml, imhtml->protocol_name, buf); | 484 gtk_imhtml_insert_smiley(imhtml, imhtml->protocol_name, buf); |
483 return TRUE; | 485 return TRUE; |
484 } | 486 } |
485 return FALSE; | 487 return FALSE; |
486 } | 488 } |
487 | 489 |
488 #if GTK_CHECK_VERSION(2,2,0) | 490 #if GTK_CHECK_VERSION(2,2,0) |
489 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) { | 491 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) { |
508 selection = g_convert(str->str, str->len, "UCS-2", "UTF-8", NULL, &len, NULL); | 510 selection = g_convert(str->str, str->len, "UCS-2", "UTF-8", NULL, &len, NULL); |
509 gtk_selection_data_set (selection_data, gdk_atom_intern("text/html", FALSE), 16, selection, len); | 511 gtk_selection_data_set (selection_data, gdk_atom_intern("text/html", FALSE), 16, selection, len); |
510 g_string_free(str, TRUE); | 512 g_string_free(str, TRUE); |
511 g_free(selection); | 513 g_free(selection); |
512 } else { | 514 } else { |
513 text = gtk_text_buffer_get_text(imhtml->text_buffer, &start, &end, FALSE); | 515 text = gtk_imhtml_get_text(imhtml, &start, &end); |
514 gtk_selection_data_set_text(selection_data, text, strlen(text)); | 516 gtk_selection_data_set_text(selection_data, text, strlen(text)); |
515 } | 517 } |
516 g_free(text); | 518 g_free(text); |
517 } | 519 } |
518 | 520 |
530 gtk_text_buffer_move_mark (imhtml->text_buffer, | 532 gtk_text_buffer_move_mark (imhtml->text_buffer, |
531 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound"), | 533 gtk_text_buffer_get_mark (imhtml->text_buffer, "selection_bound"), |
532 &insert); | 534 &insert); |
533 } | 535 } |
534 | 536 |
535 static void copy_clipboard_cb(GtkIMHtml *imhtml, GtkClipboard *clipboard) | 537 static void copy_clipboard_cb(GtkIMHtml *imhtml, gpointer unused) |
536 { | 538 { |
537 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), | 539 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD), |
538 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | 540 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), |
539 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | 541 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, |
540 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); | 542 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml)); |
545 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) | 547 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) |
546 { | 548 { |
547 char *text; | 549 char *text; |
548 guint16 c; | 550 guint16 c; |
549 GtkIMHtml *imhtml = data; | 551 GtkIMHtml *imhtml = data; |
552 GtkTextIter iter; | |
550 | 553 |
551 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) | 554 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) |
552 return; | 555 return; |
553 | 556 |
554 if (selection_data->length < 0) { | 557 if (selection_data->length < 0) { |
567 /* This is UCS2 */ | 570 /* This is UCS2 */ |
568 char *utf8 = g_convert(text+2, (selection_data->length * (selection_data->format / 8)) - 2, "UTF-8", "UCS-2", NULL, NULL, NULL); | 571 char *utf8 = g_convert(text+2, (selection_data->length * (selection_data->format / 8)) - 2, "UTF-8", "UCS-2", NULL, NULL, NULL); |
569 g_free(text); | 572 g_free(text); |
570 text = utf8; | 573 text = utf8; |
571 } | 574 } |
572 gtk_imhtml_close_tags(imhtml); | 575 if (!imhtml->wbfo) |
573 gtk_imhtml_append_text_with_images(imhtml, text, GTK_IMHTML_NO_NEWLINE, NULL); | 576 gtk_imhtml_close_tags(imhtml); |
577 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
578 gtk_imhtml_insert_html_at_iter(imhtml, text, GTK_IMHTML_NO_NEWLINE, &iter); | |
579 gtk_text_buffer_move_mark_by_name(imhtml->text_buffer, "insert", &iter); | |
574 } | 580 } |
575 | 581 |
576 | 582 |
577 static void paste_clipboard_cb(GtkIMHtml *imhtml, gpointer blah) | 583 static void paste_clipboard_cb(GtkIMHtml *imhtml, gpointer blah) |
578 { | 584 { |
581 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | 587 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), |
582 paste_received_cb, imhtml); | 588 paste_received_cb, imhtml); |
583 g_signal_stop_emission_by_name(imhtml, "paste-clipboard"); | 589 g_signal_stop_emission_by_name(imhtml, "paste-clipboard"); |
584 } | 590 } |
585 | 591 |
586 static gboolean button_release_cb(GtkIMHtml *imhtml, GdkEventButton event, gpointer the_foibles_of_man) | 592 static void imhtml_realized_remove_primary(GtkIMHtml *imhtml, gpointer unused) |
587 { | 593 { |
588 GtkClipboard *clipboard; | 594 gtk_text_buffer_remove_selection_clipboard(GTK_IMHTML(imhtml)->text_buffer, |
589 if (event.button == 1) { | 595 gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); |
590 if ((clipboard = gtk_widget_get_clipboard (GTK_WIDGET (imhtml), | 596 |
591 GDK_SELECTION_PRIMARY))) | 597 } |
592 gtk_text_buffer_remove_selection_clipboard (imhtml->text_buffer, clipboard); | 598 |
599 #endif | |
600 | |
601 static void mark_set_so_update_selection_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, GtkIMHtml *imhtml) | |
602 { | |
603 if (gtk_text_buffer_get_selection_bounds(buffer, NULL, NULL)) { | |
593 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY), | 604 gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY), |
594 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), | 605 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry), |
595 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, | 606 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get, |
596 (GtkClipboardClearFunc)gtk_imhtml_primary_clipboard_clear, G_OBJECT(imhtml)); | 607 (GtkClipboardClearFunc)gtk_imhtml_primary_clipboard_clear, G_OBJECT(imhtml)); |
597 } | 608 } |
609 } | |
610 | |
611 /* does this go in the #ifdef too? I need to keep track of which functions are 2.2 only */ | |
612 /* adapted from gtktextview.c */ | |
613 static gboolean gtk_imhtml_button_press_event(GtkIMHtml *imhtml, GdkEventButton *event, gpointer unused) | |
614 { | |
615 if (event->button == 2) { | |
616 int x, y; | |
617 GtkTextIter iter; | |
618 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY); | |
619 | |
620 if (!imhtml->editable) | |
621 return FALSE; | |
622 | |
623 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), | |
624 GTK_TEXT_WINDOW_TEXT, | |
625 event->x, | |
626 event->y, | |
627 &x, | |
628 &y); | |
629 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); | |
630 gtk_text_buffer_place_cursor(imhtml->text_buffer, &iter); | |
631 | |
632 gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), | |
633 paste_received_cb, imhtml); | |
634 | |
635 return TRUE; | |
636 } | |
637 | |
598 return FALSE; | 638 return FALSE; |
599 } | 639 } |
600 #endif | |
601 | |
602 | 640 |
603 static GtkTextViewClass *parent_class = NULL; | 641 static GtkTextViewClass *parent_class = NULL; |
604 | 642 |
605 static void | 643 static void |
606 gtk_imhtml_finalize (GObject *object) | 644 gtk_imhtml_finalize (GObject *object) |
611 g_hash_table_destroy(imhtml->smiley_data); | 649 g_hash_table_destroy(imhtml->smiley_data); |
612 gtk_smiley_tree_destroy(imhtml->default_smilies); | 650 gtk_smiley_tree_destroy(imhtml->default_smilies); |
613 gdk_cursor_unref(imhtml->hand_cursor); | 651 gdk_cursor_unref(imhtml->hand_cursor); |
614 gdk_cursor_unref(imhtml->arrow_cursor); | 652 gdk_cursor_unref(imhtml->arrow_cursor); |
615 gdk_cursor_unref(imhtml->text_cursor); | 653 gdk_cursor_unref(imhtml->text_cursor); |
616 | 654 |
617 if(imhtml->tip_window){ | 655 if(imhtml->tip_window){ |
618 gtk_widget_destroy(imhtml->tip_window); | 656 gtk_widget_destroy(imhtml->tip_window); |
619 } | 657 } |
620 if(imhtml->tip_timer) | 658 if(imhtml->tip_timer) |
621 gtk_timeout_remove(imhtml->tip_timer); | 659 gtk_timeout_remove(imhtml->tip_timer); |
686 static void gtk_imhtml_init (GtkIMHtml *imhtml) | 724 static void gtk_imhtml_init (GtkIMHtml *imhtml) |
687 { | 725 { |
688 GtkTextIter iter; | 726 GtkTextIter iter; |
689 imhtml->text_buffer = gtk_text_buffer_new(NULL); | 727 imhtml->text_buffer = gtk_text_buffer_new(NULL); |
690 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); | 728 gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter); |
691 imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); | 729 imhtml->scrollpoint = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE); |
692 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); | 730 gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer); |
693 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); | 731 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR); |
694 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); | 732 gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5); |
733 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(imhtml), 2); | |
734 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(imhtml), 2); | |
695 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ | 735 /*gtk_text_view_set_indent(GTK_TEXT_VIEW(imhtml), -15);*/ |
696 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ | 736 /*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/ |
697 | 737 |
698 /* These tags will be used often and can be reused--we create them on init and then apply them by name | 738 /* These tags will be used often and can be reused--we create them on init and then apply them by name |
699 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ | 739 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ |
703 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); | 743 gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL); |
704 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); | 744 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL); |
705 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); | 745 gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL); |
706 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); | 746 gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL); |
707 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); | 747 gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL); |
708 gtk_text_buffer_create_tag(imhtml->text_buffer, "LINK", "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); | 748 |
709 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ | 749 /* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */ |
710 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); | 750 imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2); |
711 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); | 751 imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); |
712 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); | 752 imhtml->text_cursor = gdk_cursor_new (GDK_XTERM); |
713 | 753 |
720 | 760 |
721 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); | 761 g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); |
722 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); | 762 g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); |
723 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); | 763 g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); |
724 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); | 764 g_signal_connect(G_OBJECT(imhtml), "key_press_event", G_CALLBACK(gtk_key_pressed_cb), NULL); |
765 g_signal_connect(G_OBJECT(imhtml), "button_press_event", G_CALLBACK(gtk_imhtml_button_press_event), NULL); | |
766 g_signal_connect(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(preinsert_cb), imhtml); | |
725 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); | 767 g_signal_connect_after(G_OBJECT(imhtml->text_buffer), "insert-text", G_CALLBACK(insert_cb), imhtml); |
726 | 768 |
727 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, | 769 gtk_drag_dest_set(GTK_WIDGET(imhtml), 0, |
728 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), | 770 link_drag_drop_targets, sizeof(link_drag_drop_targets) / sizeof(GtkTargetEntry), |
729 GDK_ACTION_COPY); | 771 GDK_ACTION_COPY); |
730 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); | 772 g_signal_connect(G_OBJECT(imhtml), "drag_data_received", G_CALLBACK(gtk_imhtml_link_drag_rcv_cb), imhtml); |
731 | 773 |
732 #if GTK_CHECK_VERSION(2,2,0) | 774 #if GTK_CHECK_VERSION(2,2,0) |
733 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); | 775 g_signal_connect(G_OBJECT(imhtml), "copy-clipboard", G_CALLBACK(copy_clipboard_cb), NULL); |
734 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); | 776 g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); |
735 g_signal_connect(G_OBJECT(imhtml), "button-release-event", G_CALLBACK(button_release_cb), imhtml); | 777 //g_signal_connect_after(G_OBJECT(imhtml), "button-release-event", G_CALLBACK(button_release_cb), imhtml); |
778 g_signal_connect_after(G_OBJECT(imhtml), "realize", G_CALLBACK(imhtml_realized_remove_primary), NULL); | |
736 #endif | 779 #endif |
780 | |
781 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
782 G_CALLBACK(mark_set_so_update_selection_cb), imhtml); | |
783 | |
737 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); | 784 gtk_widget_add_events(GTK_WIDGET(imhtml), GDK_LEAVE_NOTIFY_MASK); |
738 | 785 |
739 imhtml->tip = NULL; | 786 imhtml->tip = NULL; |
740 imhtml->tip_timer = 0; | 787 imhtml->tip_timer = 0; |
741 imhtml->tip_window = NULL; | 788 imhtml->tip_window = NULL; |
742 | 789 |
743 imhtml->edit.bold = NULL; | 790 imhtml->edit.bold = FALSE; |
744 imhtml->edit.italic = NULL; | 791 imhtml->edit.italic = FALSE; |
745 imhtml->edit.underline = NULL; | 792 imhtml->edit.underline = FALSE; |
746 imhtml->edit.forecolor = NULL; | 793 imhtml->edit.forecolor = NULL; |
747 imhtml->edit.backcolor = NULL; | 794 imhtml->edit.backcolor = NULL; |
748 imhtml->edit.fontface = NULL; | 795 imhtml->edit.fontface = NULL; |
749 imhtml->edit.sizespan = NULL; | 796 imhtml->edit.fontsize = 0; |
750 imhtml->edit.fontsize = 3; | 797 imhtml->edit.link = NULL; |
751 | 798 |
752 imhtml->format_spans = NULL; | |
753 | 799 |
754 imhtml->scalables = NULL; | 800 imhtml->scalables = NULL; |
755 | 801 |
756 gtk_imhtml_set_editable(imhtml, FALSE); | 802 gtk_imhtml_set_editable(imhtml, FALSE); |
757 } | 803 } |
788 struct url_data { | 834 struct url_data { |
789 GObject *object; | 835 GObject *object; |
790 gchar *url; | 836 gchar *url; |
791 }; | 837 }; |
792 | 838 |
839 static void url_data_destroy(gpointer mydata) | |
840 { | |
841 struct url_data *data = mydata; | |
842 g_object_unref(data->object); | |
843 g_free(data->url); | |
844 g_free(data); | |
845 } | |
846 | |
793 static void url_open(GtkWidget *w, struct url_data *data) { | 847 static void url_open(GtkWidget *w, struct url_data *data) { |
794 if(!data) return; | 848 if(!data) return; |
795 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); | 849 g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url); |
796 | 850 |
797 g_object_unref(data->object); | |
798 g_free(data->url); | |
799 g_free(data); | |
800 } | 851 } |
801 | 852 |
802 static void url_copy(GtkWidget *w, gchar *url) { | 853 static void url_copy(GtkWidget *w, gchar *url) { |
803 GtkClipboard *clipboard; | 854 GtkClipboard *clipboard; |
804 | 855 |
808 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); | 859 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); |
809 gtk_clipboard_set_text(clipboard, url, -1); | 860 gtk_clipboard_set_text(clipboard, url, -1); |
810 } | 861 } |
811 | 862 |
812 /* The callback for an event on a link tag. */ | 863 /* The callback for an event on a link tag. */ |
813 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, char *url) { | 864 gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused) { |
814 GdkEventButton *event_button = (GdkEventButton *) event; | 865 GdkEventButton *event_button = (GdkEventButton *) event; |
815 if (GTK_IMHTML(imhtml)->editable) | 866 if (GTK_IMHTML(imhtml)->editable) |
816 return FALSE; | 867 return FALSE; |
817 if (event->type == GDK_BUTTON_RELEASE) { | 868 if (event->type == GDK_BUTTON_RELEASE) { |
818 if (event_button->button == 1) { | 869 if (event_button->button == 1) { |
819 GtkTextIter start, end; | 870 GtkTextIter start, end; |
820 /* we shouldn't open a URL if the user has selected something: */ | 871 /* we shouldn't open a URL if the user has selected something: */ |
821 gtk_text_buffer_get_selection_bounds( | 872 if (gtk_text_buffer_get_selection_bounds( |
822 gtk_text_iter_get_buffer(arg2), &start, &end); | 873 gtk_text_iter_get_buffer(arg2), &start, &end)) |
823 if(gtk_text_iter_get_offset(&start) != | |
824 gtk_text_iter_get_offset(&end)) | |
825 return FALSE; | 874 return FALSE; |
826 | 875 |
827 /* A link was clicked--we emit the "url_clicked" signal | 876 /* A link was clicked--we emit the "url_clicked" signal |
828 * with the URL as the argument */ | 877 * with the URL as the argument */ |
829 g_signal_emit(imhtml, signals[URL_CLICKED], 0, url); | 878 g_object_ref(G_OBJECT(tag)); |
879 g_signal_emit(imhtml, signals[URL_CLICKED], 0, g_object_get_data(G_OBJECT(tag), "link_url")); | |
880 g_object_unref(G_OBJECT(tag)); | |
830 return FALSE; | 881 return FALSE; |
831 } else if(event_button->button == 3) { | 882 } else if(event_button->button == 3) { |
832 GtkWidget *img, *item, *menu; | 883 GtkWidget *img, *item, *menu; |
833 struct url_data *tempdata = g_new(struct url_data, 1); | 884 struct url_data *tempdata = g_new(struct url_data, 1); |
834 tempdata->object = g_object_ref(imhtml); | 885 tempdata->object = g_object_ref(imhtml); |
835 tempdata->url = g_strdup(url); | 886 tempdata->url = g_strdup(g_object_get_data(G_OBJECT(tag), "link_url")); |
836 | 887 |
837 /* Don't want the tooltip around if user right-clicked on link */ | 888 /* Don't want the tooltip around if user right-clicked on link */ |
838 if (GTK_IMHTML(imhtml)->tip_window) { | 889 if (GTK_IMHTML(imhtml)->tip_window) { |
839 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); | 890 gtk_widget_destroy(GTK_IMHTML(imhtml)->tip_window); |
840 GTK_IMHTML(imhtml)->tip_window = NULL; | 891 GTK_IMHTML(imhtml)->tip_window = NULL; |
846 if (GTK_IMHTML(imhtml)->editable) | 897 if (GTK_IMHTML(imhtml)->editable) |
847 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); | 898 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->text_cursor); |
848 else | 899 else |
849 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); | 900 gdk_window_set_cursor(event_button->window, GTK_IMHTML(imhtml)->arrow_cursor); |
850 menu = gtk_menu_new(); | 901 menu = gtk_menu_new(); |
902 g_object_set_data_full(G_OBJECT(menu), "x-imhtml-url-data", tempdata, url_data_destroy); | |
851 | 903 |
852 /* buttons and such */ | 904 /* buttons and such */ |
853 | 905 |
854 if (!strncmp(url, "mailto:", 7)) | 906 if (!strncmp(tempdata->url, "mailto:", 7)) |
855 { | 907 { |
856 /* Copy E-Mail Address */ | 908 /* Copy E-Mail Address */ |
857 img = gtk_image_new_from_stock(GTK_STOCK_COPY, | 909 img = gtk_image_new_from_stock(GTK_STOCK_COPY, |
858 GTK_ICON_SIZE_MENU); | 910 GTK_ICON_SIZE_MENU); |
859 item = gtk_image_menu_item_new_with_mnemonic( | 911 item = gtk_image_menu_item_new_with_mnemonic( |
860 _("_Copy E-Mail Address")); | 912 _("_Copy E-Mail Address")); |
861 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | 913 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
862 g_signal_connect(G_OBJECT(item), "activate", | 914 g_signal_connect(G_OBJECT(item), "activate", |
863 G_CALLBACK(url_copy), url + 7); | 915 G_CALLBACK(url_copy), tempdata->url + 7); |
864 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | 916 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
865 } | 917 } |
866 else | 918 else |
867 { | 919 { |
868 /* Copy Link Location */ | 920 /* Copy Link Location */ |
870 GTK_ICON_SIZE_MENU); | 922 GTK_ICON_SIZE_MENU); |
871 item = gtk_image_menu_item_new_with_mnemonic( | 923 item = gtk_image_menu_item_new_with_mnemonic( |
872 _("_Copy Link Location")); | 924 _("_Copy Link Location")); |
873 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); | 925 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); |
874 g_signal_connect(G_OBJECT(item), "activate", | 926 g_signal_connect(G_OBJECT(item), "activate", |
875 G_CALLBACK(url_copy), url); | 927 G_CALLBACK(url_copy), tempdata->url); |
876 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); | 928 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); |
877 | 929 |
878 /* Open Link in Browser */ | 930 /* Open Link in Browser */ |
879 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, | 931 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, |
880 GTK_ICON_SIZE_MENU); | 932 GTK_ICON_SIZE_MENU); |
914 links = g_strsplit(sd->data, "\n", 0); | 966 links = g_strsplit(sd->data, "\n", 0); |
915 while((link = *links++) != NULL){ | 967 while((link = *links++) != NULL){ |
916 if(gaim_str_has_prefix(link, "http://") || | 968 if(gaim_str_has_prefix(link, "http://") || |
917 gaim_str_has_prefix(link, "https://") || | 969 gaim_str_has_prefix(link, "https://") || |
918 gaim_str_has_prefix(link, "ftp://")){ | 970 gaim_str_has_prefix(link, "ftp://")){ |
919 gtk_imhtml_insert_link(imhtml, link, link); | 971 gtk_imhtml_insert_link(imhtml, gtk_text_buffer_get_insert(imhtml->text_buffer), link, link); |
920 } else if (link=='\0') { | 972 } else if (link=='\0') { |
921 /* Ignore blank lines */ | 973 /* Ignore blank lines */ |
922 } else { | 974 } else { |
923 /* Special reasons, aka images being put in via other tag, etc. */ | 975 /* Special reasons, aka images being put in via other tag, etc. */ |
924 } | 976 } |
1406 } | 1458 } |
1407 } | 1459 } |
1408 return 0; | 1460 return 0; |
1409 } | 1461 } |
1410 | 1462 |
1411 GString* gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, | 1463 /* |
1412 const gchar *text, | 1464 <KingAnt> marv: The two IM image functions in oscar are gaim_odc_send_im and gaim_odc_incoming |
1413 GtkIMHtmlOptions options, | 1465 |
1414 GSList *images) | 1466 |
1415 { | 1467 [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :) |
1416 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 1468 [19:59] <KingAnt> marv: I think the image tag used by the core is something like <img id="#"/> |
1417 GtkTextIter insert; | 1469 [19:59] Ro0tSiEgE robert42 RobFlynn Robot101 ross22 roz |
1470 [20:00] <KingAnt> marv: Where the ID is the what is returned when you add the image to the imgstore using gaim_imgstore_add | |
1471 [20:00] <marv> Robot101: so how does the image get passed to serv_got_im() and serv_send_im()? just as the <img id="#" and then the prpl looks it up from the store? | |
1472 [20:00] <KingAnt> marv: Right | |
1473 [20:00] <marv> alright | |
1474 | |
1475 Here's my plan with IMImages. make gtk_imhtml_[append|insert]_text_with_images instead just | |
1476 gtkimhtml_[append|insert]_text (hrm maybe it should be called html instead of text), add a | |
1477 function for gaim to register for look up images, i.e. gtk_imhtml_set_get_img_fnc, so that | |
1478 images can be looked up like that, instead of passing a GSList of them. | |
1479 */ | |
1480 | |
1481 void gtk_imhtml_append_text_with_images (GtkIMHtml *imhtml, | |
1482 const gchar *text, | |
1483 GtkIMHtmlOptions options, | |
1484 GSList *unused) | |
1485 { | |
1486 GtkTextIter iter, ins, sel; | |
1487 GdkRectangle rect; | |
1488 int y, height, ins_offset = 0, sel_offset = 0; | |
1489 gboolean fixins = FALSE, fixsel = FALSE; | |
1490 | |
1491 g_return_if_fail (imhtml != NULL); | |
1492 g_return_if_fail (GTK_IS_IMHTML (imhtml)); | |
1493 g_return_if_fail (text != NULL); | |
1494 | |
1495 | |
1496 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
1497 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, gtk_text_buffer_get_insert(imhtml->text_buffer)); | |
1498 if (gtk_text_iter_equal(&iter, &ins) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
1499 fixins = TRUE; | |
1500 ins_offset = gtk_text_iter_get_offset(&ins); | |
1501 } | |
1502 | |
1503 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &sel, gtk_text_buffer_get_selection_bound(imhtml->text_buffer)); | |
1504 if (gtk_text_iter_equal(&iter, &sel) && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, NULL, NULL)) { | |
1505 fixsel = TRUE; | |
1506 sel_offset = gtk_text_iter_get_offset(&sel); | |
1507 } | |
1508 | |
1509 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1510 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
1511 | |
1512 | |
1513 if(((y + height) - (rect.y + rect.height)) > height | |
1514 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
1515 options |= GTK_IMHTML_NO_SCROLL; | |
1516 } | |
1517 | |
1518 gtk_imhtml_insert_html_at_iter(imhtml, text, options, &iter); | |
1519 | |
1520 if (fixins) { | |
1521 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ins, ins_offset); | |
1522 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_insert(imhtml->text_buffer), &ins); | |
1523 } | |
1524 | |
1525 if (fixsel) { | |
1526 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &sel, sel_offset); | |
1527 gtk_text_buffer_move_mark(imhtml->text_buffer, gtk_text_buffer_get_selection_bound(imhtml->text_buffer), &sel); | |
1528 } | |
1529 | |
1530 if (!(options & GTK_IMHTML_NO_SCROLL)) { | |
1531 /* If this seems backwards at first glance, well it's not. | |
1532 * It means scroll such that the mark is closest to the top, | |
1533 * and closest to the right as possible. Remember kids, you have | |
1534 * to scroll left to move a given spot closest to the right, | |
1535 * and scroll down to move a spot closest to the top. | |
1536 */ | |
1537 gtk_text_iter_set_line_offset(&iter, 0); | |
1538 gtk_text_buffer_move_mark(imhtml->text_buffer, imhtml->scrollpoint, &iter); | |
1539 gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(imhtml), imhtml->scrollpoint, | |
1540 0, TRUE, 1.0, 0.0); | |
1541 } | |
1542 } | |
1543 | |
1544 void gtk_imhtml_insert_html_at_iter(GtkIMHtml *imhtml, | |
1545 const gchar *text, | |
1546 GtkIMHtmlOptions options, | |
1547 GtkTextIter *iter) | |
1548 { | |
1418 GdkRectangle rect; | 1549 GdkRectangle rect; |
1419 gint pos = 0; | 1550 gint pos = 0; |
1420 GString *str = NULL; | |
1421 GtkTextIter iter; | |
1422 GtkTextMark *mark; | |
1423 gchar *ws; | 1551 gchar *ws; |
1424 gchar *tag; | 1552 gchar *tag; |
1425 gchar *url = NULL; | |
1426 gchar *bg = NULL; | 1553 gchar *bg = NULL; |
1427 gint len; | 1554 gint len; |
1428 gint tlen, smilelen, wpos=0; | 1555 gint tlen, smilelen, wpos=0; |
1429 gint type; | 1556 gint type; |
1430 const gchar *c; | 1557 const gchar *c; |
1441 pre = 0; | 1568 pre = 0; |
1442 | 1569 |
1443 GSList *fonts = NULL; | 1570 GSList *fonts = NULL; |
1444 GObject *object; | 1571 GObject *object; |
1445 GtkIMHtmlScalable *scalable = NULL; | 1572 GtkIMHtmlScalable *scalable = NULL; |
1446 int y, height; | 1573 |
1447 | 1574 g_return_if_fail (imhtml != NULL); |
1448 g_return_val_if_fail (imhtml != NULL, NULL); | 1575 g_return_if_fail (GTK_IS_IMHTML (imhtml)); |
1449 g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL); | 1576 g_return_if_fail (text != NULL); |
1450 g_return_val_if_fail (text != NULL, NULL); | |
1451 c = text; | 1577 c = text; |
1452 len = strlen(text); | 1578 len = strlen(text); |
1453 ws = g_malloc(len + 1); | 1579 ws = g_malloc(len + 1); |
1454 ws[0] = 0; | 1580 ws[0] = 0; |
1455 | |
1456 if (options & GTK_IMHTML_RETURN_LOG) | |
1457 str = g_string_new(""); | |
1458 | |
1459 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &insert, ins); | |
1460 | |
1461 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
1462 mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE); | |
1463 | |
1464 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1465 gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); | |
1466 | |
1467 #if GTK_CHECK_VERSION(2,2,0) | |
1468 gtk_imhtml_primary_clipboard_clear(NULL, imhtml); | |
1469 #endif | |
1470 gtk_text_buffer_move_mark (imhtml->text_buffer, | |
1471 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert"), | |
1472 &iter); | |
1473 | |
1474 if(((y + height) - (rect.y + rect.height)) > height | |
1475 && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ | |
1476 options |= GTK_IMHTML_NO_SCROLL; | |
1477 } | |
1478 | 1581 |
1479 while (pos < len) { | 1582 while (pos < len) { |
1480 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { | 1583 if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) { |
1481 c++; | 1584 c++; |
1482 pos++; | 1585 pos++; |
1484 switch (type) | 1587 switch (type) |
1485 { | 1588 { |
1486 case 1: /* B */ | 1589 case 1: /* B */ |
1487 case 2: /* BOLD */ | 1590 case 2: /* BOLD */ |
1488 case 54: /* STRONG */ | 1591 case 54: /* STRONG */ |
1489 if (url) | 1592 |
1490 gtk_imhtml_insert_link(imhtml, url, ws); | 1593 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1491 else | 1594 |
1492 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | 1595 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD)) |
1493 if (bold == 0) | |
1494 gtk_imhtml_toggle_bold(imhtml); | 1596 gtk_imhtml_toggle_bold(imhtml); |
1495 bold++; | 1597 bold++; |
1496 ws[0] = '\0'; wpos = 0; | 1598 ws[0] = '\0'; wpos = 0; |
1497 break; | 1599 break; |
1498 case 3: /* /B */ | 1600 case 3: /* /B */ |
1499 case 4: /* /BOLD */ | 1601 case 4: /* /BOLD */ |
1500 case 55: /* /STRONG */ | 1602 case 55: /* /STRONG */ |
1501 if (url) | 1603 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1502 gtk_imhtml_insert_link(imhtml, url, ws); | |
1503 else | |
1504 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1505 ws[0] = '\0'; wpos = 0; | 1604 ws[0] = '\0'; wpos = 0; |
1506 | 1605 |
1507 if (bold) | 1606 if (bold) |
1508 bold--; | 1607 bold--; |
1509 if (bold == 0) | 1608 if ((bold == 0) && (imhtml->format_functions & GTK_IMHTML_BOLD) && !imhtml->wbfo) |
1510 gtk_imhtml_toggle_bold(imhtml); | 1609 gtk_imhtml_toggle_bold(imhtml); |
1511 break; | 1610 break; |
1512 case 5: /* I */ | 1611 case 5: /* I */ |
1513 case 6: /* ITALIC */ | 1612 case 6: /* ITALIC */ |
1514 case 52: /* EM */ | 1613 case 52: /* EM */ |
1515 if (url) | 1614 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1516 gtk_imhtml_insert_link(imhtml, url, ws); | |
1517 else | |
1518 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1519 ws[0] = '\0'; wpos = 0; | 1615 ws[0] = '\0'; wpos = 0; |
1520 if (italics == 0) | 1616 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC)) |
1521 gtk_imhtml_toggle_italic(imhtml); | 1617 gtk_imhtml_toggle_italic(imhtml); |
1522 italics++; | 1618 italics++; |
1523 break; | 1619 break; |
1524 case 7: /* /I */ | 1620 case 7: /* /I */ |
1525 case 8: /* /ITALIC */ | 1621 case 8: /* /ITALIC */ |
1526 case 53: /* /EM */ | 1622 case 53: /* /EM */ |
1527 if (url) | 1623 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1528 gtk_imhtml_insert_link(imhtml, url, ws); | |
1529 else | |
1530 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1531 ws[0] = '\0'; wpos = 0; | 1624 ws[0] = '\0'; wpos = 0; |
1532 if (italics) | 1625 if (italics) |
1533 italics--; | 1626 italics--; |
1534 if (italics == 0) | 1627 if ((italics == 0) && (imhtml->format_functions & GTK_IMHTML_ITALIC) && !imhtml->wbfo) |
1535 gtk_imhtml_toggle_italic(imhtml); | 1628 gtk_imhtml_toggle_italic(imhtml); |
1536 break; | 1629 break; |
1537 case 9: /* U */ | 1630 case 9: /* U */ |
1538 case 10: /* UNDERLINE */ | 1631 case 10: /* UNDERLINE */ |
1539 if (url) | 1632 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1540 gtk_imhtml_insert_link(imhtml, url, ws); | |
1541 else | |
1542 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1543 ws[0] = '\0'; wpos = 0; | 1633 ws[0] = '\0'; wpos = 0; |
1544 if (underline == 0) | 1634 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE)) |
1545 gtk_imhtml_toggle_underline(imhtml); | 1635 gtk_imhtml_toggle_underline(imhtml); |
1546 underline++; | 1636 underline++; |
1547 break; | 1637 break; |
1548 case 11: /* /U */ | 1638 case 11: /* /U */ |
1549 case 12: /* /UNDERLINE */ | 1639 case 12: /* /UNDERLINE */ |
1550 if (url) | 1640 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1551 gtk_imhtml_insert_link(imhtml, url, ws); | |
1552 else | |
1553 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1554 ws[0] = '\0'; wpos = 0; | 1641 ws[0] = '\0'; wpos = 0; |
1555 if (underline) | 1642 if (underline) |
1556 underline--; | 1643 underline--; |
1557 if (underline == 0) | 1644 if ((underline == 0) && (imhtml->format_functions & GTK_IMHTML_UNDERLINE) && !imhtml->wbfo) |
1558 gtk_imhtml_toggle_underline(imhtml); | 1645 gtk_imhtml_toggle_underline(imhtml); |
1559 break; | 1646 break; |
1560 case 13: /* S */ | 1647 case 13: /* S */ |
1561 case 14: /* STRIKE */ | 1648 case 14: /* STRIKE */ |
1562 /* NEW_BIT (NEW_TEXT_BIT); */ | 1649 /* FIXME: reimplement this */ |
1563 strike++; | 1650 strike++; |
1564 break; | 1651 break; |
1565 case 15: /* /S */ | 1652 case 15: /* /S */ |
1566 case 16: /* /STRIKE */ | 1653 case 16: /* /STRIKE */ |
1567 /* NEW_BIT (NEW_TEXT_BIT); */ | 1654 /* FIXME: reimplement this */ |
1568 if (strike) | 1655 if (strike) |
1569 strike--; | 1656 strike--; |
1570 break; | 1657 break; |
1571 case 17: /* SUB */ | 1658 case 17: /* SUB */ |
1572 /* NEW_BIT (NEW_TEXT_BIT); */ | 1659 /* FIXME: reimpliment this */ |
1573 sub++; | 1660 sub++; |
1574 break; | 1661 break; |
1575 case 18: /* /SUB */ | 1662 case 18: /* /SUB */ |
1576 /* NEW_BIT (NEW_TEXT_BIT); */ | 1663 /* FIXME: reimpliment this */ |
1577 if (sub) | 1664 if (sub) |
1578 sub--; | 1665 sub--; |
1579 break; | 1666 break; |
1580 case 19: /* SUP */ | 1667 case 19: /* SUP */ |
1581 /* NEW_BIT (NEW_TEXT_BIT); */ | 1668 /* FIXME: reimplement this */ |
1582 sup++; | 1669 sup++; |
1583 break; | 1670 break; |
1584 case 20: /* /SUP */ | 1671 case 20: /* /SUP */ |
1585 /* NEW_BIT (NEW_TEXT_BIT); */ | 1672 /* FIXME: reimplement this */ |
1586 if (sup) | 1673 if (sup) |
1587 sup--; | 1674 sup--; |
1588 break; | 1675 break; |
1589 case 21: /* PRE */ | 1676 case 21: /* PRE */ |
1590 /* NEW_BIT (NEW_TEXT_BIT); */ | 1677 /* FIXME: reimplement this */ |
1591 pre++; | 1678 pre++; |
1592 break; | 1679 break; |
1593 case 22: /* /PRE */ | 1680 case 22: /* /PRE */ |
1594 /* NEW_BIT (NEW_TEXT_BIT); */ | 1681 /* FIXME: reimplement this */ |
1595 if (pre) | 1682 if (pre) |
1596 pre--; | 1683 pre--; |
1597 break; | 1684 break; |
1598 case 23: /* TITLE */ | 1685 case 23: /* TITLE */ |
1599 /* NEW_BIT (NEW_TEXT_BIT); */ | 1686 /* FIXME: what was this supposed to do anyway? */ |
1600 title++; | 1687 title++; |
1601 break; | 1688 break; |
1602 case 24: /* /TITLE */ | 1689 case 24: /* /TITLE */ |
1690 /* FIXME: make this undo whatever 23 was supposed to do */ | |
1603 if (title) { | 1691 if (title) { |
1604 if (options & GTK_IMHTML_NO_TITLE) { | 1692 if (options & GTK_IMHTML_NO_TITLE) { |
1605 wpos = 0; | 1693 wpos = 0; |
1606 ws [wpos] = '\0'; | 1694 ws [wpos] = '\0'; |
1607 } | 1695 } |
1611 case 25: /* BR */ | 1699 case 25: /* BR */ |
1612 case 58: /* BR/ */ | 1700 case 58: /* BR/ */ |
1613 case 61: /* BR (opt) */ | 1701 case 61: /* BR (opt) */ |
1614 ws[wpos] = '\n'; | 1702 ws[wpos] = '\n'; |
1615 wpos++; | 1703 wpos++; |
1616 /* NEW_BIT (NEW_TEXT_BIT); */ | |
1617 break; | 1704 break; |
1618 case 26: /* HR */ | 1705 case 26: /* HR */ |
1619 case 42: /* HR (opt) */ | 1706 case 42: /* HR (opt) */ |
1620 ws[wpos++] = '\n'; | 1707 ws[wpos++] = '\n'; |
1621 if (url) | 1708 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1622 gtk_imhtml_insert_link(imhtml, url, ws); | 1709 |
1623 else | |
1624 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1625 scalable = gtk_imhtml_hr_new(); | 1710 scalable = gtk_imhtml_hr_new(); |
1626 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | 1711 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); |
1627 scalable->add_to(scalable, imhtml, &iter); | 1712 scalable->add_to(scalable, imhtml, iter); |
1628 scalable->scale(scalable, rect.width, rect.height); | 1713 scalable->scale(scalable, rect.width, rect.height); |
1629 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | 1714 imhtml->scalables = g_list_append(imhtml->scalables, scalable); |
1630 ws[0] = '\0'; wpos = 0; | 1715 ws[0] = '\0'; wpos = 0; |
1631 ws[wpos++] = '\n'; | 1716 ws[wpos++] = '\n'; |
1632 | 1717 |
1633 break; | 1718 break; |
1634 case 27: /* /FONT */ | 1719 case 27: /* /FONT */ |
1635 if (fonts) { | 1720 if (fonts && !imhtml->wbfo) { |
1636 GtkIMHtmlFontDetail *font = fonts->data; | 1721 GtkIMHtmlFontDetail *font = fonts->data; |
1637 if (url) | 1722 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1638 gtk_imhtml_insert_link(imhtml, url, ws); | |
1639 else | |
1640 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1641 ws[0] = '\0'; wpos = 0; | 1723 ws[0] = '\0'; wpos = 0; |
1642 /* NEW_BIT (NEW_TEXT_BIT); */ | 1724 /* NEW_BIT (NEW_TEXT_BIT); */ |
1643 | 1725 |
1644 if (font->face) { | 1726 if (font->face) { |
1645 gtk_imhtml_toggle_fontface(imhtml, NULL); | 1727 gtk_imhtml_toggle_fontface(imhtml, NULL); |
1646 g_free (font->face); | 1728 g_free (font->face); |
1647 } | 1729 } |
1648 if (font->fore) { | 1730 if (font->fore) { |
1661 gtk_imhtml_font_set_size(imhtml, 3); | 1743 gtk_imhtml_font_set_size(imhtml, 3); |
1662 | 1744 |
1663 fonts = fonts->next; | 1745 fonts = fonts->next; |
1664 if (fonts) { | 1746 if (fonts) { |
1665 GtkIMHtmlFontDetail *font = fonts->data; | 1747 GtkIMHtmlFontDetail *font = fonts->data; |
1666 | 1748 |
1667 if (font->face) | 1749 if (font->face) |
1668 gtk_imhtml_toggle_fontface(imhtml, font->face); | 1750 gtk_imhtml_toggle_fontface(imhtml, font->face); |
1669 if (font->fore) | 1751 if (font->fore) |
1670 gtk_imhtml_toggle_forecolor(imhtml, font->fore); | 1752 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
1671 if (font->back) | 1753 if (font->back) |
1672 gtk_imhtml_toggle_backcolor(imhtml, font->back); | 1754 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
1673 if (font->size != 3) | 1755 if (font->size != 3) |
1674 gtk_imhtml_font_set_size(imhtml, font->size); | 1756 gtk_imhtml_font_set_size(imhtml, font->size); |
1675 } | 1757 } |
1676 } | 1758 } |
1677 break; | 1759 break; |
1678 case 28: /* /A */ | 1760 case 28: /* /A */ |
1679 if (url) { | 1761 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1680 gtk_imhtml_insert_link(imhtml, url, ws); | 1762 gtk_imhtml_toggle_link(imhtml, NULL); |
1681 g_free(url); | 1763 ws[0] = '\0'; wpos = 0; |
1682 ws[0] = '\0'; wpos = 0; | |
1683 url = NULL; | |
1684 ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
1685 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
1686 } | |
1687 break; | 1764 break; |
1688 | 1765 |
1689 case 29: /* P */ | 1766 case 29: /* P */ |
1690 case 30: /* /P */ | 1767 case 30: /* /P */ |
1691 case 31: /* H3 */ | 1768 case 31: /* H3 */ |
1710 size = gtk_imhtml_get_html_opt (tag, "SIZE="); | 1787 size = gtk_imhtml_get_html_opt (tag, "SIZE="); |
1711 sml = gtk_imhtml_get_html_opt (tag, "SML="); | 1788 sml = gtk_imhtml_get_html_opt (tag, "SML="); |
1712 if (!(color || back || face || size || sml)) | 1789 if (!(color || back || face || size || sml)) |
1713 break; | 1790 break; |
1714 | 1791 |
1715 if (url) | 1792 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1716 gtk_imhtml_insert_link(imhtml, url, ws); | |
1717 else | |
1718 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1719 ws[0] = '\0'; wpos = 0; | 1793 ws[0] = '\0'; wpos = 0; |
1720 | 1794 |
1721 font = g_new0 (GtkIMHtmlFontDetail, 1); | 1795 font = g_new0 (GtkIMHtmlFontDetail, 1); |
1722 if (fonts) | 1796 if (fonts) |
1723 oldfont = fonts->data; | 1797 oldfont = fonts->data; |
1724 | 1798 |
1725 if (color && !(options & GTK_IMHTML_NO_COLOURS)) { | 1799 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) { |
1726 font->fore = color; | 1800 font->fore = color; |
1727 gtk_imhtml_toggle_forecolor(imhtml, font->fore); | 1801 gtk_imhtml_toggle_forecolor(imhtml, font->fore); |
1728 } | 1802 } |
1729 //else if (oldfont && oldfont->fore) | 1803 //else if (oldfont && oldfont->fore) |
1730 // font->fore = g_strdup(oldfont->fore); | 1804 // font->fore = g_strdup(oldfont->fore); |
1731 | 1805 |
1732 if (back && !(options & GTK_IMHTML_NO_COLOURS)) { | 1806 if (back && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
1733 font->back = back; | 1807 font->back = back; |
1734 gtk_imhtml_toggle_backcolor(imhtml, font->back); | 1808 gtk_imhtml_toggle_backcolor(imhtml, font->back); |
1735 } | 1809 } |
1736 //else if (oldfont && oldfont->back) | 1810 //else if (oldfont && oldfont->back) |
1737 // font->back = g_strdup(oldfont->back); | 1811 // font->back = g_strdup(oldfont->back); |
1738 | 1812 |
1739 if (face && !(options & GTK_IMHTML_NO_FONTS)) { | 1813 if (face && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) { |
1740 font->face = face; | 1814 font->face = face; |
1741 gtk_imhtml_toggle_fontface(imhtml, font->face); | 1815 gtk_imhtml_toggle_fontface(imhtml, font->face); |
1742 } | 1816 } |
1743 //else if (oldfont && oldfont->face) | 1817 //else if (oldfont && oldfont->face) |
1744 // font->face = g_strdup(oldfont->face); | 1818 // font->face = g_strdup(oldfont->face); |
1746 if (sml) | 1820 if (sml) |
1747 font->sml = sml; | 1821 font->sml = sml; |
1748 else if (oldfont && oldfont->sml) | 1822 else if (oldfont && oldfont->sml) |
1749 font->sml = g_strdup(oldfont->sml); | 1823 font->sml = g_strdup(oldfont->sml); |
1750 | 1824 |
1751 if (size && !(options & GTK_IMHTML_NO_SIZES)) { | 1825 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_GROW|GTK_IMHTML_SHRINK))) { |
1752 if (*size == '+') { | 1826 if (*size == '+') { |
1753 sscanf (size + 1, "%hd", &font->size); | 1827 sscanf (size + 1, "%hd", &font->size); |
1754 font->size += 3; | 1828 font->size += 3; |
1755 } else if (*size == '-') { | 1829 } else if (*size == '-') { |
1756 sscanf (size + 1, "%hd", &font->size); | 1830 sscanf (size + 1, "%hd", &font->size); |
1770 } | 1844 } |
1771 break; | 1845 break; |
1772 case 44: /* BODY (opt) */ | 1846 case 44: /* BODY (opt) */ |
1773 if (!(options & GTK_IMHTML_NO_COLOURS)) { | 1847 if (!(options & GTK_IMHTML_NO_COLOURS)) { |
1774 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); | 1848 char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR="); |
1775 if (bgcolor) { | 1849 if (bgcolor && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) { |
1776 if (url) | 1850 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1777 gtk_imhtml_insert_link(imhtml, url, ws); | |
1778 else | |
1779 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1780 ws[0] = '\0'; wpos = 0; | 1851 ws[0] = '\0'; wpos = 0; |
1781 /* NEW_BIT(NEW_TEXT_BIT); */ | 1852 /* NEW_BIT(NEW_TEXT_BIT); */ |
1782 if (bg) | 1853 if (bg) |
1783 g_free(bg); | 1854 g_free(bg); |
1784 bg = bgcolor; | 1855 bg = bgcolor; |
1787 } | 1858 } |
1788 break; | 1859 break; |
1789 case 45: /* A (opt) */ | 1860 case 45: /* A (opt) */ |
1790 { | 1861 { |
1791 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); | 1862 gchar *href = gtk_imhtml_get_html_opt (tag, "HREF="); |
1792 if (href) { | 1863 if (href && (imhtml->format_functions & GTK_IMHTML_LINK)) { |
1793 if (url) { | 1864 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1794 gtk_imhtml_insert_link(imhtml, url, ws); | |
1795 g_free(url); | |
1796 } else | |
1797 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1798 ws[0] = '\0'; wpos = 0; | 1865 ws[0] = '\0'; wpos = 0; |
1799 url = href; | 1866 gtk_imhtml_toggle_link(imhtml, href); |
1800 } | 1867 } |
1801 } | 1868 } |
1802 break; | 1869 break; |
1803 case 46: /* IMG (opt) */ | 1870 case 46: /* IMG (opt) */ |
1804 case 59: /* IMG */ | 1871 case 59: /* IMG */ |
1805 { | 1872 { |
1873 #if 0 | |
1874 /* disabling this for now, it's easy to add it back... */ | |
1806 GdkPixbuf *img = NULL; | 1875 GdkPixbuf *img = NULL; |
1807 const gchar *filename = NULL; | 1876 const gchar *filename = NULL; |
1877 | |
1878 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) | |
1879 break; | |
1808 | 1880 |
1809 if (images && images->data) { | 1881 if (images && images->data) { |
1810 img = images->data; | 1882 img = images->data; |
1811 images = images->next; | 1883 images = images->next; |
1812 filename = g_object_get_data(G_OBJECT(img), "filename"); | 1884 filename = g_object_get_data(G_OBJECT(img), "filename"); |
1817 "gtkimhtml-missing-image"); | 1889 "gtkimhtml-missing-image"); |
1818 } | 1890 } |
1819 | 1891 |
1820 scalable = gtk_imhtml_image_new(img, filename); | 1892 scalable = gtk_imhtml_image_new(img, filename); |
1821 /* NEW_BIT(NEW_SCALABLE_BIT); */ | 1893 /* NEW_BIT(NEW_SCALABLE_BIT); */ |
1894 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
1895 scalable->add_to(scalable, imhtml, iter); | |
1896 scalable->scale(scalable, rect.width, rect.height); | |
1897 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | |
1898 | |
1822 g_object_unref(G_OBJECT(img)); | 1899 g_object_unref(G_OBJECT(img)); |
1900 #endif | |
1823 } | 1901 } |
1824 case 47: /* P (opt) */ | 1902 case 47: /* P (opt) */ |
1825 case 48: /* H3 (opt) */ | 1903 case 48: /* H3 (opt) */ |
1826 case 49: /* HTML (opt) */ | 1904 case 49: /* HTML (opt) */ |
1827 case 50: /* CITE */ | 1905 case 50: /* CITE */ |
1848 if (!(color || family || size)) { | 1926 if (!(color || family || size)) { |
1849 g_free(style); | 1927 g_free(style); |
1850 break; | 1928 break; |
1851 } | 1929 } |
1852 | 1930 |
1853 if (url) | 1931 |
1854 gtk_imhtml_insert_link(imhtml, url, ws); | 1932 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1855 else | |
1856 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1857 ws[0] = '\0'; wpos = 0; | 1933 ws[0] = '\0'; wpos = 0; |
1858 /* NEW_BIT (NEW_TEXT_BIT); */ | 1934 /* NEW_BIT (NEW_TEXT_BIT); */ |
1859 | 1935 |
1860 font = g_new0 (GtkIMHtmlFontDetail, 1); | 1936 font = g_new0 (GtkIMHtmlFontDetail, 1); |
1861 if (fonts) | 1937 if (fonts) |
1862 oldfont = fonts->data; | 1938 oldfont = fonts->data; |
1863 | 1939 |
1864 if (color && !(options & GTK_IMHTML_NO_COLOURS)) | 1940 if (color && !(options & GTK_IMHTML_NO_COLOURS) && (imhtml->format_functions & GTK_IMHTML_FORECOLOR)) |
1865 font->fore = color; | 1941 font->fore = color; |
1866 else if (oldfont && oldfont->fore) | 1942 else if (oldfont && oldfont->fore) |
1867 font->fore = g_strdup(oldfont->fore); | 1943 font->fore = g_strdup(oldfont->fore); |
1868 | 1944 |
1869 if (oldfont && oldfont->back) | 1945 if (oldfont && oldfont->back && (imhtml->format_functions & GTK_IMHTML_BACKCOLOR)) |
1870 font->back = g_strdup(oldfont->back); | 1946 font->back = g_strdup(oldfont->back); |
1871 | 1947 |
1872 if (family && !(options & GTK_IMHTML_NO_FONTS)) | 1948 if (family && !(options & GTK_IMHTML_NO_FONTS) && (imhtml->format_functions & GTK_IMHTML_FACE)) |
1873 font->face = family; | 1949 font->face = family; |
1874 else if (oldfont && oldfont->face) | 1950 else if (oldfont && oldfont->face) |
1875 font->face = g_strdup(oldfont->face); | 1951 font->face = g_strdup(oldfont->face); |
1876 if (font->face && (atoi(font->face) > 100)) { | 1952 if (font->face && (atoi(font->face) > 100)) { |
1953 /* WTF is this? */ | |
1877 g_free(font->face); | 1954 g_free(font->face); |
1878 font->face = g_strdup("100"); | 1955 font->face = g_strdup("100"); |
1879 } | 1956 } |
1880 | 1957 |
1881 if (oldfont && oldfont->sml) | 1958 if (oldfont && oldfont->sml) |
1882 font->sml = g_strdup(oldfont->sml); | 1959 font->sml = g_strdup(oldfont->sml); |
1883 | 1960 |
1884 if (size && !(options & GTK_IMHTML_NO_SIZES)) { | 1961 if (size && !(options & GTK_IMHTML_NO_SIZES) && (imhtml->format_functions & (GTK_IMHTML_SHRINK|GTK_IMHTML_GROW))) { |
1885 if (g_ascii_strcasecmp(size, "smaller") == 0) | 1962 if (g_ascii_strcasecmp(size, "smaller") == 0) |
1886 { | 1963 { |
1887 font->size = 2; | 1964 font->size = 2; |
1888 } | 1965 } |
1889 else if (g_ascii_strcasecmp(size, "larger") == 0) | 1966 else if (g_ascii_strcasecmp(size, "larger") == 0) |
1902 fonts = g_slist_prepend (fonts, font); | 1979 fonts = g_slist_prepend (fonts, font); |
1903 } | 1980 } |
1904 break; | 1981 break; |
1905 case 57: /* /SPAN */ | 1982 case 57: /* /SPAN */ |
1906 /* Inline CSS Support - Douglas Thrift */ | 1983 /* Inline CSS Support - Douglas Thrift */ |
1907 if (fonts) { | 1984 if (fonts && !imhtml->wbfo) { |
1908 GtkIMHtmlFontDetail *font = fonts->data; | 1985 GtkIMHtmlFontDetail *font = fonts->data; |
1909 if (url) | 1986 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1910 gtk_imhtml_insert_link(imhtml, url, ws); | |
1911 else | |
1912 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1913 ws[0] = '\0'; wpos = 0; | 1987 ws[0] = '\0'; wpos = 0; |
1914 /* NEW_BIT (NEW_TEXT_BIT); */ | 1988 /* NEW_BIT (NEW_TEXT_BIT); */ |
1915 fonts = g_slist_remove (fonts, font); | 1989 fonts = g_slist_remove (fonts, font); |
1916 if (font->face) | 1990 if (font->face) |
1917 g_free (font->face); | 1991 g_free (font->face); |
1927 case 60: /* SPAN */ | 2001 case 60: /* SPAN */ |
1928 break; | 2002 break; |
1929 case 62: /* comment */ | 2003 case 62: /* comment */ |
1930 /* NEW_BIT (NEW_TEXT_BIT); */ | 2004 /* NEW_BIT (NEW_TEXT_BIT); */ |
1931 ws[wpos] = '\0'; | 2005 ws[wpos] = '\0'; |
1932 if (url) | 2006 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1933 gtk_imhtml_insert_link(imhtml, url, ws); | 2007 |
1934 else | |
1935 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1936 if (imhtml->show_comments) | 2008 if (imhtml->show_comments) |
1937 wpos = g_snprintf (ws, len, "%s", tag); | 2009 wpos = g_snprintf (ws, len, "%s", tag); |
1938 /* NEW_BIT (NEW_COMMENT_BIT); */ | 2010 /* NEW_BIT (NEW_COMMENT_BIT); */ |
1939 break; | 2011 break; |
1940 default: | 2012 default: |
1950 gchar *sml = NULL; | 2022 gchar *sml = NULL; |
1951 if (fonts) { | 2023 if (fonts) { |
1952 fd = fonts->data; | 2024 fd = fonts->data; |
1953 sml = fd->sml; | 2025 sml = fd->sml; |
1954 } | 2026 } |
1955 if (url) | 2027 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1956 gtk_imhtml_insert_link(imhtml, url, ws); | |
1957 else { | |
1958 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1959 } | |
1960 wpos = g_snprintf (ws, smilelen + 1, "%s", c); | 2028 wpos = g_snprintf (ws, smilelen + 1, "%s", c); |
1961 | 2029 |
1962 gtk_imhtml_insert_smiley(imhtml, sml, ws); | 2030 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, ws, iter); |
1963 | |
1964 ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
1965 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
1966 | 2031 |
1967 c += smilelen; | 2032 c += smilelen; |
1968 pos += smilelen; | 2033 pos += smilelen; |
1969 wpos = 0; | 2034 wpos = 0; |
1970 ws[0] = 0; | 2035 ws[0] = 0; |
1976 pos += tlen; | 2041 pos += tlen; |
1977 } else if (*c == '\n') { | 2042 } else if (*c == '\n') { |
1978 if (!(options & GTK_IMHTML_NO_NEWLINE)) { | 2043 if (!(options & GTK_IMHTML_NO_NEWLINE)) { |
1979 ws[wpos] = '\n'; | 2044 ws[wpos] = '\n'; |
1980 wpos++; | 2045 wpos++; |
1981 if (url) | 2046 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
1982 gtk_imhtml_insert_link(imhtml, url, ws); | |
1983 else | |
1984 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
1985 ws[0] = '\0'; | 2047 ws[0] = '\0'; |
1986 wpos = 0; | 2048 wpos = 0; |
1987 /* NEW_BIT (NEW_TEXT_BIT); */ | 2049 /* NEW_BIT (NEW_TEXT_BIT); */ |
1988 } | 2050 } |
1989 c++; | 2051 c++; |
1990 pos++; | 2052 pos++; |
1991 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ | 2053 } else if ((len_protocol = gtk_imhtml_is_protocol(c)) > 0){ |
1992 while(len_protocol--){ | 2054 while(len_protocol--){ |
1993 /* Skip the next len_protocol characters, but make sure they're | 2055 /* Skip the next len_protocol characters, but make sure they're |
1994 copied into the ws array. | 2056 copied into the ws array. |
1995 */ | 2057 */ |
1996 ws [wpos++] = *c++; | 2058 ws [wpos++] = *c++; |
1997 pos++; | 2059 pos++; |
1998 } | 2060 } |
2001 pos++; | 2063 pos++; |
2002 } else { | 2064 } else { |
2003 break; | 2065 break; |
2004 } | 2066 } |
2005 } | 2067 } |
2006 if (url) | 2068 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2007 gtk_imhtml_insert_link(imhtml, url, ws); | |
2008 else | |
2009 gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, wpos); | |
2010 ws[0] = '\0'; wpos = 0; | 2069 ws[0] = '\0'; wpos = 0; |
2011 | 2070 |
2012 /* NEW_BIT(NEW_TEXT_BIT); */ | 2071 /* NEW_BIT(NEW_TEXT_BIT); */ |
2013 if (url) { | |
2014 g_free (url); | |
2015 if (str) | |
2016 str = g_string_append (str, "</A>"); | |
2017 } | |
2018 | 2072 |
2019 while (fonts) { | 2073 while (fonts) { |
2020 GtkIMHtmlFontDetail *font = fonts->data; | 2074 GtkIMHtmlFontDetail *font = fonts->data; |
2021 fonts = g_slist_remove (fonts, font); | 2075 fonts = g_slist_remove (fonts, font); |
2022 if (font->face) | 2076 if (font->face) |
2026 if (font->back) | 2080 if (font->back) |
2027 g_free (font->back); | 2081 g_free (font->back); |
2028 if (font->sml) | 2082 if (font->sml) |
2029 g_free (font->sml); | 2083 g_free (font->sml); |
2030 g_free (font); | 2084 g_free (font); |
2031 if (str) | 2085 //if (str) |
2032 str = g_string_append (str, "</FONT>"); | 2086 // str = g_string_append (str, "</FONT>"); |
2033 } | 2087 } |
2034 | 2088 #if 0 |
2035 if (str) { | 2089 if (str) { |
2036 while (bold) { | 2090 while (bold) { |
2037 str = g_string_append (str, "</B>"); | 2091 // str = g_string_append (str, "</B>"); |
2038 bold--; | 2092 bold--; |
2039 } | 2093 } |
2040 while (italics) { | 2094 while (italics) { |
2041 str = g_string_append (str, "</I>"); | 2095 // str = g_string_append (str, "</I>"); |
2042 italics--; | 2096 italics--; |
2043 } | 2097 } |
2044 while (underline) { | 2098 while (underline) { |
2045 str = g_string_append (str, "</U>"); | 2099 //str = g_string_append (str, "</U>"); |
2046 underline--; | 2100 underline--; |
2047 } | 2101 } |
2048 while (strike) { | 2102 while (strike) { |
2049 str = g_string_append (str, "</S>"); | 2103 //str = g_string_append (str, "</S>"); |
2050 strike--; | 2104 strike--; |
2051 } | 2105 } |
2052 while (sub) { | 2106 while (sub) { |
2053 str = g_string_append (str, "</SUB>"); | 2107 //str = g_string_append (str, "</SUB>"); |
2054 sub--; | 2108 sub--; |
2055 } | 2109 } |
2056 while (sup) { | 2110 while (sup) { |
2057 str = g_string_append (str, "</SUP>"); | 2111 //str = g_string_append (str, "</SUP>"); |
2058 sup--; | 2112 sup--; |
2059 } | 2113 } |
2060 while (title) { | 2114 while (title) { |
2061 str = g_string_append (str, "</TITLE>"); | 2115 //str = g_string_append (str, "</TITLE>"); |
2062 title--; | 2116 title--; |
2063 } | 2117 } |
2064 while (pre) { | 2118 while (pre) { |
2065 str = g_string_append (str, "</PRE>"); | 2119 //str = g_string_append (str, "</PRE>"); |
2066 pre--; | 2120 pre--; |
2067 } | 2121 } |
2068 } | 2122 } |
2123 #endif | |
2069 g_free (ws); | 2124 g_free (ws); |
2070 if(bg) | 2125 if(bg) |
2071 g_free(bg); | 2126 g_free(bg); |
2072 /* this shouldn't be necessary if we want to be able to continue | 2127 |
2073 * using the format if it was unclosed. But seeing as removing this | 2128 if (!imhtml->wbfo) |
2074 * line does not help the ctrl-up/down from enabling open tags, I'm | 2129 gtk_imhtml_close_tags(imhtml); |
2075 * leaving it up to sean, or unless I find some time to look into it | |
2076 * more -Gary */ | |
2077 gtk_imhtml_close_tags(imhtml); | |
2078 if (!(options & GTK_IMHTML_NO_SCROLL)) | |
2079 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark, | |
2080 0, TRUE, 0.0, 1.0); | |
2081 gtk_text_buffer_delete_mark (imhtml->text_buffer, mark); | |
2082 gtk_text_buffer_move_mark (imhtml->text_buffer, | |
2083 gtk_text_buffer_get_mark (imhtml->text_buffer, "insert"), | |
2084 &iter); | |
2085 | 2130 |
2086 object = g_object_ref(G_OBJECT(imhtml)); | 2131 object = g_object_ref(G_OBJECT(imhtml)); |
2087 g_signal_emit(object, signals[UPDATE_FORMAT], 0); | 2132 g_signal_emit(object, signals[UPDATE_FORMAT], 0); |
2088 g_object_unref(object); | 2133 g_object_unref(object); |
2089 | 2134 |
2090 return str; | |
2091 } | 2135 } |
2092 | 2136 |
2093 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) | 2137 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml) |
2094 { | 2138 { |
2095 g_hash_table_destroy(imhtml->smiley_data); | 2139 g_hash_table_destroy(imhtml->smiley_data); |
2137 | 2181 |
2138 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | 2182 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
2139 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | 2183 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); |
2140 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); | 2184 gtk_text_buffer_delete(imhtml->text_buffer, &start, &end); |
2141 | 2185 |
2142 for(del = imhtml->format_spans; del; del = del->next) { | |
2143 GtkIMHtmlFormatSpan *span = del->data; | |
2144 if (span->start_tag) | |
2145 g_free(span->start_tag); | |
2146 if (span->end_tag) | |
2147 g_free(span->end_tag); | |
2148 g_free(span); | |
2149 } | |
2150 g_list_free(imhtml->format_spans); | |
2151 imhtml->format_spans = NULL; | |
2152 | |
2153 for(del = imhtml->scalables; del; del = del->next) { | 2186 for(del = imhtml->scalables; del; del = del->next) { |
2154 GtkIMHtmlScalable *scale = del->data; | 2187 GtkIMHtmlScalable *scale = del->data; |
2155 scale->free(scale); | 2188 scale->free(scale); |
2156 } | 2189 } |
2157 g_list_free(imhtml->scalables); | 2190 g_list_free(imhtml->scalables); |
2158 imhtml->scalables = NULL; | 2191 imhtml->scalables = NULL; |
2159 | 2192 |
2160 imhtml->edit.bold = NULL; | 2193 imhtml->edit.bold = FALSE; |
2161 imhtml->edit.italic = NULL; | 2194 imhtml->edit.italic = FALSE; |
2162 imhtml->edit.underline = NULL; | 2195 imhtml->edit.underline = FALSE; |
2196 | |
2197 if (imhtml->edit.fontface) | |
2198 g_free(imhtml->edit.fontface); | |
2163 imhtml->edit.fontface = NULL; | 2199 imhtml->edit.fontface = NULL; |
2200 | |
2201 if (imhtml->edit.forecolor) | |
2202 g_free(imhtml->edit.forecolor); | |
2164 imhtml->edit.forecolor = NULL; | 2203 imhtml->edit.forecolor = NULL; |
2204 | |
2205 if (imhtml->edit.backcolor) | |
2206 g_free(imhtml->edit.backcolor); | |
2165 imhtml->edit.backcolor = NULL; | 2207 imhtml->edit.backcolor = NULL; |
2166 imhtml->edit.sizespan = NULL; | 2208 |
2167 imhtml->edit.fontsize = 3; | 2209 imhtml->edit.fontsize = 0; |
2168 | 2210 |
2169 g_signal_emit(object, signals[CLEAR_FORMAT], 0); | 2211 g_signal_emit(object, signals[CLEAR_FORMAT], 0); |
2170 g_object_unref(object); | 2212 g_object_unref(object); |
2171 } | 2213 } |
2172 | 2214 |
2488 if (imhtml->search_string) | 2530 if (imhtml->search_string) |
2489 g_free(imhtml->search_string); | 2531 g_free(imhtml->search_string); |
2490 imhtml->search_string = NULL; | 2532 imhtml->search_string = NULL; |
2491 } | 2533 } |
2492 | 2534 |
2535 static GtkTextTag *find_font_forecolor_tag(GtkIMHtml *imhtml, gchar *color) | |
2536 { | |
2537 gchar str[18]; | |
2538 GtkTextTag *tag; | |
2539 | |
2540 g_snprintf(str, sizeof(str), "FORECOLOR %s", color); | |
2541 | |
2542 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2543 if (!tag) | |
2544 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", color, NULL); | |
2545 | |
2546 return tag; | |
2547 } | |
2548 | |
2549 static GtkTextTag *find_font_backcolor_tag(GtkIMHtml *imhtml, gchar *color) | |
2550 { | |
2551 gchar str[18]; | |
2552 GtkTextTag *tag; | |
2553 | |
2554 g_snprintf(str, sizeof(str), "BACKCOLOR %s", color); | |
2555 | |
2556 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2557 if (!tag) | |
2558 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "background", color, NULL); | |
2559 | |
2560 return tag; | |
2561 } | |
2562 | |
2563 static GtkTextTag *find_font_face_tag(GtkIMHtml *imhtml, gchar *face) | |
2564 { | |
2565 gchar str[256]; | |
2566 GtkTextTag *tag; | |
2567 | |
2568 g_snprintf(str, sizeof(str), "FONT FACE %s", face); | |
2569 str[255] = '\0'; | |
2570 | |
2571 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2572 if (!tag) | |
2573 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "family", face, NULL); | |
2574 | |
2575 return tag; | |
2576 } | |
2577 | |
2578 static GtkTextTag *find_font_size_tag(GtkIMHtml *imhtml, int size) | |
2579 { | |
2580 gchar str[24]; | |
2581 GtkTextTag *tag; | |
2582 | |
2583 g_snprintf(str, sizeof(str), "FONT SIZE %d", size); | |
2584 str[23] = '\0'; | |
2585 | |
2586 tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), str); | |
2587 if (!tag) { | |
2588 /* For reasons I don't understand, setting "scale" here scaled based on some default | |
2589 * size other than my theme's default size. Our size 4 was actually smaller than | |
2590 * our size 3 for me. So this works around that oddity. | |
2591 */ | |
2592 GtkTextAttributes *attr = gtk_text_view_get_default_attributes(GTK_TEXT_VIEW(imhtml)); | |
2593 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "size", | |
2594 (gint) (pango_font_description_get_size(attr->font) * | |
2595 (double) _point_sizes[size-1]), NULL); | |
2596 gtk_text_attributes_unref(attr); | |
2597 } | |
2598 | |
2599 return tag; | |
2600 } | |
2601 | |
2602 static void remove_tag_by_prefix(GtkIMHtml *imhtml, const GtkTextIter *i, const GtkTextIter *e, | |
2603 const char *prefix, guint len, gboolean homo) | |
2604 { | |
2605 GSList *tags, *l; | |
2606 GtkTextIter iter; | |
2607 | |
2608 tags = gtk_text_iter_get_tags(i); | |
2609 | |
2610 for (l = tags; l; l = l->next) { | |
2611 GtkTextTag *tag = l->data; | |
2612 | |
2613 if (tag->name && !strncmp(tag->name, prefix, len)) | |
2614 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); | |
2615 } | |
2616 | |
2617 g_slist_free(tags); | |
2618 | |
2619 if (homo) | |
2620 return; | |
2621 | |
2622 iter = *i; | |
2623 | |
2624 while (gtk_text_iter_forward_char(&iter) && !gtk_text_iter_equal(&iter, e)) { | |
2625 if (gtk_text_iter_begins_tag(&iter, NULL)) { | |
2626 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE); | |
2627 | |
2628 for (l = tags; l; l = l->next) { | |
2629 GtkTextTag *tag = l->data; | |
2630 | |
2631 if (tag->name && !strncmp(tag->name, prefix, len)) | |
2632 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); | |
2633 } | |
2634 | |
2635 g_slist_free(tags); | |
2636 } | |
2637 } | |
2638 } | |
2639 | |
2640 static void remove_font_size(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2641 { | |
2642 remove_tag_by_prefix(imhtml, i, e, "FONT SIZE ", 10, homo); | |
2643 } | |
2644 | |
2645 static void remove_font_face(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2646 { | |
2647 remove_tag_by_prefix(imhtml, i, e, "FONT FACE ", 10, homo); | |
2648 } | |
2649 | |
2650 static void remove_font_forecolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2651 { | |
2652 remove_tag_by_prefix(imhtml, i, e, "FORECOLOR ", 10, homo); | |
2653 } | |
2654 | |
2655 static void remove_font_backcolor(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2656 { | |
2657 remove_tag_by_prefix(imhtml, i, e, "BACKCOLOR ", 10, homo); | |
2658 } | |
2659 | |
2660 static void remove_font_link(GtkIMHtml *imhtml, GtkTextIter *i, GtkTextIter *e, gboolean homo) | |
2661 { | |
2662 remove_tag_by_prefix(imhtml, i, e, "LINK ", 5, homo); | |
2663 } | |
2664 | |
2493 /* Editable stuff */ | 2665 /* Editable stuff */ |
2494 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) | 2666 static void preinsert_cb(GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len, GtkIMHtml *imhtml) |
2495 { | 2667 { |
2496 GtkIMHtmlFormatSpan *span = NULL; | 2668 imhtml->insert_offset = gtk_text_iter_get_offset(iter); |
2497 GtkTextIter end; | 2669 } |
2498 | 2670 |
2499 gtk_text_iter_forward_chars(iter, len); | 2671 static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *end, gchar *text, gint len, GtkIMHtml *imhtml) |
2500 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | 2672 { |
2501 gtk_text_iter_forward_char(&end); | 2673 GtkTextIter start; |
2502 | 2674 |
2503 if (!gtk_text_iter_equal(&end, iter)) | 2675 if (!len) |
2504 return; | 2676 return; |
2505 | 2677 |
2506 | 2678 start = *end; |
2507 if ((span = imhtml->edit.bold)) { | 2679 gtk_text_iter_set_offset(&start, imhtml->insert_offset); |
2508 GtkTextIter bold; | 2680 |
2509 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &bold, span->start); | 2681 if (imhtml->edit.bold) |
2510 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &bold, iter); | 2682 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, end); |
2511 } | 2683 else |
2512 | 2684 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, end); |
2513 if ((span = imhtml->edit.italic)) { | 2685 |
2514 GtkTextIter italic; | 2686 if (imhtml->edit.italic) |
2515 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &italic, span->start); | 2687 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, end); |
2516 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &italic, | 2688 else |
2517 iter); | 2689 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, end); |
2518 } | 2690 |
2519 | 2691 if (imhtml->edit.underline) |
2520 if ((span = imhtml->edit.underline)) { | 2692 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, end); |
2521 GtkTextIter underline; | 2693 else |
2522 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &underline, span->start); | 2694 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, end); |
2523 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &underline, | 2695 |
2524 iter); | 2696 if (imhtml->edit.forecolor) { |
2525 } | 2697 remove_font_forecolor(imhtml, &start, end, TRUE); |
2526 | 2698 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2527 if ((span = imhtml->edit.forecolor)) { | 2699 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), |
2528 GtkTextIter fore; | 2700 &start, end); |
2529 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &fore, span->start); | 2701 } |
2530 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &fore, iter); | 2702 |
2531 } | 2703 if (imhtml->edit.backcolor) { |
2532 | 2704 remove_font_backcolor(imhtml, &start, end, TRUE); |
2533 if ((span = imhtml->edit.backcolor)) { | 2705 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2534 GtkTextIter back; | 2706 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), |
2535 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &back, span->start); | 2707 &start, end); |
2536 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &back, iter); | 2708 } |
2537 } | 2709 |
2538 | 2710 if (imhtml->edit.fontface) { |
2539 if ((span = imhtml->edit.fontface)) { | 2711 remove_font_face(imhtml, &start, end, TRUE); |
2540 GtkTextIter face; | 2712 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2541 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &face, span->start); | 2713 find_font_face_tag(imhtml, imhtml->edit.fontface), |
2542 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &face, iter); | 2714 &start, end); |
2543 } | 2715 } |
2544 | 2716 |
2545 if ((span = imhtml->edit.sizespan)) { | 2717 if (imhtml->edit.fontsize) { |
2546 GtkTextIter size; | 2718 remove_font_size(imhtml, &start, end, TRUE); |
2547 /* We create the tags here so that one can grow font or shrink font several times | 2719 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2548 * in a row without creating unnecessary tags */ | 2720 find_font_size_tag(imhtml, imhtml->edit.fontsize), |
2549 if (span->tag == NULL) { | 2721 &start, end); |
2550 span->tag = gtk_text_buffer_create_tag | 2722 } |
2551 (imhtml->text_buffer, NULL, "scale", (double)_point_sizes [imhtml->edit.fontsize-1], NULL); | 2723 |
2552 span->start_tag = g_strdup_printf("<font size=\"%d\">", imhtml->edit.fontsize); | 2724 if (imhtml->edit.link) { |
2553 span->end_tag = g_strdup("</font>"); | 2725 remove_font_link(imhtml, &start, end, TRUE); |
2554 } | 2726 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2555 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &size, span->start); | 2727 imhtml->edit.link, |
2556 gtk_text_buffer_apply_tag(imhtml->text_buffer, span->tag, &size, iter); | 2728 &start, end); |
2557 } | 2729 } |
2730 | |
2558 } | 2731 } |
2559 | 2732 |
2560 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) | 2733 void gtk_imhtml_set_editable(GtkIMHtml *imhtml, gboolean editable) |
2561 { | 2734 { |
2562 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); | 2735 gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), editable); |
2564 * We need a visible caret for accessibility, so mouseless | 2737 * We need a visible caret for accessibility, so mouseless |
2565 * people can highlight stuff. | 2738 * people can highlight stuff. |
2566 */ | 2739 */ |
2567 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ | 2740 /* gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), editable); */ |
2568 imhtml->editable = editable; | 2741 imhtml->editable = editable; |
2569 imhtml->format_functions = !editable ? 0 : -1; | 2742 imhtml->format_functions = GTK_IMHTML_ALL; |
2743 | |
2744 if (editable) | |
2745 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set", | |
2746 G_CALLBACK(mark_set_cb), imhtml); | |
2747 } | |
2748 | |
2749 void gtk_imhtml_set_whole_buffer_formatting_only(GtkIMHtml *imhtml, gboolean wbfo) | |
2750 { | |
2751 g_return_if_fail(imhtml != NULL); | |
2752 | |
2753 imhtml->wbfo = wbfo; | |
2570 } | 2754 } |
2571 | 2755 |
2572 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) | 2756 void gtk_imhtml_set_format_functions(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) |
2573 { | 2757 { |
2574 GObject *object = g_object_ref(G_OBJECT(imhtml)); | 2758 GObject *object = g_object_ref(G_OBJECT(imhtml)); |
2759 imhtml->format_functions = buttons; | |
2575 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); | 2760 g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); |
2576 imhtml->format_functions = buttons; | |
2577 g_object_unref(object); | 2761 g_object_unref(object); |
2578 } | 2762 } |
2579 | 2763 |
2580 static gboolean | |
2581 gtk_imhtml_has_open_tags(GtkIMHtml *imhtml) { | |
2582 if(imhtml->edit.bold && imhtml->edit.bold->end == NULL) | |
2583 return TRUE; | |
2584 | |
2585 if(imhtml->edit.italic && imhtml->edit.italic->end == NULL) | |
2586 return TRUE; | |
2587 | |
2588 if(imhtml->edit.underline && imhtml->edit.underline->end == NULL) | |
2589 return TRUE; | |
2590 | |
2591 if(imhtml->edit.forecolor && imhtml->edit.forecolor->end == NULL) | |
2592 return TRUE; | |
2593 | |
2594 if(imhtml->edit.backcolor && imhtml->edit.backcolor->end == NULL) | |
2595 return TRUE; | |
2596 | |
2597 if(imhtml->edit.fontface && imhtml->edit.fontface->end == NULL) | |
2598 return TRUE; | |
2599 | |
2600 if(imhtml->edit.sizespan && imhtml->edit.sizespan->end == NULL) | |
2601 return TRUE; | |
2602 | |
2603 return FALSE; | |
2604 } | |
2605 | 2764 |
2606 void gtk_imhtml_get_current_format(GtkIMHtml *imhtml, gboolean *bold, | 2765 void gtk_imhtml_get_current_format(GtkIMHtml *imhtml, gboolean *bold, |
2607 gboolean *italic, gboolean *underline) | 2766 gboolean *italic, gboolean *underline) |
2608 { | 2767 { |
2609 GtkTextMark *ins_mark; | 2768 if (imhtml->edit.bold) |
2610 GtkTextIter ins_iter; | 2769 (*bold) = TRUE; |
2611 GSList *tags; | 2770 if (imhtml->edit.italic) |
2612 | 2771 (*italic) = TRUE; |
2613 ins_mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2772 if (imhtml->edit.underline) |
2614 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins_iter, ins_mark); | 2773 (*underline) = TRUE; |
2615 | |
2616 if(gtk_imhtml_has_open_tags(imhtml)) { | |
2617 GtkTextIter end_iter; | |
2618 gint position, length; | |
2619 | |
2620 position = gtk_text_iter_get_offset(&ins_iter); | |
2621 | |
2622 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end_iter); | |
2623 length = gtk_text_iter_get_offset(&end_iter); | |
2624 | |
2625 if(position == length) | |
2626 gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ins_iter, | |
2627 length - 1); | |
2628 } | |
2629 | |
2630 for(tags = gtk_text_iter_get_tags(&ins_iter); | |
2631 tags != NULL; tags = tags->next) | |
2632 { | |
2633 GtkTextTag *tag = GTK_TEXT_TAG(tags->data); | |
2634 if(tag->name) { | |
2635 if(g_ascii_strcasecmp(tag->name, "BOLD") == 0) | |
2636 (*bold) = TRUE; | |
2637 if(g_ascii_strcasecmp(tag->name, "ITALICS") == 0) | |
2638 (*italic) = TRUE; | |
2639 if(g_ascii_strcasecmp(tag->name, "UNDERLINE") == 0) | |
2640 (*underline) = TRUE; | |
2641 } | |
2642 } | |
2643 } | 2774 } |
2644 | 2775 |
2645 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) | 2776 gboolean gtk_imhtml_get_editable(GtkIMHtml *imhtml) |
2646 { | 2777 { |
2647 return imhtml->editable; | 2778 return imhtml->editable; |
2648 } | 2779 } |
2649 | 2780 |
2781 /* | |
2782 * I had this crazy idea about changing the text cursor color to reflex the foreground color | |
2783 * of the text about to be entered. This is the place you'd do it, along with the place where | |
2784 * we actually set a new foreground color. | |
2785 * I may not do this, because people will bitch about Gaim overriding their gtk theme's cursor | |
2786 * colors. | |
2787 * | |
2788 * Just in case I do do this, I asked about what to set the secondary text cursor to. | |
2789 * | |
2790 (12:45:27) ?? ???: secondary_cursor_color = (rgb(background) + rgb(primary_cursor_color) ) / 2 * | |
2791 (12:45:55) ?? ???: understand? * | |
2792 * (12:46:14) Tim: yeah. i didn't know there was an exact formula | |
2793 (12:46:56) ?? ???: u might need to exactract separate each color from RGB * | |
2794 */ | |
2795 | |
2796 static void mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *arg1, GtkTextMark *mark, | |
2797 GtkIMHtml *imhtml) | |
2798 { | |
2799 GSList *tags, *l; | |
2800 GtkTextIter iter; | |
2801 | |
2802 if (mark != gtk_text_buffer_get_insert(buffer)) | |
2803 return; | |
2804 | |
2805 if (!gtk_text_buffer_get_char_count(buffer)) | |
2806 return; | |
2807 | |
2808 imhtml->edit.bold = imhtml->edit.italic = imhtml->edit.underline = FALSE; | |
2809 if (imhtml->edit.forecolor) | |
2810 g_free(imhtml->edit.forecolor); | |
2811 imhtml->edit.forecolor = NULL; | |
2812 if (imhtml->edit.backcolor) | |
2813 g_free(imhtml->edit.backcolor); | |
2814 imhtml->edit.backcolor = NULL; | |
2815 if (imhtml->edit.fontface) | |
2816 g_free(imhtml->edit.fontface); | |
2817 imhtml->edit.fontface = NULL; | |
2818 imhtml->edit.fontsize = 0; | |
2819 imhtml->edit.link = NULL; | |
2820 | |
2821 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | |
2822 | |
2823 | |
2824 if (gtk_text_iter_is_end(&iter)) | |
2825 tags = gtk_text_iter_get_toggled_tags(&iter, FALSE); | |
2826 else | |
2827 tags = gtk_text_iter_get_tags(&iter); | |
2828 | |
2829 for (l = tags; l != NULL; l = l->next) { | |
2830 GtkTextTag *tag = GTK_TEXT_TAG(l->data); | |
2831 | |
2832 if (tag->name) { | |
2833 if (strcmp(tag->name, "BOLD") == 0) | |
2834 imhtml->edit.bold = TRUE; | |
2835 if (strcmp(tag->name, "ITALICS") == 0) | |
2836 imhtml->edit.italic = TRUE; | |
2837 if (strcmp(tag->name, "UNDERLINE") == 0) | |
2838 imhtml->edit.underline = TRUE; | |
2839 if (strncmp(tag->name, "FORECOLOR ", 10) == 0) | |
2840 imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); | |
2841 if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) | |
2842 imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); | |
2843 if (strncmp(tag->name, "FONT FACE ", 10) == 0) | |
2844 imhtml->edit.fontface = g_strdup(&(tag->name)[10]); | |
2845 if (strncmp(tag->name, "FONT SIZE ", 10) == 0) | |
2846 imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); | |
2847 if (strncmp(tag->name, "LINK ", 5) == 0) | |
2848 imhtml->edit.link = tag; | |
2849 } | |
2850 } | |
2851 | |
2852 g_slist_free(tags); | |
2853 } | |
2854 | |
2650 gboolean gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) | 2855 gboolean gtk_imhtml_toggle_bold(GtkIMHtml *imhtml) |
2651 { | 2856 { |
2652 GtkIMHtmlFormatSpan *span; | |
2653 GObject *object; | 2857 GObject *object; |
2654 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2858 GtkTextIter start, end; |
2655 GtkTextIter iter; | 2859 |
2656 | 2860 imhtml->edit.bold = !imhtml->edit.bold; |
2657 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | 2861 |
2658 | 2862 if (imhtml->wbfo) { |
2659 if (!imhtml->edit.bold) { | 2863 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
2660 span = g_new0(GtkIMHtmlFormatSpan, 1); | 2864 if (imhtml->edit.bold) |
2661 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2865 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); |
2662 span->start_tag = g_strdup("<b>"); | 2866 else |
2663 span->end = NULL; | 2867 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); |
2664 span->end_tag = g_strdup("</b>"); | 2868 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
2665 span->buffer = imhtml->text_buffer; | 2869 if (imhtml->edit.bold) |
2666 span->tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "BOLD"); | 2870 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); |
2667 imhtml->edit.bold = span; | 2871 else |
2668 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | 2872 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "BOLD", &start, &end); |
2669 } else { | 2873 |
2670 GtkTextIter start; | 2874 } |
2671 span = imhtml->edit.bold; | |
2672 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2673 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, span->start); | |
2674 if (gtk_text_iter_equal(&start, &iter)) { | |
2675 /* Format turned off before any text was entered, so remove the tag */ | |
2676 imhtml->format_spans = g_list_remove(imhtml->format_spans, span); | |
2677 if (span->start_tag) | |
2678 g_free(span->start_tag); | |
2679 if (span->end_tag) | |
2680 g_free(span->end_tag); | |
2681 g_free(span); | |
2682 } | |
2683 imhtml->edit.bold = NULL; | |
2684 } | |
2685 | |
2686 object = g_object_ref(G_OBJECT(imhtml)); | 2875 object = g_object_ref(G_OBJECT(imhtml)); |
2687 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); | 2876 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_BOLD); |
2688 g_object_unref(object); | 2877 g_object_unref(object); |
2689 | 2878 |
2690 return (imhtml->edit.bold != NULL); | 2879 return (imhtml->edit.bold != FALSE); |
2691 } | 2880 } |
2692 | 2881 |
2693 gboolean gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) | 2882 gboolean gtk_imhtml_toggle_italic(GtkIMHtml *imhtml) |
2694 { | 2883 { |
2695 GtkIMHtmlFormatSpan *span; | |
2696 GObject *object; | 2884 GObject *object; |
2697 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2885 GtkTextIter start, end; |
2698 GtkTextIter iter; | 2886 |
2699 | 2887 imhtml->edit.italic = !imhtml->edit.italic; |
2700 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | 2888 |
2701 | 2889 if (imhtml->wbfo) { |
2702 if (!imhtml->edit.italic) { | 2890 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
2703 span = g_new0(GtkIMHtmlFormatSpan, 1); | 2891 if (imhtml->edit.italic) |
2704 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2892 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
2705 span->start_tag = g_strdup("<i>"); | 2893 else |
2706 span->end = NULL; | 2894 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
2707 span->end_tag = g_strdup("</i>"); | 2895 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
2708 span->buffer = imhtml->text_buffer; | 2896 if (imhtml->edit.italic) |
2709 span->tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "ITALIC"); | 2897 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
2710 imhtml->edit.italic = span; | 2898 else |
2711 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | 2899 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "ITALICS", &start, &end); |
2712 } else { | 2900 } |
2713 GtkTextIter start; | |
2714 span = imhtml->edit.italic; | |
2715 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2716 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, span->start); | |
2717 if (gtk_text_iter_equal(&start, &iter)) { /* Format turned off before any text was entered, so remove the tag */ | |
2718 imhtml->format_spans = g_list_remove(imhtml->format_spans, span); | |
2719 if (span->start_tag) | |
2720 g_free(span->start_tag); | |
2721 if (span->end_tag) | |
2722 g_free(span->end_tag); | |
2723 g_free(span); | |
2724 } | |
2725 imhtml->edit.italic = NULL; | |
2726 } | |
2727 | |
2728 object = g_object_ref(G_OBJECT(imhtml)); | 2901 object = g_object_ref(G_OBJECT(imhtml)); |
2729 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_ITALIC); | 2902 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_ITALIC); |
2730 g_object_unref(object); | 2903 g_object_unref(object); |
2731 | 2904 |
2732 return imhtml->edit.italic != NULL; | 2905 return imhtml->edit.italic != FALSE; |
2733 } | 2906 } |
2734 | 2907 |
2735 gboolean gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) | 2908 gboolean gtk_imhtml_toggle_underline(GtkIMHtml *imhtml) |
2736 { | 2909 { |
2737 GtkIMHtmlFormatSpan *span; | |
2738 GObject *object; | 2910 GObject *object; |
2739 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2911 GtkTextIter start, end; |
2740 GtkTextIter iter; | 2912 |
2741 | 2913 imhtml->edit.underline = !imhtml->edit.underline; |
2742 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | 2914 |
2743 | 2915 if (imhtml->wbfo) { |
2744 if (!imhtml->edit.underline) { | 2916 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
2745 span = g_new0(GtkIMHtmlFormatSpan, 1); | 2917 if (imhtml->edit.underline) |
2746 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2918 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
2747 span->start_tag = g_strdup("<u>"); | 2919 else |
2748 span->end = NULL; | 2920 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
2749 span->end_tag = g_strdup("</u>"); | 2921 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
2750 span->buffer = imhtml->text_buffer; | 2922 if (imhtml->edit.underline) |
2751 span->tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "UNDERLINE"); | 2923 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
2752 imhtml->edit.underline = span; | 2924 else |
2753 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | 2925 gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "UNDERLINE", &start, &end); |
2754 } else { | 2926 } |
2755 GtkTextIter start; | |
2756 span = imhtml->edit.underline; | |
2757 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2758 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, span->start); | |
2759 if (gtk_text_iter_equal(&start, &iter)) { /* Format turned off before any text was entered, so remove the tag */ | |
2760 imhtml->format_spans = g_list_remove(imhtml->format_spans, span); | |
2761 if (span->start_tag) | |
2762 g_free(span->start_tag); | |
2763 if (span->end_tag) | |
2764 g_free(span->end_tag); | |
2765 g_free(span); | |
2766 } | |
2767 imhtml->edit.underline = NULL; | |
2768 } | |
2769 | |
2770 object = g_object_ref(G_OBJECT(imhtml)); | 2927 object = g_object_ref(G_OBJECT(imhtml)); |
2771 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_UNDERLINE); | 2928 g_signal_emit(object, signals[TOGGLE_FORMAT], 0, GTK_IMHTML_UNDERLINE); |
2772 g_object_unref(object); | 2929 g_object_unref(object); |
2773 | 2930 |
2774 return imhtml->edit.underline != NULL; | 2931 return imhtml->edit.underline != FALSE; |
2775 } | 2932 } |
2776 | 2933 |
2777 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) | 2934 void gtk_imhtml_font_set_size(GtkIMHtml *imhtml, gint size) |
2778 { | 2935 { |
2779 GtkIMHtmlFormatSpan *span; | 2936 GtkTextIter start, end; |
2780 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
2781 GtkTextIter iter; | |
2782 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
2783 | 2937 |
2784 imhtml->edit.fontsize = size; | 2938 imhtml->edit.fontsize = size; |
2785 | 2939 |
2786 if (imhtml->edit.sizespan) { | 2940 |
2787 GtkTextIter iter2; | 2941 if (imhtml->wbfo) { |
2788 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter2, imhtml->edit.sizespan->start); | 2942 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
2789 if (gtk_text_iter_equal(&iter2, &iter)) | 2943 remove_font_size(imhtml, &start, &end, TRUE); |
2790 return; | 2944 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2791 span = imhtml->edit.sizespan; | 2945 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); |
2792 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2946 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
2793 } | 2947 remove_font_size(imhtml, &start, &end, FALSE); |
2794 if (size != -1) { | 2948 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2795 span = g_malloc0(sizeof(GtkIMHtmlFormatSpan)); | 2949 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); |
2796 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2950 } |
2797 span->end = NULL; | 2951 |
2798 span->buffer = imhtml->text_buffer; | |
2799 span->tag = NULL; | |
2800 imhtml->edit.sizespan = span; | |
2801 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2802 } | |
2803 } | 2952 } |
2804 | 2953 |
2805 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) | 2954 void gtk_imhtml_font_shrink(GtkIMHtml *imhtml) |
2806 { | 2955 { |
2807 GtkIMHtmlFormatSpan *span; | 2956 GtkTextIter start, end; |
2808 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2957 |
2809 GtkTextIter iter; | |
2810 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
2811 if (imhtml->edit.fontsize == 1) | 2958 if (imhtml->edit.fontsize == 1) |
2812 return; | 2959 return; |
2813 | 2960 |
2814 imhtml->edit.fontsize--; | 2961 if (!imhtml->edit.fontsize) |
2815 | 2962 imhtml->edit.fontsize = 2; |
2816 if (imhtml->edit.sizespan) { | 2963 else |
2817 GtkTextIter iter2; | 2964 imhtml->edit.fontsize--; |
2818 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter2, imhtml->edit.sizespan->start); | 2965 |
2819 if (gtk_text_iter_equal(&iter2, &iter)) | 2966 if (imhtml->wbfo) { |
2820 return; | 2967 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
2821 span = imhtml->edit.sizespan; | 2968 remove_font_size(imhtml, &start, &end, TRUE); |
2822 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2969 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2823 } | 2970 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); |
2824 | 2971 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
2825 span = g_malloc0(sizeof(GtkIMHtmlFormatSpan)); | 2972 remove_font_size(imhtml, &start, &end, FALSE); |
2826 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2973 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2827 span->end = NULL; | 2974 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); |
2828 span->buffer = imhtml->text_buffer; | 2975 } |
2829 span->tag = NULL; | |
2830 imhtml->edit.sizespan = span; | |
2831 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2832 } | 2976 } |
2833 | 2977 |
2834 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) | 2978 void gtk_imhtml_font_grow(GtkIMHtml *imhtml) |
2835 { | 2979 { |
2836 GtkIMHtmlFormatSpan *span; | 2980 GtkTextIter start, end; |
2837 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 2981 |
2838 GtkTextIter iter; | |
2839 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
2840 if (imhtml->edit.fontsize == MAX_FONT_SIZE) | 2982 if (imhtml->edit.fontsize == MAX_FONT_SIZE) |
2841 return; | 2983 return; |
2842 | 2984 |
2843 imhtml->edit.fontsize++; | 2985 if (!imhtml->edit.fontsize) |
2844 if (imhtml->edit.sizespan) { | 2986 imhtml->edit.fontsize = 4; |
2845 GtkTextIter iter2; | 2987 else |
2846 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter2, imhtml->edit.sizespan->start); | 2988 imhtml->edit.fontsize++; |
2847 if (gtk_text_iter_equal(&iter2, &iter)) | 2989 |
2848 return; | 2990 if (imhtml->wbfo) { |
2849 span = imhtml->edit.sizespan; | 2991 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); |
2850 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2992 remove_font_size(imhtml, &start, &end, TRUE); |
2851 } | 2993 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2852 | 2994 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); |
2853 span = g_malloc0(sizeof(GtkIMHtmlFormatSpan)); | 2995 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { |
2854 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 2996 remove_font_size(imhtml, &start, &end, FALSE); |
2855 span->end = NULL; | 2997 gtk_text_buffer_apply_tag(imhtml->text_buffer, |
2856 span->tag = NULL; | 2998 find_font_size_tag(imhtml, imhtml->edit.fontsize), &start, &end); |
2857 span->buffer = imhtml->text_buffer; | 2999 } |
2858 imhtml->edit.sizespan = span; | |
2859 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2860 } | 3000 } |
2861 | 3001 |
2862 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) | 3002 gboolean gtk_imhtml_toggle_forecolor(GtkIMHtml *imhtml, const char *color) |
2863 { | 3003 { |
2864 GtkIMHtmlFormatSpan *span; | 3004 GtkTextIter start, end; |
2865 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | 3005 |
3006 if (imhtml->edit.forecolor != NULL) | |
3007 g_free(imhtml->edit.forecolor); | |
3008 | |
3009 if (color) { | |
3010 imhtml->edit.forecolor = g_strdup(color); | |
3011 if (imhtml->wbfo) { | |
3012 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3013 remove_font_forecolor(imhtml, &start, &end, TRUE); | |
3014 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3015 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), &start, &end); | |
3016 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3017 remove_font_forecolor(imhtml, &start, &end, FALSE); | |
3018 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3019 find_font_forecolor_tag(imhtml, imhtml->edit.forecolor), | |
3020 &start, &end); | |
3021 } | |
3022 } else { | |
3023 imhtml->edit.forecolor = NULL; | |
3024 } | |
3025 | |
3026 return imhtml->edit.forecolor != NULL; | |
3027 } | |
3028 | |
3029 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
3030 { | |
3031 GtkTextIter start, end; | |
3032 | |
3033 if (imhtml->edit.backcolor != NULL) | |
3034 g_free(imhtml->edit.backcolor); | |
3035 | |
3036 if (color) { | |
3037 imhtml->edit.backcolor = g_strdup(color); | |
3038 | |
3039 if (imhtml->wbfo) { | |
3040 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3041 remove_font_backcolor(imhtml, &start, &end, TRUE); | |
3042 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3043 find_font_backcolor_tag(imhtml, imhtml->edit.backcolor), &start, &end); | |
3044 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3045 remove_font_backcolor(imhtml, &start, &end, FALSE); | |
3046 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3047 find_font_backcolor_tag(imhtml, | |
3048 imhtml->edit.backcolor), &start, &end); | |
3049 } | |
3050 } else { | |
3051 imhtml->edit.backcolor = NULL; | |
3052 } | |
3053 | |
3054 return imhtml->edit.backcolor != NULL; | |
3055 } | |
3056 | |
3057 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
3058 { | |
3059 GtkTextIter start, end; | |
3060 | |
3061 if (imhtml->edit.fontface != NULL) | |
3062 g_free(imhtml->edit.fontface); | |
3063 | |
3064 if (face) { | |
3065 imhtml->edit.fontface = g_strdup(face); | |
3066 | |
3067 if (imhtml->wbfo) { | |
3068 gtk_text_buffer_get_bounds(imhtml->text_buffer, &start, &end); | |
3069 remove_font_face(imhtml, &start, &end, TRUE); | |
3070 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3071 find_font_face_tag(imhtml, imhtml->edit.fontface), &start, &end); | |
3072 } else if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3073 remove_font_face(imhtml, &start, &end, FALSE); | |
3074 gtk_text_buffer_apply_tag(imhtml->text_buffer, | |
3075 find_font_face_tag(imhtml, imhtml->edit.fontface), | |
3076 &start, &end); | |
3077 } | |
3078 } else { | |
3079 imhtml->edit.fontface = NULL; | |
3080 } | |
3081 | |
3082 return imhtml->edit.fontface != NULL; | |
3083 } | |
3084 | |
3085 void gtk_imhtml_toggle_link(GtkIMHtml *imhtml, const char *url) | |
3086 { | |
3087 GtkTextIter start, end; | |
3088 GtkTextTag *linktag; | |
3089 static guint linkno = 0; | |
3090 gchar str[48]; | |
3091 | |
3092 imhtml->edit.link = NULL; | |
3093 | |
3094 | |
3095 | |
3096 if (url) { | |
3097 g_snprintf(str, sizeof(str), "LINK %d", linkno++); | |
3098 str[47] = '\0'; | |
3099 | |
3100 imhtml->edit.link = linktag = gtk_text_buffer_create_tag(imhtml->text_buffer, str, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); | |
3101 g_object_set_data_full(G_OBJECT(linktag), "link_url", g_strdup(url), g_free); | |
3102 g_signal_connect(G_OBJECT(linktag), "event", G_CALLBACK(tag_event), NULL); | |
3103 | |
3104 if (imhtml->editable && gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) { | |
3105 remove_font_link(imhtml, &start, &end, FALSE); | |
3106 gtk_text_buffer_apply_tag(imhtml->text_buffer, linktag, &start, &end); | |
3107 } | |
3108 } | |
3109 } | |
3110 | |
3111 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, GtkTextMark *mark, const char *url, const char *text) | |
3112 { | |
2866 GtkTextIter iter; | 3113 GtkTextIter iter; |
2867 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | 3114 |
2868 if (color) { | 3115 gtk_imhtml_toggle_link(imhtml, url); |
2869 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | 3116 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); |
2870 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 3117 gtk_text_buffer_insert(imhtml->text_buffer, &iter, text, -1); |
2871 span->start_tag = g_strdup_printf("<font color=\"%s\">", color); | 3118 gtk_imhtml_toggle_link(imhtml, NULL); |
2872 span->end = NULL; | 3119 } |
2873 span->end_tag = g_strdup("</font>"); | 3120 |
2874 span->buffer = imhtml->text_buffer; | 3121 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) |
2875 span->tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", color, NULL); | 3122 { |
2876 imhtml->edit.forecolor = span; | 3123 GtkTextMark *mark; |
2877 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2878 } else { | |
2879 span = imhtml->edit.forecolor; | |
2880 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2881 imhtml->edit.forecolor = NULL; | |
2882 } | |
2883 | |
2884 | |
2885 return imhtml->edit.forecolor != NULL; | |
2886 } | |
2887 | |
2888 gboolean gtk_imhtml_toggle_backcolor(GtkIMHtml *imhtml, const char *color) | |
2889 { | |
2890 GtkIMHtmlFormatSpan *span; | |
2891 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
2892 GtkTextIter iter; | 3124 GtkTextIter iter; |
2893 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | 3125 |
2894 if (color) { | 3126 mark = gtk_text_buffer_get_insert(imhtml->text_buffer); |
2895 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
2896 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2897 span->start_tag = g_strdup_printf("<font back=\"%s\">", color); | |
2898 span->end = NULL; | |
2899 span->end_tag = g_strdup("</font>"); | |
2900 span->buffer = imhtml->text_buffer; | |
2901 span->tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", color, NULL); | |
2902 imhtml->edit.backcolor = span; | |
2903 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2904 } else { | |
2905 span = imhtml->edit.backcolor; | |
2906 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2907 imhtml->edit.backcolor = NULL; | |
2908 } | |
2909 return imhtml->edit.backcolor != NULL; | |
2910 } | |
2911 | |
2912 gboolean gtk_imhtml_toggle_fontface(GtkIMHtml *imhtml, const char *face) | |
2913 { | |
2914 GtkIMHtmlFormatSpan *span; | |
2915 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
2916 GtkTextIter iter; | |
2917 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | |
2918 if (face) { | |
2919 span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
2920 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2921 span->start_tag = g_strdup_printf("<font face=\"%s\">", face); | |
2922 span->end = NULL; | |
2923 span->end_tag = g_strdup("</font>"); | |
2924 span->buffer = imhtml->text_buffer; | |
2925 span->tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "family", face, NULL); | |
2926 imhtml->edit.fontface = span; | |
2927 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2928 } else { | |
2929 span = imhtml->edit.fontface; | |
2930 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2931 imhtml->edit.fontface = NULL; | |
2932 } | |
2933 return imhtml->edit.fontface != NULL; | |
2934 } | |
2935 | |
2936 void gtk_imhtml_insert_link(GtkIMHtml *imhtml, const char *url, const char *text) | |
2937 { | |
2938 GtkIMHtmlFormatSpan *span = g_malloc(sizeof(GtkIMHtmlFormatSpan)); | |
2939 GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
2940 GtkTextIter iter; | |
2941 GtkTextTag *tag, *linktag; | |
2942 | |
2943 tag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, NULL); | |
2944 g_object_set_data(G_OBJECT(tag), "link_url", g_strdup(url)); | |
2945 | |
2946 linktag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(imhtml->text_buffer), "LINK"); | |
2947 | 3127 |
2948 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); | 3128 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); |
2949 span->start = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | 3129 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); |
2950 span->buffer = imhtml->text_buffer; | 3130 } |
2951 span->start_tag = g_strdup_printf("<a href=\"%s\">", url); | 3131 |
2952 span->end_tag = g_strdup("</a>"); | 3132 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) |
2953 g_signal_connect(G_OBJECT(tag), "event", G_CALLBACK(tag_event), g_strdup(url)); | 3133 { |
2954 | |
2955 gtk_text_buffer_insert_with_tags(imhtml->text_buffer, &iter, text, strlen(text), linktag, tag, NULL); | |
2956 span->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); | |
2957 imhtml->format_spans = g_list_append(imhtml->format_spans, span); | |
2958 } | |
2959 | |
2960 void gtk_imhtml_insert_smiley(GtkIMHtml *imhtml, const char *sml, char *smiley) | |
2961 { | |
2962 GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer); | |
2963 GtkTextIter iter; | |
2964 GdkPixbuf *pixbuf = NULL; | 3134 GdkPixbuf *pixbuf = NULL; |
2965 GdkPixbufAnimation *annipixbuf = NULL; | 3135 GdkPixbufAnimation *annipixbuf = NULL; |
2966 GtkWidget *icon = NULL; | 3136 GtkWidget *icon = NULL; |
2967 GtkTextChildAnchor *anchor; | 3137 GtkTextChildAnchor *anchor; |
2968 char *unescaped = gaim_unescape_html(smiley); | 3138 char *unescaped = gaim_unescape_html(smiley); |
2969 | 3139 |
2970 if (!imhtml->show_smileys) { | 3140 if (!imhtml->show_smileys) { |
2971 gtk_text_buffer_insert_at_cursor(imhtml->text_buffer, smiley, strlen(smiley)); | 3141 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, strlen(smiley)); |
2972 return; | 3142 return; |
2973 } | 3143 } |
2974 | 3144 |
2975 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, ins); | 3145 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
2976 anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); | |
2977 g_object_set_data(G_OBJECT(anchor), "text_tag", unescaped); | 3146 g_object_set_data(G_OBJECT(anchor), "text_tag", unescaped); |
2978 | 3147 |
2979 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); | 3148 annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); |
2980 if(annipixbuf) { | 3149 if(annipixbuf) { |
2981 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { | 3150 if(gdk_pixbuf_animation_is_static_image(annipixbuf)) { |
2991 gtk_widget_show(icon); | 3160 gtk_widget_show(icon); |
2992 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); | 3161 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); |
2993 } | 3162 } |
2994 } | 3163 } |
2995 | 3164 |
2996 int span_compare_begin(const GtkIMHtmlFormatSpan *a, const GtkIMHtmlFormatSpan *b, GtkTextBuffer *buffer) | 3165 static const gchar *tag_to_html_start(GtkTextTag *tag) |
2997 { | 3166 { |
2998 GtkTextIter ia, ib; | 3167 const gchar *name; |
2999 gtk_text_buffer_get_iter_at_mark(buffer, &ia, a->start); | 3168 static gchar buf[1024]; |
3000 gtk_text_buffer_get_iter_at_mark(buffer, &ib, b->start); | 3169 |
3001 return gtk_text_iter_compare(&ia, &ib); | 3170 name = tag->name; |
3002 } | 3171 g_return_val_if_fail(name != NULL, ""); |
3003 | 3172 |
3004 int span_compare_end(GtkIMHtmlFormatSpan *a, GtkIMHtmlFormatSpan *b) | 3173 if (strcmp(name, "BOLD") == 0) { |
3005 { | 3174 return "<b>"; |
3006 GtkTextIter ia, ib; | 3175 } else if (strcmp(name, "ITALICS") == 0) { |
3007 gtk_text_buffer_get_iter_at_mark(a->buffer, &ia, a->start); | 3176 return "<i>"; |
3008 gtk_text_buffer_get_iter_at_mark(b->buffer, &ib, b->start); | 3177 } else if (strcmp(name, "UNDERLINE") == 0) { |
3009 /* The -1 here makes it so that if I have two spans that close at the same point, the | 3178 return "<u>"; |
3010 * span added second will be closed first, as in <b><i>Hello</i></b>. Without this, | 3179 } else if (strncmp(name, "LINK ", 5) == 0) { |
3011 * it would be <b><i>Hello</b></i> I took it out. It started breaking things, and I don't know why*/ | 3180 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); |
3012 return gtk_text_iter_compare(&ia, &ib); | 3181 if (tmp) { |
3182 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); | |
3183 buf[sizeof(buf)-1] = '\0'; | |
3184 return buf; | |
3185 } else { | |
3186 return ""; | |
3187 } | |
3188 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
3189 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); | |
3190 return buf; | |
3191 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
3192 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); | |
3193 return buf; | |
3194 } else if (strncmp(name, "FONT FACE ", 10) == 0) { | |
3195 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); | |
3196 return buf; | |
3197 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
3198 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); | |
3199 return buf; | |
3200 } else { | |
3201 return ""; | |
3202 } | |
3203 } | |
3204 | |
3205 static const gchar *tag_to_html_end(GtkTextTag *tag) | |
3206 { | |
3207 const gchar *name; | |
3208 | |
3209 name = tag->name; | |
3210 g_return_val_if_fail(name != NULL, ""); | |
3211 | |
3212 if (strcmp(name, "BOLD") == 0) { | |
3213 return "</b>"; | |
3214 } else if (strcmp(name, "ITALICS") == 0) { | |
3215 return "</i>"; | |
3216 } else if (strcmp(name, "UNDERLINE") == 0) { | |
3217 return "</u>"; | |
3218 } else if (strncmp(name, "LINK ", 5) == 0) { | |
3219 return "</a>"; | |
3220 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { | |
3221 return "</font>"; | |
3222 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { | |
3223 return "</font>"; | |
3224 } else if (strncmp(name, "FONT FACE ", 10) == 0) { | |
3225 return "</font>"; | |
3226 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { | |
3227 return "</font>"; | |
3228 } else { | |
3229 return ""; | |
3230 } | |
3231 } | |
3232 | |
3233 static gboolean tag_ends_here(GtkTextTag *tag, GtkTextIter *iter, GtkTextIter *niter) | |
3234 { | |
3235 return ((gtk_text_iter_has_tag(iter, GTK_TEXT_TAG(tag)) && | |
3236 !gtk_text_iter_has_tag(niter, GTK_TEXT_TAG(tag))) || | |
3237 gtk_text_iter_is_end(niter)); | |
3013 } | 3238 } |
3014 | 3239 |
3015 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such | 3240 /* Basic notion here: traverse through the text buffer one-by-one, non-character elements, such |
3016 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else | 3241 * as smileys and IM images are represented by the Unicode "unknown" character. Handle them. Else |
3017 * check the list of formatted strings, sorted by the position of the starting tags and apply them as | 3242 * check for tags that are toggled on, insert their html form, and push them on the queue. Then insert |
3018 * needed. After applying the start tags, add the end tags to the "closers" list, which is sorted by | 3243 * the actual text. Then check for tags that are toggled off and insert them, after checking the queue. |
3019 * location of ending tags. These get applied in a similar fashion. Finally, replace <, >, &, and " | 3244 * Finally, replace <, >, &, and " with their HTML equivilent. |
3020 * with their HTML equivilent. */ | 3245 */ |
3021 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) | 3246 char *gtk_imhtml_get_markup_range(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) |
3022 { | 3247 { |
3023 gunichar c; | 3248 gunichar c; |
3024 GtkIMHtmlFormatSpan *sspan = NULL, *espan = NULL; | 3249 GtkTextIter iter, nextiter; |
3025 GtkTextIter iter, siter, eiter; | |
3026 GList *starters = imhtml->format_spans; | |
3027 GList *closers = NULL; | |
3028 GString *str = g_string_new(""); | 3250 GString *str = g_string_new(""); |
3029 | 3251 GSList *tags, *sl; |
3030 g_list_sort_with_data(starters, (GCompareDataFunc)span_compare_begin, imhtml->text_buffer); | 3252 GQueue *q, *r; |
3253 GtkTextTag *tag; | |
3254 | |
3255 q = g_queue_new(); | |
3256 r = g_queue_new(); | |
3257 | |
3031 | 3258 |
3032 gtk_text_iter_order(start, end); | 3259 gtk_text_iter_order(start, end); |
3033 iter = *start; | 3260 nextiter = iter = *start; |
3034 | 3261 gtk_text_iter_forward_char(&nextiter); |
3035 | 3262 |
3036 /* Initialize these to the end iter */ | 3263 /* First add the tags that are already in progress */ |
3037 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | 3264 tags = gtk_text_iter_get_tags(start); |
3038 eiter = siter; | 3265 |
3039 | 3266 for (sl = tags; sl; sl = sl->next) { |
3040 if (starters) { | 3267 tag = sl->data; |
3041 while (starters) { | 3268 if (!gtk_text_iter_toggles_tag(start, GTK_TEXT_TAG(tag))) { |
3042 GtkTextIter tagend; | 3269 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tag))); |
3043 sspan = (GtkIMHtmlFormatSpan*)starters->data; | 3270 g_queue_push_tail(q, tag); |
3044 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | 3271 } |
3045 if (gtk_text_iter_compare(&siter, start) > 0) | 3272 } |
3046 break; | 3273 g_slist_free(tags); |
3047 if (sspan->end) | 3274 |
3048 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &tagend, sspan->end); | 3275 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { |
3049 if (sspan->end == NULL || gtk_text_iter_compare(&tagend, start) > 0) { | 3276 |
3050 str = g_string_append(str, sspan->start_tag); | 3277 tags = gtk_text_iter_get_tags(&iter); |
3051 closers = g_list_insert_sorted(closers, sspan, (GCompareFunc)span_compare_end); | 3278 |
3052 espan = (GtkIMHtmlFormatSpan*)closers->data; | 3279 for (sl = tags; sl; sl = sl->next) { |
3053 /* | 3280 tag = sl->data; |
3054 * When sending an IM, the following line causes the following warning: | 3281 if (gtk_text_iter_begins_tag(&iter, GTK_TEXT_TAG(tag))) { |
3055 * Gtk: file gtktextbuffer.c: line 1794 | 3282 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tag))); |
3056 * (gtk_text_buffer_get_iter_at_mark): assertion `GTK_IS_TEXT_MARK (mark)' failed | 3283 g_queue_push_tail(q, tag); |
3057 * | |
3058 * The callback path thingy to get here is: | |
3059 * gtkconv.c, send(), "buf = gtk_imhtml_get_markup(GTK_IMHTML(gtkconv->entry));" | |
3060 * gtkimhtml.c, gtk_imthml_get_markup(), "return gtk_imhtml_get_markup_range(imhtml, &start, &end);" | |
3061 * | |
3062 * I don't really know anything about gtkimhtml, but it almost seems like | |
3063 * the line above this comments expects to find a closing html tag, but | |
3064 * can't, for some reason. The warning depends on how much HTML I send | |
3065 * in my message, kind of. | |
3066 */ | |
3067 } | 3284 } |
3068 sspan = (GtkIMHtmlFormatSpan*)starters->data; | 3285 } |
3069 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | 3286 |
3070 starters = starters->next; | 3287 |
3071 } | |
3072 if (!starters) { | |
3073 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | |
3074 sspan = NULL; | |
3075 } | |
3076 } | |
3077 | |
3078 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, end)) { | |
3079 if (c == 0xFFFC) { | 3288 if (c == 0xFFFC) { |
3080 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | 3289 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); |
3081 char *text = g_object_get_data(G_OBJECT(anchor), "text_tag"); | 3290 char *text = g_object_get_data(G_OBJECT(anchor), "text_tag"); |
3082 str = g_string_append(str, text); | 3291 str = g_string_append(str, text); |
3292 } else if (c == '<') { | |
3293 str = g_string_append(str, "<"); | |
3294 } else if (c == '>') { | |
3295 str = g_string_append(str, ">"); | |
3296 } else if (c == '&') { | |
3297 str = g_string_append(str, "&"); | |
3298 } else if (c == '"') { | |
3299 str = g_string_append(str, """); | |
3300 } else if (c == '\n') { | |
3301 str = g_string_append(str, "<br>"); | |
3083 } else { | 3302 } else { |
3084 while (gtk_text_iter_equal(&eiter, &iter)) { | 3303 str = g_string_append_unichar(str, c); |
3085 /* This is where we shall insert the ending tag of | 3304 } |
3086 * this format span */ | 3305 |
3087 str = g_string_append(str, espan->end_tag); | 3306 tags = g_slist_reverse(tags); |
3088 closers = g_list_remove(closers, espan); | 3307 for (sl = tags; sl; sl = sl->next) { |
3089 if (!closers) { | 3308 tag = sl->data; |
3090 espan = NULL; | 3309 if (tag_ends_here(tag, &iter, &nextiter)) { |
3091 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &eiter); | 3310 |
3092 } else { | 3311 GtkTextTag *tmp; |
3093 espan = (GtkIMHtmlFormatSpan*)closers->data; | 3312 |
3094 if (espan->end) | 3313 while ((tmp = g_queue_pop_tail(q)) != tag) { |
3095 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &eiter, espan->end); | 3314 if (tmp == NULL) |
3096 else { | 3315 break; |
3097 gtk_text_iter_forward_to_end(&eiter); | 3316 |
3098 } | 3317 if (!tag_ends_here(tmp, &iter, &nextiter)) |
3318 g_queue_push_tail(r, tmp); | |
3319 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tmp))); | |
3320 } | |
3321 | |
3322 if (tmp == NULL) | |
3323 gaim_debug_warning("gtkimhtml", "empty queue, more closing tags than open tags!\n"); | |
3324 else | |
3325 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); | |
3326 | |
3327 while ((tmp = g_queue_pop_head(r))) { | |
3328 g_string_append(str, tag_to_html_start(GTK_TEXT_TAG(tmp))); | |
3329 g_queue_push_tail(q, tmp); | |
3099 } | 3330 } |
3100 } | 3331 } |
3101 while (gtk_text_iter_equal(&siter, &iter)) { | 3332 } |
3102 /* This is where we shall insert the starting tag of | 3333 |
3103 * this format span */ | 3334 g_slist_free(tags); |
3104 str = g_string_append(str, sspan->start_tag); | |
3105 if (sspan->end) { | |
3106 closers = g_list_insert_sorted(closers, sspan, (GCompareFunc)span_compare_end); | |
3107 espan = (GtkIMHtmlFormatSpan*)closers->data; | |
3108 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &eiter, espan->end); | |
3109 | |
3110 } | |
3111 starters = starters->next; | |
3112 if (starters) { | |
3113 sspan = (GtkIMHtmlFormatSpan*)starters->data; | |
3114 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, sspan->start); | |
3115 } else { | |
3116 sspan = NULL; | |
3117 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &siter); | |
3118 } | |
3119 | |
3120 } | |
3121 | |
3122 if (c == '<') | |
3123 str = g_string_append(str, "<"); | |
3124 else if (c == '>') | |
3125 str = g_string_append(str, ">"); | |
3126 else if (c == '&') | |
3127 str = g_string_append(str, "&"); | |
3128 else if (c == '"') | |
3129 str = g_string_append(str, """); | |
3130 else if (c == '\n') | |
3131 str = g_string_append(str, "<br>"); | |
3132 else | |
3133 str = g_string_append_unichar(str, c); | |
3134 } | |
3135 gtk_text_iter_forward_char(&iter); | 3335 gtk_text_iter_forward_char(&iter); |
3136 } | 3336 gtk_text_iter_forward_char(&nextiter); |
3137 while (closers) { | 3337 } |
3138 GtkIMHtmlFormatSpan *span = (GtkIMHtmlFormatSpan*)closers->data; | 3338 |
3139 str = g_string_append(str, span->end_tag); | 3339 while ((tag = g_queue_pop_tail(q))) |
3140 closers = g_list_remove(closers, span); | 3340 g_string_append(str, tag_to_html_end(GTK_TEXT_TAG(tag))); |
3141 | 3341 |
3142 } | 3342 g_queue_free(q); |
3343 g_queue_free(r); | |
3143 return g_string_free(str, FALSE); | 3344 return g_string_free(str, FALSE); |
3144 } | 3345 } |
3145 | 3346 |
3146 void gtk_imhtml_close_tags(GtkIMHtml *imhtml) | 3347 void gtk_imhtml_close_tags(GtkIMHtml *imhtml) |
3147 { | 3348 { |
3349 GtkTextIter iter; | |
3148 | 3350 |
3149 if (imhtml->edit.bold) | 3351 if (imhtml->edit.bold) |
3150 gtk_imhtml_toggle_bold(imhtml); | 3352 gtk_imhtml_toggle_bold(imhtml); |
3151 | 3353 |
3152 if (imhtml->edit.italic) | 3354 if (imhtml->edit.italic) |
3162 gtk_imhtml_toggle_backcolor(imhtml, NULL); | 3364 gtk_imhtml_toggle_backcolor(imhtml, NULL); |
3163 | 3365 |
3164 if (imhtml->edit.fontface) | 3366 if (imhtml->edit.fontface) |
3165 gtk_imhtml_toggle_fontface(imhtml, NULL); | 3367 gtk_imhtml_toggle_fontface(imhtml, NULL); |
3166 | 3368 |
3167 if (imhtml->edit.sizespan) | 3369 imhtml->edit.fontsize = 0; |
3168 gtk_imhtml_font_set_size(imhtml, -1); | 3370 |
3371 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); | |
3372 gtk_text_buffer_remove_all_tags(imhtml->text_buffer, &iter, &iter); | |
3169 | 3373 |
3170 } | 3374 } |
3171 | 3375 |
3172 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) | 3376 char *gtk_imhtml_get_markup(GtkIMHtml *imhtml) |
3173 { | 3377 { |
3176 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | 3380 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); |
3177 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | 3381 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); |
3178 return gtk_imhtml_get_markup_range(imhtml, &start, &end); | 3382 return gtk_imhtml_get_markup_range(imhtml, &start, &end); |
3179 } | 3383 } |
3180 | 3384 |
3181 char *gtk_imhtml_get_text(GtkIMHtml *imhtml) | 3385 char **gtk_imhtml_get_markup_lines(GtkIMHtml *imhtml) |
3386 { | |
3387 int i, j, lines; | |
3388 GtkTextIter start, end; | |
3389 char **ret; | |
3390 | |
3391 lines = gtk_text_buffer_get_line_count(imhtml->text_buffer); | |
3392 ret = g_new0(char *, lines + 1); | |
3393 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start); | |
3394 end = start; | |
3395 gtk_text_iter_forward_to_line_end(&end); | |
3396 | |
3397 for (i = 0, j = 0; i < lines; i++) { | |
3398 ret[j] = gtk_imhtml_get_markup_range(imhtml, &start, &end); | |
3399 if (ret[j] != NULL) | |
3400 j++; | |
3401 gtk_text_iter_forward_line(&start); | |
3402 end = start; | |
3403 gtk_text_iter_forward_to_line_end(&end); | |
3404 } | |
3405 | |
3406 return ret; | |
3407 } | |
3408 | |
3409 char *gtk_imhtml_get_text(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *stop) | |
3182 { | 3410 { |
3183 GString *str = g_string_new(""); | 3411 GString *str = g_string_new(""); |
3184 GtkTextIter iter, end; | 3412 GtkTextIter iter, end; |
3185 gunichar c; | 3413 gunichar c; |
3186 | 3414 |
3187 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); | 3415 if (start == NULL) |
3188 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | 3416 gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter); |
3417 else | |
3418 iter = *start; | |
3419 | |
3420 if (stop == NULL) | |
3421 gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end); | |
3422 else | |
3423 end = *stop; | |
3424 | |
3425 gtk_text_iter_order(&iter, &end); | |
3189 | 3426 |
3190 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, &end)) { | 3427 while ((c = gtk_text_iter_get_char(&iter)) != 0 && !gtk_text_iter_equal(&iter, &end)) { |
3191 if (c == 0xFFFC) { | 3428 if (c == 0xFFFC) { |
3192 GtkTextChildAnchor* anchor = gtk_text_iter_get_child_anchor(&iter); | 3429 GtkTextChildAnchor* anchor; |
3193 char *text = g_object_get_data(G_OBJECT(anchor), "text_tag"); | 3430 char *text = NULL; |
3194 str = g_string_append(str, text); | 3431 |
3432 anchor = gtk_text_iter_get_child_anchor(&iter); | |
3433 if (anchor) | |
3434 text = g_object_get_data(G_OBJECT(anchor), "text_tag"); | |
3435 if (text) | |
3436 str = g_string_append(str, text); | |
3195 } else { | 3437 } else { |
3196 g_string_append_unichar(str, c); | 3438 g_string_append_unichar(str, c); |
3197 } | 3439 } |
3198 gtk_text_iter_forward_char(&iter); | 3440 gtk_text_iter_forward_char(&iter); |
3199 } | 3441 } |