Mercurial > pidgin.yaz
comparison src/gtkimhtml.c @ 8962:4ff4c34b7500
[gaim-migrate @ 9736]
IM Image, WYSIWYG.
It's still somewhat buggy, although the worse problems are with oscar's
direct connect. We could always yank oscar's im image flag if we think it
will cause too many bug reports.
I made the GaimImgstore struct opque.
I modified oscar's sending function to parse im images better, and
everything seems to work. I made it write some errors to the conversation
if you try to send an image and you aren't direct connected. That's just
a hack until you can set formatting flags on a per conversation bases.
There's a scrolling bug I haven't tracked down. I think it may exist
normally and this just causes it better.
It's worth noting jabber also uses this for pics in profiles, although
I never did find a test case. Hopefully some other stuff can use this
soon too, maybe Yahoo! pics in profiles or something.
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Mon, 17 May 2004 06:47:20 +0000 |
parents | 97a1f314b051 |
children | 0a08f671b591 |
comparison
equal
deleted
inserted
replaced
8961:92e061a1db10 | 8962:4ff4c34b7500 |
---|---|
903 static void | 903 static void |
904 gtk_imhtml_finalize (GObject *object) | 904 gtk_imhtml_finalize (GObject *object) |
905 { | 905 { |
906 GtkIMHtml *imhtml = GTK_IMHTML(object); | 906 GtkIMHtml *imhtml = GTK_IMHTML(object); |
907 GList *scalables; | 907 GList *scalables; |
908 GSList *l; | |
908 | 909 |
909 g_hash_table_destroy(imhtml->smiley_data); | 910 g_hash_table_destroy(imhtml->smiley_data); |
910 gtk_smiley_tree_destroy(imhtml->default_smilies); | 911 gtk_smiley_tree_destroy(imhtml->default_smilies); |
911 gdk_cursor_unref(imhtml->hand_cursor); | 912 gdk_cursor_unref(imhtml->hand_cursor); |
912 gdk_cursor_unref(imhtml->arrow_cursor); | 913 gdk_cursor_unref(imhtml->arrow_cursor); |
921 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { | 922 for(scalables = imhtml->scalables; scalables; scalables = scalables->next) { |
922 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); | 923 GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data); |
923 scale->free(scale); | 924 scale->free(scale); |
924 } | 925 } |
925 | 926 |
927 for (l = imhtml->im_images; l; l = l->next) { | |
928 int id; | |
929 id = GPOINTER_TO_INT(l->data); | |
930 if (imhtml->funcs->image_unref) | |
931 imhtml->funcs->image_unref(id); | |
932 } | |
933 | |
926 if (imhtml->clipboard_text_string) { | 934 if (imhtml->clipboard_text_string) { |
927 g_free(imhtml->clipboard_text_string); | 935 g_free(imhtml->clipboard_text_string); |
928 g_free(imhtml->clipboard_html_string); | 936 g_free(imhtml->clipboard_html_string); |
929 } | 937 } |
930 | 938 |
931 g_list_free(imhtml->scalables); | 939 g_list_free(imhtml->scalables); |
940 g_slist_free(imhtml->im_images); | |
932 G_OBJECT_CLASS(parent_class)->finalize (object); | 941 G_OBJECT_CLASS(parent_class)->finalize (object); |
933 } | 942 } |
934 | 943 |
935 /* Boring GTK stuff */ | 944 /* Boring GTK stuff */ |
936 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) | 945 static void gtk_imhtml_class_init (GtkIMHtmlClass *klass) |
2165 } | 2174 } |
2166 break; | 2175 break; |
2167 case 46: /* IMG (opt) */ | 2176 case 46: /* IMG (opt) */ |
2168 case 59: /* IMG */ | 2177 case 59: /* IMG */ |
2169 { | 2178 { |
2170 #if 0 | 2179 const char *id; |
2171 /* disabling this for now, it's easy to add it back... */ | 2180 |
2172 GdkPixbuf *img = NULL; | 2181 gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos); |
2173 const gchar *filename = NULL; | 2182 ws[0] = '\0'; wpos = 0; |
2174 | 2183 |
2175 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) | 2184 if (!(imhtml->format_functions & GTK_IMHTML_IMAGE)) |
2176 break; | 2185 break; |
2177 | 2186 |
2178 if (images && images->data) { | 2187 id = gtk_imhtml_get_html_opt(tag, "ID="); |
2179 img = images->data; | 2188 |
2180 images = images->next; | 2189 gtk_imhtml_insert_image_at_iter(imhtml, atoi(id), iter); |
2181 filename = g_object_get_data(G_OBJECT(img), "filename"); | 2190 break; |
2182 g_object_ref(G_OBJECT(img)); | |
2183 } else { | |
2184 img = gtk_widget_render_icon(GTK_WIDGET(imhtml), | |
2185 GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON, | |
2186 "gtkimhtml-missing-image"); | |
2187 } | |
2188 | |
2189 scalable = gtk_imhtml_image_new(img, filename); | |
2190 /* NEW_BIT(NEW_SCALABLE_BIT); */ | |
2191 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
2192 scalable->add_to(scalable, imhtml, iter); | |
2193 scalable->scale(scalable, rect.width, rect.height); | |
2194 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | |
2195 | |
2196 g_object_unref(G_OBJECT(img)); | |
2197 #endif | |
2198 } | 2191 } |
2199 case 47: /* P (opt) */ | 2192 case 47: /* P (opt) */ |
2200 case 48: /* H3 (opt) */ | 2193 case 48: /* H3 (opt) */ |
2201 case 49: /* HTML (opt) */ | 2194 case 49: /* HTML (opt) */ |
2202 case 50: /* CITE */ | 2195 case 50: /* CITE */ |
2484 gboolean allow) | 2477 gboolean allow) |
2485 { | 2478 { |
2486 imhtml->smiley_shortcuts = allow; | 2479 imhtml->smiley_shortcuts = allow; |
2487 } | 2480 } |
2488 | 2481 |
2489 void | 2482 void |
2490 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, gchar *protocol_name) { | 2483 gtk_imhtml_set_protocol_name(GtkIMHtml *imhtml, gchar *protocol_name) { |
2491 imhtml->protocol_name = protocol_name; | 2484 imhtml->protocol_name = protocol_name; |
2492 } | 2485 } |
2493 | 2486 |
2494 void | 2487 void |
2536 rect.y + rect.height); | 2529 rect.y + rect.height); |
2537 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); | 2530 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); |
2538 } | 2531 } |
2539 | 2532 |
2540 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ | 2533 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ |
2541 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename) | 2534 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) |
2542 { | 2535 { |
2543 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); | 2536 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); |
2544 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); | 2537 GtkImage *image = GTK_IMAGE(gtk_image_new_from_pixbuf(img)); |
2545 | 2538 |
2546 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; | 2539 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; |
2551 im_image->image = image; | 2544 im_image->image = image; |
2552 im_image->width = gdk_pixbuf_get_width(img); | 2545 im_image->width = gdk_pixbuf_get_width(img); |
2553 im_image->height = gdk_pixbuf_get_height(img); | 2546 im_image->height = gdk_pixbuf_get_height(img); |
2554 im_image->mark = NULL; | 2547 im_image->mark = NULL; |
2555 im_image->filename = filename ? g_strdup(filename) : NULL; | 2548 im_image->filename = filename ? g_strdup(filename) : NULL; |
2549 im_image->id = id; | |
2556 | 2550 |
2557 g_object_ref(img); | 2551 g_object_ref(img); |
2558 return GTK_IMHTML_SCALABLE(im_image); | 2552 return GTK_IMHTML_SCALABLE(im_image); |
2559 } | 2553 } |
2560 | 2554 |
2731 | 2725 |
2732 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) | 2726 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) |
2733 { | 2727 { |
2734 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; | 2728 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; |
2735 GtkWidget *box = gtk_event_box_new(); | 2729 GtkWidget *box = gtk_event_box_new(); |
2730 char *tag; | |
2736 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); | 2731 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); |
2737 | 2732 |
2738 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); | 2733 gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(image->image)); |
2739 | 2734 |
2740 gtk_widget_show(GTK_WIDGET(image->image)); | 2735 gtk_widget_show(GTK_WIDGET(image->image)); |
2741 gtk_widget_show(box); | 2736 gtk_widget_show(box); |
2737 | |
2738 tag = g_strdup_printf("<IMG ID=\"%d\">", image->id); | |
2739 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free); | |
2740 g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]"); | |
2742 | 2741 |
2743 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); | 2742 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor); |
2744 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); | 2743 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image); |
2745 } | 2744 } |
2746 | 2745 |
3509 } else { | 3508 } else { |
3510 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); | 3509 gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); |
3511 } | 3510 } |
3512 | 3511 |
3513 g_free(unescaped); | 3512 g_free(unescaped); |
3513 } | |
3514 | |
3515 void gtk_imhtml_insert_image_at_iter(GtkIMHtml *imhtml, int id, GtkTextIter *iter) | |
3516 { | |
3517 GdkPixbuf *pixbuf = NULL; | |
3518 const char *filename = NULL; | |
3519 gpointer image; | |
3520 GdkRectangle rect; | |
3521 GtkIMHtmlScalable *scalable = NULL; | |
3522 int minus; | |
3523 | |
3524 if (!imhtml->funcs || !imhtml->funcs->image_get || | |
3525 !imhtml->funcs->image_get_size || !imhtml->funcs->image_get_data || | |
3526 !imhtml->funcs->image_get_filename || !imhtml->funcs->image_ref || | |
3527 !imhtml->funcs->image_unref) | |
3528 return; | |
3529 | |
3530 image = imhtml->funcs->image_get(id); | |
3531 | |
3532 if (image) { | |
3533 gpointer data; | |
3534 size_t len; | |
3535 | |
3536 data = imhtml->funcs->image_get_data(image); | |
3537 len = imhtml->funcs->image_get_size(image); | |
3538 | |
3539 if (data && len) { | |
3540 GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); | |
3541 gdk_pixbuf_loader_write(loader, data, len, NULL); | |
3542 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); | |
3543 if (pixbuf) | |
3544 g_object_ref(G_OBJECT(pixbuf)); | |
3545 gdk_pixbuf_loader_close(loader, NULL); | |
3546 } | |
3547 | |
3548 } | |
3549 | |
3550 if (pixbuf) { | |
3551 filename = imhtml->funcs->image_get_filename(image); | |
3552 imhtml->funcs->image_ref(id); | |
3553 imhtml->im_images = g_slist_prepend(imhtml->im_images, GINT_TO_POINTER(id)); | |
3554 } else { | |
3555 pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE, | |
3556 GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image"); | |
3557 } | |
3558 | |
3559 scalable = gtk_imhtml_image_new(pixbuf, filename, id); | |
3560 gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect); | |
3561 scalable->add_to(scalable, imhtml, iter); | |
3562 minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) + | |
3563 gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml)); | |
3564 scalable->scale(scalable, rect.width - minus, rect.height); | |
3565 imhtml->scalables = g_list_append(imhtml->scalables, scalable); | |
3566 | |
3567 g_object_unref(G_OBJECT(pixbuf)); | |
3514 } | 3568 } |
3515 | 3569 |
3516 static const gchar *tag_to_html_start(GtkTextTag *tag) | 3570 static const gchar *tag_to_html_start(GtkTextTag *tag) |
3517 { | 3571 { |
3518 const gchar *name; | 3572 const gchar *name; |
3794 gtk_text_iter_forward_char(&iter); | 3848 gtk_text_iter_forward_char(&iter); |
3795 } | 3849 } |
3796 | 3850 |
3797 return g_string_free(str, FALSE); | 3851 return g_string_free(str, FALSE); |
3798 } | 3852 } |
3853 | |
3854 void gtk_imhtml_set_funcs(GtkIMHtml *imhtml, GtkIMHtmlFuncs *f) | |
3855 { | |
3856 g_return_if_fail(imhtml != NULL); | |
3857 imhtml->funcs = f; | |
3858 } |