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 }