pidgin/gtkimhtml.c

branch
cpw.qulogic.gtk3
changeset 32412
f718420c4932
parent 31208
1dccb087d00a
parent 32410
3d78feb90b9c
child 32413
00ad036bdf3d
equal deleted inserted replaced
31209:39b9c5ca504e 32412:f718420c4932
408 imhtml->old_rect = rect; 408 imhtml->old_rect = rect;
409 parent_size_allocate(widget, alloc); 409 parent_size_allocate(widget, alloc);
410 410
411 /* Don't scroll here if we're in the middle of a smooth scroll */ 411 /* Don't scroll here if we're in the middle of a smooth scroll */
412 if (scroll && imhtml->scroll_time == NULL && 412 if (scroll && imhtml->scroll_time == NULL &&
413 GTK_WIDGET_REALIZED(imhtml)) 413 gtk_widget_get_realized(GTK_WIDGET(imhtml)))
414 gtk_imhtml_scroll_to_end(imhtml, FALSE); 414 gtk_imhtml_scroll_to_end(imhtml, FALSE);
415 } 415 }
416 416
417 #define DEFAULT_SEND_COLOR "#204a87" 417 #define DEFAULT_SEND_COLOR "#204a87"
418 #define DEFAULT_RECV_COLOR "#cc0000" 418 #define DEFAULT_RECV_COLOR "#cc0000"
497 497
498 static gint 498 static gint
499 gtk_imhtml_tip_paint (GtkIMHtml *imhtml) 499 gtk_imhtml_tip_paint (GtkIMHtml *imhtml)
500 { 500 {
501 PangoLayout *layout; 501 PangoLayout *layout;
502 cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(imhtml->tip_window));
502 503
503 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); 504 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE);
504 505
505 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); 506 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip);
506 507
507 gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, 508 gtk_paint_flat_box (gtk_widget_get_style(imhtml->tip_window), cr,
508 GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, 509 GTK_STATE_NORMAL, GTK_SHADOW_OUT, imhtml->tip_window, "tooltip",
509 "tooltip", 0, 0, -1, -1); 510 0, 0, -1, -1);
510 511
511 gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, 512 gtk_paint_layout (gtk_widget_get_style(imhtml->tip_window), cr,
512 FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); 513 GTK_STATE_NORMAL, TRUE, imhtml->tip_window, NULL, 4, 4, layout);
513 514
515 cairo_destroy(cr);
514 g_object_unref(layout); 516 g_object_unref(layout);
515 return FALSE; 517 return FALSE;
516 } 518 }
517 519
518 static gint 520 static gint
520 { 522 {
521 GtkIMHtml *imhtml = data; 523 GtkIMHtml *imhtml = data;
522 PangoFontMetrics *font_metrics; 524 PangoFontMetrics *font_metrics;
523 PangoLayout *layout; 525 PangoLayout *layout;
524 PangoFont *font; 526 PangoFont *font;
525 527 GtkStyle *style = gtk_widget_get_style(imhtml->tip_window);
528 GtkAllocation allocation;
526 gint gap, x, y, h, w, scr_w, baseline_skip; 529 gint gap, x, y, h, w, scr_w, baseline_skip;
527 530
528 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); 531 g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE);
529 532
530 if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { 533 gtk_widget_get_allocation(GTK_WIDGET(imhtml), &allocation);
534
535 if (!imhtml->tip || !gtk_widget_is_drawable(GTK_WIDGET(imhtml))) {
531 imhtml->tip_timer = 0; 536 imhtml->tip_timer = 0;
532 return FALSE; 537 return FALSE;
533 } 538 }
534 539
535 if (imhtml->tip_window){ 540 if (imhtml->tip_window){
549 G_CALLBACK (gtk_imhtml_tip_paint), imhtml); 554 G_CALLBACK (gtk_imhtml_tip_paint), imhtml);
550 555
551 gtk_widget_ensure_style (imhtml->tip_window); 556 gtk_widget_ensure_style (imhtml->tip_window);
552 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); 557 layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip);
553 font = pango_context_load_font(pango_layout_get_context(layout), 558 font = pango_context_load_font(pango_layout_get_context(layout),
554 imhtml->tip_window->style->font_desc); 559 style->font_desc);
555 560
556 if (font == NULL) { 561 if (font == NULL) {
557 char *tmp = pango_font_description_to_string( 562 char *tmp = pango_font_description_to_string(style->font_desc);
558 imhtml->tip_window->style->font_desc);
559 563
560 purple_debug(PURPLE_DEBUG_ERROR, "gtk_imhtml_tip", 564 purple_debug(PURPLE_DEBUG_ERROR, "gtk_imhtml_tip",
561 "pango_context_load_font() couldn't load font: '%s'\n", 565 "pango_context_load_font() couldn't load font: '%s'\n",
562 tmp); 566 tmp);
563 g_free(tmp); 567 g_free(tmp);
578 pango_font_metrics_get_descent(font_metrics)); 582 pango_font_metrics_get_descent(font_metrics));
579 w = 8 + scr_w; 583 w = 8 + scr_w;
580 h = 8 + baseline_skip; 584 h = 8 + baseline_skip;
581 585
582 gdk_window_get_pointer (NULL, &x, &y, NULL); 586 gdk_window_get_pointer (NULL, &x, &y, NULL);
583 if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) 587 if ((!gtk_widget_get_has_window(GTK_WIDGET(imhtml))))
584 y += GTK_WIDGET(imhtml)->allocation.y; 588 y += allocation.y;
585 589
586 scr_w = gdk_screen_width(); 590 scr_w = gdk_screen_width();
587 591
588 x -= ((w >> 1) + 4); 592 x -= ((w >> 1) + 4);
589 593
619 gboolean hand = TRUE; 623 gboolean hand = TRUE;
620 GdkCursor *cursor = NULL; 624 GdkCursor *cursor = NULL;
621 625
622 oldprelit_tag = GTK_IMHTML(imhtml)->prelit_tag; 626 oldprelit_tag = GTK_IMHTML(imhtml)->prelit_tag;
623 627
624 gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); 628 gdk_window_get_pointer(gtk_widget_get_window(GTK_WIDGET(imhtml)), NULL, NULL, NULL);
625 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, 629 gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET,
626 event->x, event->y, &x, &y); 630 event->x, event->y, &x, &y);
627 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); 631 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y);
628 tags = gtk_text_iter_get_tags(&iter); 632 tags = gtk_text_iter_get_tags(&iter);
629 633
747 751
748 /* propagate the event normally */ 752 /* propagate the event normally */
749 return FALSE; 753 return FALSE;
750 } 754 }
751 755
756 /* TODO: I think this can be removed for GTK+ 3.0... */
757 #if 0
752 static gint 758 static gint
753 gtk_imhtml_expose_event (GtkWidget *widget, 759 gtk_imhtml_expose_event (GtkWidget *widget,
754 GdkEventExpose *event) 760 GdkEventExpose *event)
755 { 761 {
756 GtkTextIter start, end, cur; 762 GtkTextIter start, end, cur;
774 780
775 if (GTK_IMHTML(widget)->edit.background) { 781 if (GTK_IMHTML(widget)->edit.background) {
776 gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor); 782 gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor);
777 gdk_cairo_set_source_color(cr, &gcolor); 783 gdk_cairo_set_source_color(cr, &gcolor);
778 } else { 784 } else {
779 gdk_cairo_set_source_color(cr, &(widget->style->base[GTK_WIDGET_STATE(widget)])); 785 gdk_cairo_set_source_color(cr,
786 &(gtk_widget_get_style(widget)->base[gtk_widget_get_state(widget)]));
780 } 787 }
781 788
782 cairo_rectangle(cr, 789 cairo_rectangle(cr,
783 visible_rect.x, visible_rect.y, 790 visible_rect.x, visible_rect.y,
784 visible_rect.width, visible_rect.height); 791 visible_rect.width, visible_rect.height);
880 return (* GTK_WIDGET_CLASS (parent_class)->expose_event) 887 return (* GTK_WIDGET_CLASS (parent_class)->expose_event)
881 (widget, event); 888 (widget, event);
882 889
883 return FALSE; 890 return FALSE;
884 } 891 }
892 #endif
885 893
886 894
887 static void paste_unformatted_cb(GtkMenuItem *menu, GtkIMHtml *imhtml) 895 static void paste_unformatted_cb(GtkMenuItem *menu, GtkIMHtml *imhtml)
888 { 896 {
889 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD); 897 GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD);
1156 1164
1157 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) 1165 static void paste_received_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data)
1158 { 1166 {
1159 char *text; 1167 char *text;
1160 GtkIMHtml *imhtml = data; 1168 GtkIMHtml *imhtml = data;
1161 1169 gint length = gtk_selection_data_get_length(selection_data);
1170
1162 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) 1171 if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml)))
1163 return; 1172 return;
1164 1173
1165 if (imhtml->wbfo || selection_data->length <= 0) { 1174 if (imhtml->wbfo || length <= 0) {
1166 gtk_clipboard_request_text(clipboard, paste_plaintext_received_cb, imhtml); 1175 gtk_clipboard_request_text(clipboard, paste_plaintext_received_cb, imhtml);
1167 return; 1176 return;
1168 } else { 1177 } else {
1169 #if 0 1178 #if 0
1170 /* Here's some debug code, for figuring out what sent to us over the clipboard. */ 1179 /* Here's some debug code, for figuring out what sent to us over the clipboard. */
1184 } 1193 }
1185 printf("\n"); 1194 printf("\n");
1186 } 1195 }
1187 #endif 1196 #endif
1188 1197
1189 text = g_malloc(selection_data->length + 1); 1198 text = g_malloc(length + 1);
1190 memcpy(text, selection_data->data, selection_data->length); 1199 memcpy(text, gtk_selection_data_get_data(selection_data), length);
1191 /* Make sure the paste data is null-terminated. Given that 1200 /* Make sure the paste data is null-terminated. Given that
1192 * we're passed length (but assume later that it is 1201 * we're passed length (but assume later that it is
1193 * null-terminated), this seems sensible to me. 1202 * null-terminated), this seems sensible to me.
1194 */ 1203 */
1195 text[selection_data->length] = '\0'; 1204 text[length] = '\0';
1196 } 1205 }
1197 1206
1198 #ifdef _WIN32 1207 #ifdef _WIN32
1199 if (gtk_selection_data_get_data_type(selection_data) == gdk_atom_intern("HTML Format", FALSE)) { 1208 if (gtk_selection_data_get_data_type(selection_data) == gdk_atom_intern("HTML Format", FALSE)) {
1200 char *tmp = clipboard_win32_to_html(text); 1209 char *tmp = clipboard_win32_to_html(text);
1201 g_free(text); 1210 g_free(text);
1202 text = tmp; 1211 text = tmp;
1203 } 1212 }
1204 #endif 1213 #endif
1205 1214
1206 if (selection_data->length >= 2 && 1215 if (length >= 2 &&
1207 (*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe)) { 1216 (*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe)) {
1208 /* This is UTF-16 */ 1217 /* This is UTF-16 */
1209 char *utf8 = utf16_to_utf8_with_bom_check(text, selection_data->length); 1218 char *utf8 = utf16_to_utf8_with_bom_check(text, length);
1210 g_free(text); 1219 g_free(text);
1211 text = utf8; 1220 text = utf8;
1212 if (!text) { 1221 if (!text) {
1213 purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in paste_received_cb\n"); 1222 purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in paste_received_cb\n");
1214 return; 1223 return;
1565 klass->undo = gtk_imhtml_undo; 1574 klass->undo = gtk_imhtml_undo;
1566 klass->redo = gtk_imhtml_redo; 1575 klass->redo = gtk_imhtml_redo;
1567 1576
1568 gobject_class->finalize = gtk_imhtml_finalize; 1577 gobject_class->finalize = gtk_imhtml_finalize;
1569 widget_class->drag_motion = gtk_text_view_drag_motion; 1578 widget_class->drag_motion = gtk_text_view_drag_motion;
1570 widget_class->expose_event = gtk_imhtml_expose_event; 1579 /* TODO: I _think_ this should be removed for GTK+ 3.0 */
1580 /*widget_class->expose_event = gtk_imhtml_expose_event;*/
1571 parent_size_allocate = widget_class->size_allocate; 1581 parent_size_allocate = widget_class->size_allocate;
1572 widget_class->size_allocate = gtk_imhtml_size_allocate; 1582 widget_class->size_allocate = gtk_imhtml_size_allocate;
1573 parent_style_set = widget_class->style_set; 1583 parent_style_set = widget_class->style_set;
1574 widget_class->style_set = gtk_imhtml_style_set; 1584 widget_class->style_set = gtk_imhtml_style_set;
1575 1585
1627 _("Enable typing notification"), 1637 _("Enable typing notification"),
1628 _("Enable typing notification"), 1638 _("Enable typing notification"),
1629 TRUE, G_PARAM_READABLE)); 1639 TRUE, G_PARAM_READABLE));
1630 1640
1631 binding_set = gtk_binding_set_by_class (parent_class); 1641 binding_set = gtk_binding_set_by_class (parent_class);
1632 gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD); 1642 gtk_binding_entry_add_signal (binding_set, GDK_KEY_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD);
1633 gtk_binding_entry_add_signal (binding_set, GDK_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC); 1643 gtk_binding_entry_add_signal (binding_set, GDK_KEY_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC);
1634 gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE); 1644 gtk_binding_entry_add_signal (binding_set, GDK_KEY_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE);
1635 gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); 1645 gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW);
1636 gtk_binding_entry_add_signal (binding_set, GDK_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); 1646 gtk_binding_entry_add_signal (binding_set, GDK_KEY_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW);
1637 gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK); 1647 gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK);
1638 binding_set = gtk_binding_set_by_class(klass); 1648 binding_set = gtk_binding_set_by_class(klass);
1639 gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); 1649 gtk_binding_entry_add_signal (binding_set, GDK_KEY_r, GDK_CONTROL_MASK, "format_function_clear", 0);
1640 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); 1650 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "message_send", 0);
1641 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); 1651 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "message_send", 0);
1642 gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); 1652 gtk_binding_entry_add_signal (binding_set, GDK_KEY_z, GDK_CONTROL_MASK, "undo", 0);
1643 gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); 1653 gtk_binding_entry_add_signal (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0);
1644 gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); 1654 gtk_binding_entry_add_signal (binding_set, GDK_KEY_F14, 0, "undo", 0);
1645 gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text"); 1655 gtk_binding_entry_add_signal(binding_set, GDK_KEY_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text");
1646 } 1656 }
1647 1657
1648 static void gtk_imhtml_init (GtkIMHtml *imhtml) 1658 static void gtk_imhtml_init (GtkIMHtml *imhtml)
1649 { 1659 {
1650 imhtml->text_buffer = gtk_text_buffer_new(NULL); 1660 imhtml->text_buffer = gtk_text_buffer_new(NULL);
1867 1877
1868 if (gtk_drag_dest_find_target (widget, context, NULL) == GDK_NONE) { 1878 if (gtk_drag_dest_find_target (widget, context, NULL) == GDK_NONE) {
1869 /* can't accept any of the offered targets */ 1879 /* can't accept any of the offered targets */
1870 } else { 1880 } else {
1871 GtkWidget *source_widget; 1881 GtkWidget *source_widget;
1872 suggested_action = context->suggested_action; 1882 suggested_action = gdk_drag_context_get_suggested_action(context);
1873 source_widget = gtk_drag_get_source_widget (context); 1883 source_widget = gtk_drag_get_source_widget (context);
1874 if (source_widget == widget) { 1884 if (source_widget == widget) {
1875 /* Default to MOVE, unless the user has 1885 /* Default to MOVE, unless the user has
1876 * pressed ctrl or alt to affect available actions 1886 * pressed ctrl or alt to affect available actions
1877 */ 1887 */
1878 if ((context->actions & GDK_ACTION_MOVE) != 0) 1888 if ((gdk_drag_context_get_actions(context) & GDK_ACTION_MOVE) != 0)
1879 suggested_action = GDK_ACTION_MOVE; 1889 suggested_action = GDK_ACTION_MOVE;
1880 } 1890 }
1881 } 1891 }
1882 1892
1883 gdk_drag_status (context, suggested_action, time); 1893 gdk_drag_status (context, suggested_action, time);
1905 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, 1915 gtk_imhtml_link_drag_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y,
1906 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml) 1916 GtkSelectionData *sd, guint info, guint t, GtkIMHtml *imhtml)
1907 { 1917 {
1908 gchar **links; 1918 gchar **links;
1909 gchar *link; 1919 gchar *link;
1910 char *text = (char *)sd->data; 1920 char *text = (char *) gtk_selection_data_get_data(sd);
1911 GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer); 1921 GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer);
1912 GtkTextIter iter; 1922 GtkTextIter iter;
1913 gint i = 0; 1923 gint i = 0;
1924 gint length = gtk_selection_data_get_length(sd);
1914 1925
1915 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); 1926 gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark);
1916 1927
1917 if(gtk_imhtml_get_editable(imhtml) && sd->data){ 1928 if(gtk_imhtml_get_editable(imhtml) && text){
1918 switch (info) { 1929 switch (info) {
1919 case GTK_IMHTML_DRAG_URL: 1930 case GTK_IMHTML_DRAG_URL:
1920 /* TODO: Is it really ok to change sd->data...? */ 1931 /* TODO: Is it really ok to change sd->data...? */
1921 purple_str_strip_char((char *)sd->data, '\r'); 1932 purple_str_strip_char(text, '\r');
1922 1933
1923 links = g_strsplit((char *)sd->data, "\n", 0); 1934 links = g_strsplit(text, "\n", 0);
1924 while((link = links[i]) != NULL){ 1935 while((link = links[i]) != NULL){
1925 if (gtk_imhtml_is_protocol(link)) { 1936 if (gtk_imhtml_is_protocol(link)) {
1926 gchar *label; 1937 gchar *label;
1927 1938
1928 if(links[i + 1]) 1939 if(links[i + 1])
1957 * the string as utf8 and if that fails we assume it is ucs2 1968 * the string as utf8 and if that fails we assume it is ucs2
1958 * 1969 *
1959 * See also the comment on text/html here: 1970 * See also the comment on text/html here:
1960 * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html 1971 * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html
1961 */ 1972 */
1962 if (sd->length >= 2 && !g_utf8_validate(text, sd->length - 1, NULL)) { 1973 if (length >= 2 && !g_utf8_validate(text, length - 1, NULL)) {
1963 utf8 = utf16_to_utf8_with_bom_check(text, sd->length); 1974 utf8 = utf16_to_utf8_with_bom_check(text, length);
1964 1975
1965 if (!utf8) { 1976 if (!utf8) {
1966 purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in drag_rcv_cb\n"); 1977 purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in drag_rcv_cb\n");
1967 return; 1978 return;
1968 } 1979 }
1987 break; 1998 break;
1988 default: 1999 default:
1989 gtk_drag_finish(dc, FALSE, FALSE, t); 2000 gtk_drag_finish(dc, FALSE, FALSE, t);
1990 return; 2001 return;
1991 } 2002 }
1992 gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); 2003 gtk_drag_finish(dc, TRUE,
2004 (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t);
1993 } else { 2005 } else {
1994 gtk_drag_finish(dc, FALSE, FALSE, t); 2006 gtk_drag_finish(dc, FALSE, FALSE, t);
1995 } 2007 }
1996 } 2008 }
1997 2009
2518 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. 2530 * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom.
2519 */ 2531 */
2520 static gboolean smooth_scroll_cb(gpointer data) 2532 static gboolean smooth_scroll_cb(gpointer data)
2521 { 2533 {
2522 GtkIMHtml *imhtml = data; 2534 GtkIMHtml *imhtml = data;
2523 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; 2535 GtkAdjustment *adj = gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(imhtml));
2524 gdouble max_val = adj->upper - adj->page_size; 2536 gdouble max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj);
2525 gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3); 2537 gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3);
2526 2538
2527 g_return_val_if_fail(imhtml->scroll_time != NULL, FALSE); 2539 g_return_val_if_fail(imhtml->scroll_time != NULL, FALSE);
2528 2540
2529 if (g_timer_elapsed(imhtml->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) { 2541 if (g_timer_elapsed(imhtml->scroll_time, NULL) > MAX_SCROLL_TIME || scroll_val >= max_val) {
2542 } 2554 }
2543 2555
2544 static gboolean scroll_idle_cb(gpointer data) 2556 static gboolean scroll_idle_cb(gpointer data)
2545 { 2557 {
2546 GtkIMHtml *imhtml = data; 2558 GtkIMHtml *imhtml = data;
2547 GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; 2559 GtkAdjustment *adj = gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(imhtml));
2548 if(adj) { 2560 if(adj) {
2549 gtk_adjustment_set_value(adj, adj->upper - adj->page_size); 2561 gtk_adjustment_set_value(adj, gtk_adjustment_get_upper(adj) -
2562 gtk_adjustment_get_page_size(adj));
2550 } 2563 }
2551 imhtml->scroll_src = 0; 2564 imhtml->scroll_src = 0;
2552 return FALSE; 2565 return FALSE;
2553 } 2566 }
2554 2567
4184 4197
4185 tags = gtk_text_iter_get_tags(i); 4198 tags = gtk_text_iter_get_tags(i);
4186 4199
4187 for (l = tags; l; l = l->next) { 4200 for (l = tags; l; l = l->next) {
4188 GtkTextTag *tag = l->data; 4201 GtkTextTag *tag = l->data;
4189 4202 gchar *name;
4190 if (tag->name && !strncmp(tag->name, prefix, len)) 4203
4204 g_object_get(G_OBJECT(tag), "name", &name, NULL);
4205
4206 if (name && !strncmp(name, prefix, len))
4191 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); 4207 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e);
4208
4209 g_free(name);
4192 } 4210 }
4193 4211
4194 g_slist_free(tags); 4212 g_slist_free(tags);
4195 4213
4196 if (homo) 4214 if (homo)
4202 if (gtk_text_iter_begins_tag(&iter, NULL)) { 4220 if (gtk_text_iter_begins_tag(&iter, NULL)) {
4203 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE); 4221 tags = gtk_text_iter_get_toggled_tags(&iter, TRUE);
4204 4222
4205 for (l = tags; l; l = l->next) { 4223 for (l = tags; l; l = l->next) {
4206 GtkTextTag *tag = l->data; 4224 GtkTextTag *tag = l->data;
4207 4225 gchar *name;
4208 if (tag->name && !strncmp(tag->name, prefix, len)) 4226
4227 g_object_get(G_OBJECT(tag), "name", &name, NULL);
4228
4229 if (name && !strncmp(name, prefix, len))
4209 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); 4230 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e);
4210 } 4231
4232 g_free(name);
4233 }
4211 4234
4212 g_slist_free(tags); 4235 g_slist_free(tags);
4213 } 4236 }
4214 } 4237 }
4215 } 4238 }
4325 if (tag && /* Remove the formatting only if */ 4348 if (tag && /* Remove the formatting only if */
4326 gtk_text_iter_starts_word(start) && /* beginning of a word */ 4349 gtk_text_iter_starts_word(start) && /* beginning of a word */
4327 gtk_text_iter_begins_tag(start, tag) && /* the tag starts with the selection */ 4350 gtk_text_iter_begins_tag(start, tag) && /* the tag starts with the selection */
4328 (!gtk_text_iter_has_tag(end, tag) || /* the tag ends within the selection */ 4351 (!gtk_text_iter_has_tag(end, tag) || /* the tag ends within the selection */
4329 gtk_text_iter_ends_tag(end, tag))) { 4352 gtk_text_iter_ends_tag(end, tag))) {
4353 gchar *name;
4354
4355 g_object_get(G_OBJECT(tag), "name", &name, NULL);
4330 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, start, end); 4356 gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, start, end);
4331 if (tag->name && 4357
4332 strncmp(tag->name, "LINK ", 5) == 0 && imhtml->edit.link) { 4358 if (name && strncmp(name, "LINK ", 5) == 0 && imhtml->edit.link) {
4333 gtk_imhtml_toggle_link(imhtml, NULL); 4359 gtk_imhtml_toggle_link(imhtml, NULL);
4334 } 4360 }
4361
4362 g_free(name);
4335 } 4363 }
4336 } 4364 }
4337 g_slist_free(tags); 4365 g_slist_free(tags);
4338 } 4366 }
4339 4367
4551 else 4579 else
4552 tags = gtk_text_iter_get_tags(&iter); 4580 tags = gtk_text_iter_get_tags(&iter);
4553 4581
4554 for (l = tags; l != NULL; l = l->next) { 4582 for (l = tags; l != NULL; l = l->next) {
4555 GtkTextTag *tag = GTK_TEXT_TAG(l->data); 4583 GtkTextTag *tag = GTK_TEXT_TAG(l->data);
4556 4584 gchar *name;
4557 if (tag->name) { 4585
4558 if (strcmp(tag->name, "BOLD") == 0) 4586 g_object_get(G_OBJECT(tag), "name", &name, NULL);
4587
4588 if (name) {
4589 if (strcmp(name, "BOLD") == 0)
4559 imhtml->edit.bold = TRUE; 4590 imhtml->edit.bold = TRUE;
4560 else if (strcmp(tag->name, "ITALICS") == 0) 4591 else if (strcmp(name, "ITALICS") == 0)
4561 imhtml->edit.italic = TRUE; 4592 imhtml->edit.italic = TRUE;
4562 else if (strcmp(tag->name, "UNDERLINE") == 0) 4593 else if (strcmp(name, "UNDERLINE") == 0)
4563 imhtml->edit.underline = TRUE; 4594 imhtml->edit.underline = TRUE;
4564 else if (strcmp(tag->name, "STRIKE") == 0) 4595 else if (strcmp(name, "STRIKE") == 0)
4565 imhtml->edit.strike = TRUE; 4596 imhtml->edit.strike = TRUE;
4566 else if (strncmp(tag->name, "FORECOLOR ", 10) == 0) 4597 else if (strncmp(name, "FORECOLOR ", 10) == 0)
4567 imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); 4598 imhtml->edit.forecolor = g_strdup(&(name)[10]);
4568 else if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) 4599 else if (strncmp(name, "BACKCOLOR ", 10) == 0)
4569 imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); 4600 imhtml->edit.backcolor = g_strdup(&(name)[10]);
4570 else if (strncmp(tag->name, "FONT FACE ", 10) == 0) 4601 else if (strncmp(name, "FONT FACE ", 10) == 0)
4571 imhtml->edit.fontface = g_strdup(&(tag->name)[10]); 4602 imhtml->edit.fontface = g_strdup(&(name)[10]);
4572 else if (strncmp(tag->name, "FONT SIZE ", 10) == 0) 4603 else if (strncmp(name, "FONT SIZE ", 10) == 0)
4573 imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); 4604 imhtml->edit.fontsize = strtol(&(name)[10], NULL, 10);
4574 else if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) 4605 else if ((strncmp(name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter))
4575 imhtml->edit.link = tag; 4606 imhtml->edit.link = tag;
4576 } 4607 }
4608
4609 g_free(name);
4577 } 4610 }
4578 4611
4579 g_slist_free(tags); 4612 g_slist_free(tags);
4580 } 4613 }
4581 4614
4862 gtk_text_buffer_begin_user_action(imhtml->text_buffer); 4895 gtk_text_buffer_begin_user_action(imhtml->text_buffer);
4863 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter); 4896 gtk_imhtml_insert_smiley_at_iter(imhtml, sml, smiley, &iter);
4864 gtk_text_buffer_end_user_action(imhtml->text_buffer); 4897 gtk_text_buffer_end_user_action(imhtml->text_buffer);
4865 } 4898 }
4866 4899
4900 /* TODO: I think this can be removed for GTK+ 3.0... */
4901 #if 0
4867 static gboolean 4902 static gboolean
4868 image_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) 4903 image_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
4869 { 4904 {
4870 GTK_WIDGET_CLASS(GTK_WIDGET_GET_CLASS(widget))->expose_event(widget, event); 4905 GTK_WIDGET_CLASS(GTK_WIDGET_GET_CLASS(widget))->expose_event(widget, event);
4871 4906
4872 return TRUE; 4907 return TRUE;
4873 } 4908 }
4909 #endif
4874 4910
4875 /* In case the smiley gets removed from the imhtml before it gets removed from the queue */ 4911 /* In case the smiley gets removed from the imhtml before it gets removed from the queue */
4876 static void animated_smiley_destroy_cb(GtkObject *widget, GtkIMHtml *imhtml) 4912 static void animated_smiley_destroy_cb(GtkWidget *widget, GtkIMHtml *imhtml)
4877 { 4913 {
4878 GList *l = imhtml->animations->head; 4914 GList *l = imhtml->animations->head;
4879 while (l) { 4915 while (l) {
4880 GList *next = l->next; 4916 GList *next = l->next;
4881 if (l->data == widget) { 4917 if (l->data == widget) {
4966 5002
4967 /* This catches the expose events generated by animated 5003 /* This catches the expose events generated by animated
4968 * images, and ensures that they are handled by the image 5004 * images, and ensures that they are handled by the image
4969 * itself, without propagating to the textview and causing 5005 * itself, without propagating to the textview and causing
4970 * a complete refresh */ 5006 * a complete refresh */
5007 /* TODO: I think this should be removed for GTK+ 3.0?
4971 g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL); 5008 g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL);
4972 5009 */
5010
4973 gtk_widget_show(icon); 5011 gtk_widget_show(icon);
4974 if (ebox) 5012 if (ebox)
4975 gtk_container_add(GTK_CONTAINER(ebox), icon); 5013 gtk_container_add(GTK_CONTAINER(ebox), icon);
4976 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor); 5014 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), ebox ? ebox : icon, anchor);
4977 5015
5068 imhtml->scalables = g_list_append(imhtml->scalables, sd); 5106 imhtml->scalables = g_list_append(imhtml->scalables, sd);
5069 } 5107 }
5070 5108
5071 static const gchar *tag_to_html_start(GtkTextTag *tag) 5109 static const gchar *tag_to_html_start(GtkTextTag *tag)
5072 { 5110 {
5073 const gchar *name;
5074 static gchar buf[1024]; 5111 static gchar buf[1024];
5075 5112 gchar *name;
5076 name = tag->name; 5113
5114 g_object_get(G_OBJECT(tag), "name", &name, NULL);
5077 g_return_val_if_fail(name != NULL, ""); 5115 g_return_val_if_fail(name != NULL, "");
5078 5116
5079 if (strcmp(name, "BOLD") == 0) { 5117 if (strcmp(name, "BOLD") == 0) {
5118 g_free(name);
5080 return "<b>"; 5119 return "<b>";
5081 } else if (strcmp(name, "ITALICS") == 0) { 5120 } else if (strcmp(name, "ITALICS") == 0) {
5121 g_free(name);
5082 return "<i>"; 5122 return "<i>";
5083 } else if (strcmp(name, "UNDERLINE") == 0) { 5123 } else if (strcmp(name, "UNDERLINE") == 0) {
5084 return "<u>"; 5124 g_free(name);
5125 return "<u>";
5085 } else if (strcmp(name, "STRIKE") == 0) { 5126 } else if (strcmp(name, "STRIKE") == 0) {
5086 return "<s>"; 5127 g_free(name);
5128 return "<s>";
5087 } else if (strncmp(name, "LINK ", 5) == 0) { 5129 } else if (strncmp(name, "LINK ", 5) == 0) {
5088 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); 5130 char *tmp = g_object_get_data(G_OBJECT(tag), "link_url");
5089 if (tmp) { 5131
5132 g_free(name);
5133
5134 if (tmp) {
5090 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); 5135 g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp);
5091 buf[sizeof(buf)-1] = '\0'; 5136 buf[sizeof(buf)-1] = '\0';
5092 return buf; 5137 return buf;
5093 } else { 5138 } else {
5094 return ""; 5139 return "";
5095 } 5140 }
5096 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { 5141 } else if (strncmp(name, "FORECOLOR ", 10) == 0) {
5097 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); 5142 g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]);
5098 return buf; 5143
5144 g_free(name);
5145
5146 return buf;
5099 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { 5147 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) {
5100 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); 5148 g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]);
5101 return buf; 5149 g_free(name);
5150
5151 return buf;
5102 } else if (strncmp(name, "BACKGROUND ", 10) == 0) { 5152 } else if (strncmp(name, "BACKGROUND ", 10) == 0) {
5103 g_snprintf(buf, sizeof(buf), "<body bgcolor=\"%s\">", &name[11]); 5153 g_snprintf(buf, sizeof(buf), "<body bgcolor=\"%s\">", &name[11]);
5104 return buf; 5154 g_free(name);
5155
5156 return buf;
5105 } else if (strncmp(name, "FONT FACE ", 10) == 0) { 5157 } else if (strncmp(name, "FONT FACE ", 10) == 0) {
5106 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); 5158 g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]);
5107 return buf; 5159 g_free(name);
5160
5161 return buf;
5108 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { 5162 } else if (strncmp(name, "FONT SIZE ", 10) == 0) {
5109 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); 5163 g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]);
5110 return buf; 5164 g_free(name);
5165
5166 return buf;
5111 } else { 5167 } else {
5112 char *str = buf; 5168 char *str = buf;
5113 gboolean isset; 5169 gboolean isset;
5114 int ivalue = 0; 5170 int ivalue = 0;
5115 GdkColor *color = NULL; 5171 GdkColor *color = NULL;
5167 empty = FALSE; 5223 empty = FALSE;
5168 } 5224 }
5169 } 5225 }
5170 5226
5171 g_snprintf(str, sizeof(buf) - (str - buf), "'>"); 5227 g_snprintf(str, sizeof(buf) - (str - buf), "'>");
5172 5228 g_free(name);
5229
5173 return (empty ? "" : buf); 5230 return (empty ? "" : buf);
5174 } 5231 }
5175 } 5232 }
5176 5233
5177 static const gchar *tag_to_html_end(GtkTextTag *tag) 5234 static const gchar *tag_to_html_end(GtkTextTag *tag)
5178 { 5235 {
5179 const gchar *name; 5236 gchar *name;
5180 5237
5181 name = tag->name; 5238 g_object_get(G_OBJECT(tag), "name", &name, NULL);
5182 g_return_val_if_fail(name != NULL, ""); 5239 g_return_val_if_fail(name != NULL, "");
5183 5240
5184 if (strcmp(name, "BOLD") == 0) { 5241 if (strcmp(name, "BOLD") == 0) {
5242 g_free(name);
5185 return "</b>"; 5243 return "</b>";
5186 } else if (strcmp(name, "ITALICS") == 0) { 5244 } else if (strcmp(name, "ITALICS") == 0) {
5187 return "</i>"; 5245 g_free(name);
5246 return "</i>";
5188 } else if (strcmp(name, "UNDERLINE") == 0) { 5247 } else if (strcmp(name, "UNDERLINE") == 0) {
5189 return "</u>"; 5248 g_free(name);
5249 return "</u>";
5190 } else if (strcmp(name, "STRIKE") == 0) { 5250 } else if (strcmp(name, "STRIKE") == 0) {
5191 return "</s>"; 5251 g_free(name);
5252 return "</s>";
5192 } else if (strncmp(name, "LINK ", 5) == 0) { 5253 } else if (strncmp(name, "LINK ", 5) == 0) {
5193 return "</a>"; 5254 g_free(name);
5255 return "</a>";
5194 } else if (strncmp(name, "FORECOLOR ", 10) == 0) { 5256 } else if (strncmp(name, "FORECOLOR ", 10) == 0) {
5195 return "</font>"; 5257 g_free(name);
5258 return "</font>";
5196 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { 5259 } else if (strncmp(name, "BACKCOLOR ", 10) == 0) {
5197 return "</font>"; 5260 g_free(name);
5261 return "</font>";
5198 } else if (strncmp(name, "BACKGROUND ", 10) == 0) { 5262 } else if (strncmp(name, "BACKGROUND ", 10) == 0) {
5199 return "</body>"; 5263 g_free(name);
5264 return "</body>";
5200 } else if (strncmp(name, "FONT FACE ", 10) == 0) { 5265 } else if (strncmp(name, "FONT FACE ", 10) == 0) {
5201 return "</font>"; 5266 g_free(name);
5267 return "</font>";
5202 } else if (strncmp(name, "FONT SIZE ", 10) == 0) { 5268 } else if (strncmp(name, "FONT SIZE ", 10) == 0) {
5203 return "</font>"; 5269 g_free(name);
5270 return "</font>";
5204 } else { 5271 } else {
5205 const char *props[] = {"weight-set", "foreground-set", "background-set", 5272 const char *props[] = {"weight-set", "foreground-set", "background-set",
5206 "size-set", "underline-set", NULL}; 5273 "size-set", "underline-set", NULL};
5207 int i; 5274 int i;
5208 for (i = 0; props[i]; i++) { 5275 for (i = 0; props[i]; i++) {
5209 gboolean set = FALSE; 5276 gboolean set = FALSE;
5210 g_object_get(G_OBJECT(tag), props[i], &set, NULL); 5277 g_object_get(G_OBJECT(tag), props[i], &set, NULL);
5211 if (set) 5278 if (set)
5212 return "</span>"; 5279 return "</span>";
5213 } 5280 }
5281
5282 g_free(name);
5214 5283
5215 return ""; 5284 return "";
5216 } 5285 }
5217 } 5286 }
5218 5287

mercurial