Mercurial > pidgin.yaz
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); |