comparison pidgin/gtkimhtml.c @ 32779:d72f2f13b60f

merge of 'c8c73eea7431e6f940916315ace40a41c8da3faa' and 'fec428131bde0ae8247941bd6a3d996c984c9189'
author Ethan Blanton <elb@pidgin.im>
date Fri, 21 Oct 2011 14:36:18 +0000
parents 1cec4425d0cc
children 4a34689eeb33
comparison
equal deleted inserted replaced
32778:14787acaf9d7 32779:d72f2f13b60f
81 struct im_image_data { 81 struct im_image_data {
82 int id; 82 int id;
83 GtkTextMark *mark; 83 GtkTextMark *mark;
84 }; 84 };
85 85
86 struct _GtkIMHtmlScalable {
87 void (*scale)(struct _GtkIMHtmlScalable *, int, int);
88 void (*add_to)(struct _GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *);
89 void (*free)(struct _GtkIMHtmlScalable *);
90 };
91
92 struct _GtkIMHtmlHr {
93 GtkIMHtmlScalable scalable;
94 GtkWidget *sep;
95 };
96
97 struct _GtkIMHtmlImage {
98 GtkIMHtmlScalable scalable;
99 GtkImage *image; /**< Contains the scaled version of this pixbuf. */
100 GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */
101 GtkTextMark *mark;
102 gchar *filename;
103 int width;
104 int height;
105 int id;
106 GtkWidget *filesel;
107 };
108
109 struct _GtkIMHtmlAnimation {
110 GtkIMHtmlImage imhtmlimage;
111 GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */
112 GdkPixbufAnimationIter *iter;
113 guint timer;
114 };
115
86 struct _GtkIMHtmlLink 116 struct _GtkIMHtmlLink
87 { 117 {
88 GtkIMHtml *imhtml; 118 GtkIMHtml *imhtml;
89 gchar *url; 119 gchar *url;
90 GtkTextTag *tag; 120 GtkTextTag *tag;
91 }; 121 };
92 122
93 typedef struct _GtkIMHtmlProtocol 123 struct _GtkSmileyTree {
94 { 124 GString *values;
125 GtkSmileyTree **children;
126 GtkIMHtmlSmiley *image;
127 };
128
129 typedef struct {
95 char *name; 130 char *name;
96 int length; 131 int length;
97 132
98 gboolean (*activate)(GtkIMHtml *imhtml, GtkIMHtmlLink *link); 133 gboolean (*activate)(GtkIMHtml *imhtml, GtkIMHtmlLink *link);
99 gboolean (*context_menu)(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu); 134 gboolean (*context_menu)(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu);
100 } GtkIMHtmlProtocol; 135 } GtkIMHtmlProtocol;
101 136
102 typedef struct _GtkIMHtmlFontDetail { 137 /* The five elements contained in a FONT tag */
138 typedef struct {
103 gushort size; 139 gushort size;
104 gchar *face; 140 gchar *face;
105 gchar *fore; 141 gchar *fore;
106 gchar *back; 142 gchar *back;
107 gchar *bg; 143 gchar *bg;
3591 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x, 3627 gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, rect.x,
3592 rect.y + rect.height); 3628 rect.y + rect.height);
3593 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); 3629 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0);
3594 } 3630 }
3595 3631
3596 /* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ 3632 /**
3597 GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) 3633 * Destroys and frees a GTK+ IM/HTML scalable image.
3598 { 3634 *
3599 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); 3635 * @param scale The GTK+ IM/HTML scalable.
3600 3636 */
3601 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; 3637 static void gtk_imhtml_image_free(GtkIMHtmlScalable *scale)
3602 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; 3638 {
3603 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; 3639 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
3604 3640
3605 im_image->pixbuf = img; 3641 g_object_unref(image->pixbuf);
3606 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); 3642 g_free(image->filename);
3607 im_image->width = gdk_pixbuf_get_width(img); 3643 if (image->filesel)
3608 im_image->height = gdk_pixbuf_get_height(img); 3644 gtk_widget_destroy(image->filesel);
3609 im_image->mark = NULL; 3645 g_free(scale);
3610 im_image->filename = g_strdup(filename); 3646 }
3611 im_image->id = id; 3647
3612 im_image->filesel = NULL; 3648 /**
3613 3649 * Destroys and frees a GTK+ IM/HTML scalable animation.
3614 g_object_ref(img); 3650 *
3615 return GTK_IMHTML_SCALABLE(im_image); 3651 * @param scale The GTK+ IM/HTML scalable.
3616 } 3652 */
3617 3653 static void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale)
3618 static gboolean 3654 {
3619 animate_image_cb(gpointer data) 3655 GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale;
3620 { 3656
3621 GtkIMHtmlImage *im_image; 3657 if (animation->timer > 0)
3622 int width, height; 3658 g_source_remove(animation->timer);
3623 int delay; 3659 if (animation->iter != NULL)
3624 3660 g_object_unref(animation->iter);
3625 im_image = data; 3661 g_object_unref(animation->anim);
3626 3662
3627 /* Update the pointer to this GdkPixbuf frame of the animation */ 3663 gtk_imhtml_image_free(scale);
3628 if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
3629 GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3630 g_object_unref(G_OBJECT(im_image->pixbuf));
3631 im_image->pixbuf = gdk_pixbuf_copy(pb);
3632
3633 /* Update the displayed GtkImage */
3634 width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
3635 height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
3636 if (width > 0 && height > 0)
3637 {
3638 /* Need to scale the new frame to the same size as the old frame */
3639 GdkPixbuf *tmp;
3640 tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
3641 gtk_image_set_from_pixbuf(im_image->image, tmp);
3642 g_object_unref(G_OBJECT(tmp));
3643 } else {
3644 /* Display at full-size */
3645 gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
3646 }
3647 }
3648
3649 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3650 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3651
3652 return FALSE;
3653 }
3654
3655 GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
3656 {
3657 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1);
3658
3659 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3660 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3661 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
3662
3663 GTK_IMHTML_ANIMATION(im_image)->anim = anim;
3664 if (gdk_pixbuf_animation_is_static_image(anim)) {
3665 im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
3666 g_object_ref(im_image->pixbuf);
3667 } else {
3668 int delay;
3669 GdkPixbuf *pb;
3670 GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
3671 pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3672 im_image->pixbuf = gdk_pixbuf_copy(pb);
3673 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
3674 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
3675 }
3676 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
3677 im_image->width = gdk_pixbuf_animation_get_width(anim);
3678 im_image->height = gdk_pixbuf_animation_get_height(anim);
3679 im_image->filename = g_strdup(filename);
3680 im_image->id = id;
3681
3682 g_object_ref(anim);
3683
3684 return GTK_IMHTML_SCALABLE(im_image);
3685 }
3686
3687 void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
3688 {
3689 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
3690
3691 if (im_image->width > width || im_image->height > height) {
3692 double ratio_w, ratio_h, ratio;
3693 int new_h, new_w;
3694 GdkPixbuf *new_image = NULL;
3695
3696 ratio_w = ((double)width - 2) / im_image->width;
3697 ratio_h = ((double)height - 2) / im_image->height;
3698
3699 ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
3700
3701 new_w = (int)(im_image->width * ratio);
3702 new_h = (int)(im_image->height * ratio);
3703
3704 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR);
3705 gtk_image_set_from_pixbuf(im_image->image, new_image);
3706 g_object_unref(G_OBJECT(new_image));
3707 } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) {
3708 /* Enough space to show the full-size of the image. */
3709 GdkPixbuf *new_image;
3710
3711 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR);
3712 gtk_image_set_from_pixbuf(im_image->image, new_image);
3713 g_object_unref(G_OBJECT(new_image));
3714 }
3715 } 3664 }
3716 3665
3717 static void 3666 static void
3718 image_save_yes_cb(GtkIMHtmlImageSave *save, const char *filename) 3667 image_save_yes_cb(GtkIMHtmlImageSave *save, const char *filename)
3719 { 3668 {
3916 else 3865 else
3917 return FALSE; /* Let clicks go through if we didn't catch anything */ 3866 return FALSE; /* Let clicks go through if we didn't catch anything */
3918 3867
3919 } 3868 }
3920 3869
3921 static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) 3870 /**
3922 { 3871 * Rescales a GTK+ IM/HTML scalable image to a given size.
3923 GdkPixbufAnimation *anim = NULL; 3872 *
3924 GtkIMHtmlImageSave *save = NULL; 3873 * @param scale The GTK+ IM/HTML scalable.
3925 gboolean ret; 3874 * @param width The new width.
3926 3875 * @param height The new height.
3927 if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) 3876 */
3928 return FALSE; 3877 static void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height)
3929 3878 {
3930 anim = gtk_smiley_get_image(smiley); 3879 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale;
3931 if (!anim) 3880
3932 return FALSE; 3881 if (im_image->width > width || im_image->height > height) {
3933 3882 double ratio_w, ratio_h, ratio;
3934 save = g_new0(GtkIMHtmlImageSave, 1); 3883 int new_h, new_w;
3935 save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); 3884 GdkPixbuf *new_image = NULL;
3936 save->data = smiley->data; /* Do not need to memdup here, since the smiley is not 3885
3937 destroyed before this GtkIMHtmlImageSave */ 3886 ratio_w = ((double)width - 2) / im_image->width;
3938 save->datasize = smiley->datasize; 3887 ratio_h = ((double)height - 2) / im_image->height;
3939 ret = gtk_imhtml_image_clicked(w, event, save); 3888
3940 g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); 3889 ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h;
3941 g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); 3890
3942 return ret; 3891 new_w = (int)(im_image->width * ratio);
3943 } 3892 new_h = (int)(im_image->height * ratio);
3944 3893
3945 void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) 3894 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR);
3946 { 3895 gtk_image_set_from_pixbuf(im_image->image, new_image);
3947 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; 3896 g_object_unref(G_OBJECT(new_image));
3948 3897 } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) {
3949 g_object_unref(image->pixbuf); 3898 /* Enough space to show the full-size of the image. */
3950 g_free(image->filename); 3899 GdkPixbuf *new_image;
3951 if (image->filesel) 3900
3952 gtk_widget_destroy(image->filesel); 3901 new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR);
3953 g_free(scale); 3902 gtk_image_set_from_pixbuf(im_image->image, new_image);
3954 } 3903 g_object_unref(G_OBJECT(new_image));
3955 3904 }
3956 void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) 3905 }
3957 { 3906
3958 GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; 3907 /**
3959 3908 * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter.
3960 if (animation->timer > 0) 3909 *
3961 g_source_remove(animation->timer); 3910 * @param scale The GTK+ IM/HTML scalable.
3962 if (animation->iter != NULL) 3911 * @param imhtml The GTK+ IM/HTML.
3963 g_object_unref(animation->iter); 3912 * @param iter The GtkTextIter at which to add the scalable.
3964 g_object_unref(animation->anim); 3913 */
3965 3914 static void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
3966 gtk_imhtml_image_free(scale);
3967 }
3968
3969 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
3970 { 3915 {
3971 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; 3916 GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
3972 GtkWidget *box = gtk_event_box_new(); 3917 GtkWidget *box = gtk_event_box_new();
3973 char *tag; 3918 char *tag;
3974 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); 3919 GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
3990 3935
3991 save = g_new0(GtkIMHtmlImageSave, 1); 3936 save = g_new0(GtkIMHtmlImageSave, 1);
3992 save->image = scale; 3937 save->image = scale;
3993 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), save); 3938 g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), save);
3994 g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free); 3939 g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free);
3940 }
3941
3942 /**
3943 * Creates and returns a new GTK+ IM/HTML scalable object with an image.
3944 *
3945 * @param img A GdkPixbuf of the image to add.
3946 * @param filename The filename to associate with the image.
3947 * @param id The id to associate with the image.
3948 *
3949 * @return A new IM/HTML Scalable object with an image.
3950 */
3951 static GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id)
3952 {
3953 GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage));
3954
3955 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
3956 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
3957 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free;
3958
3959 im_image->pixbuf = img;
3960 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
3961 im_image->width = gdk_pixbuf_get_width(img);
3962 im_image->height = gdk_pixbuf_get_height(img);
3963 im_image->mark = NULL;
3964 im_image->filename = g_strdup(filename);
3965 im_image->id = id;
3966 im_image->filesel = NULL;
3967
3968 g_object_ref(img);
3969 return GTK_IMHTML_SCALABLE(im_image);
3970 }
3971
3972 static gboolean
3973 animate_image_cb(gpointer data)
3974 {
3975 GtkIMHtmlImage *im_image;
3976 int width, height;
3977 int delay;
3978
3979 im_image = data;
3980
3981 /* Update the pointer to this GdkPixbuf frame of the animation */
3982 if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) {
3983 GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
3984 g_object_unref(G_OBJECT(im_image->pixbuf));
3985 im_image->pixbuf = gdk_pixbuf_copy(pb);
3986
3987 /* Update the displayed GtkImage */
3988 width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image));
3989 height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image));
3990 if (width > 0 && height > 0)
3991 {
3992 /* Need to scale the new frame to the same size as the old frame */
3993 GdkPixbuf *tmp;
3994 tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR);
3995 gtk_image_set_from_pixbuf(im_image->image, tmp);
3996 g_object_unref(G_OBJECT(tmp));
3997 } else {
3998 /* Display at full-size */
3999 gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf);
4000 }
4001 }
4002
4003 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
4004 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
4005
4006 return FALSE;
4007 }
4008
4009 /**
4010 * Creates and returns a new GTK+ IM/HTML scalable object with an
4011 * animated image.
4012 *
4013 * @param img A GdkPixbufAnimation of the image to add.
4014 * @param filename The filename to associate with the image.
4015 * @param id The id to associate with the image.
4016 *
4017 * @return A new IM/HTML Scalable object with an image.
4018 */
4019 /*
4020 * TODO: All this animation code could be combined much better with
4021 * the image code. It couldn't be done when it was written
4022 * because it requires breaking backward compatibility. It
4023 * would be good to do it for 3.0.0.
4024 */
4025 static GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id)
4026 {
4027 GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1);
4028
4029 GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale;
4030 GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to;
4031 GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free;
4032
4033 GTK_IMHTML_ANIMATION(im_image)->anim = anim;
4034 if (gdk_pixbuf_animation_is_static_image(anim)) {
4035 im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim);
4036 g_object_ref(im_image->pixbuf);
4037 } else {
4038 int delay;
4039 GdkPixbuf *pb;
4040 GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL);
4041 pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter);
4042 im_image->pixbuf = gdk_pixbuf_copy(pb);
4043 delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100);
4044 GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image);
4045 }
4046 im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf));
4047 im_image->width = gdk_pixbuf_animation_get_width(anim);
4048 im_image->height = gdk_pixbuf_animation_get_height(anim);
4049 im_image->filename = g_strdup(filename);
4050 im_image->id = id;
4051
4052 g_object_ref(anim);
4053
4054 return GTK_IMHTML_SCALABLE(im_image);
3995 } 4055 }
3996 4056
3997 GtkIMHtmlScalable *gtk_imhtml_hr_new() 4057 GtkIMHtmlScalable *gtk_imhtml_hr_new()
3998 { 4058 {
3999 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); 4059 GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr));
4914 imhtml->animations->head = g_list_delete_link(imhtml->animations->head, l); 4974 imhtml->animations->head = g_list_delete_link(imhtml->animations->head, l);
4915 imhtml->num_animations--; 4975 imhtml->num_animations--;
4916 } 4976 }
4917 l = next; 4977 l = next;
4918 } 4978 }
4979 }
4980
4981 static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley)
4982 {
4983 GdkPixbufAnimation *anim = NULL;
4984 GtkIMHtmlImageSave *save = NULL;
4985 gboolean ret;
4986
4987 if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3)
4988 return FALSE;
4989
4990 anim = gtk_smiley_get_image(smiley);
4991 if (!anim)
4992 return FALSE;
4993
4994 save = g_new0(GtkIMHtmlImageSave, 1);
4995 save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0);
4996 save->data = smiley->data; /* Do not need to memdup here, since the smiley is not
4997 destroyed before this GtkIMHtmlImageSave */
4998 save->datasize = smiley->datasize;
4999 ret = gtk_imhtml_image_clicked(w, event, save);
5000 g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free);
5001 g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free);
5002 return ret;
4919 } 5003 }
4920 5004
4921 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) 5005 void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter)
4922 { 5006 {
4923 GdkPixbuf *pixbuf = NULL; 5007 GdkPixbuf *pixbuf = NULL;
5365 tags = g_slist_reverse(tags); 5449 tags = g_slist_reverse(tags);
5366 for (sl = tags; sl; sl = sl->next) { 5450 for (sl = tags; sl; sl = sl->next) {
5367 tag = sl->data; 5451 tag = sl->data;
5368 /** don't worry about non-printing tags ending */ 5452 /** don't worry about non-printing tags ending */
5369 if (tag_ends_here(tag, &iter, &next_iter) && 5453 if (tag_ends_here(tag, &iter, &next_iter) &&
5370 strlen(tag_to_html_end(tag)) > 0 && 5454 *tag_to_html_end(tag) &&
5371 strlen(tag_to_html_start(tag)) > 0) { 5455 *tag_to_html_start(tag))
5372 5456 {
5373 PidginTextTagData *tmp; 5457 PidginTextTagData *tmp;
5374 GQueue *r = g_queue_new(); 5458 GQueue *r = g_queue_new();
5375 5459
5376 while ((tmp = g_queue_pop_tail(q)) && tmp->tag != tag) { 5460 while ((tmp = g_queue_pop_tail(q)) && tmp->tag != tag) {
5377 g_string_append(str, tmp->end); 5461 g_string_append(str, tmp->end);