Mercurial > pidgin
comparison src/gtkconv.c @ 12335:3726ff9022f3
[gaim-migrate @ 14639]
[ 1342462 ] [HEAD] Crash on some custom smilies
committer: Tailor Script <tailor@pidgin.im>
author | Tim Ringenbach <marv@pidgin.im> |
---|---|
date | Mon, 05 Dec 2005 02:56:55 +0000 |
parents | a532eccfc7bb |
children | f6fa5d742c76 |
comparison
equal
deleted
inserted
replaced
12334:2823118073fa | 12335:3726ff9022f3 |
---|---|
69 #define AUTO_RESPONSE "<AUTO-REPLY> : " | 69 #define AUTO_RESPONSE "<AUTO-REPLY> : " |
70 | 70 |
71 #define SEND_COLOR "#204a87" | 71 #define SEND_COLOR "#204a87" |
72 #define RECV_COLOR "#cc0000" | 72 #define RECV_COLOR "#cc0000" |
73 | 73 |
74 /* Undef this to turn off "custom-smiley" debug messages */ | |
75 #define DEBUG_CUSTOM_SMILEY | |
76 | |
74 #define LUMINANCE(c) (float)((0.3*(c.red))+(0.59*(c.green))+(0.11*(c.blue))) | 77 #define LUMINANCE(c) (float)((0.3*(c.red))+(0.59*(c.green))+(0.11*(c.blue))) |
75 | 78 |
76 /* These colors come from the default GNOME palette */ | 79 /* These colors come from the default GNOME palette */ |
77 static GdkColor nick_colors[] = { | 80 static GdkColor nick_colors[] = { |
78 {0, 47616, 46336, 43776}, /* Basic 3D Medium */ | 81 {0, 47616, 46336, 43776}, /* Basic 3D Medium */ |
131 static void gaim_gtkconv_updated(GaimConversation *conv, GaimConvUpdateType type); | 134 static void gaim_gtkconv_updated(GaimConversation *conv, GaimConvUpdateType type); |
132 static void gtkconv_set_unseen(GaimGtkConversation *gtkconv, GaimUnseenState state); | 135 static void gtkconv_set_unseen(GaimGtkConversation *gtkconv, GaimUnseenState state); |
133 static void update_typing_icon(GaimGtkConversation *gtkconv); | 136 static void update_typing_icon(GaimGtkConversation *gtkconv); |
134 static char *item_factory_translate_func (const char *path, gpointer func_data); | 137 static char *item_factory_translate_func (const char *path, gpointer func_data); |
135 gboolean gaim_gtkconv_has_focus(GaimConversation *conv); | 138 gboolean gaim_gtkconv_has_focus(GaimConversation *conv); |
139 static void gaim_gtkconv_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data); | |
140 static void gaim_gtkconv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data); | |
136 | 141 |
137 static GdkColor *get_nick_color(GaimGtkConversation *gtkconv, const char *name) { | 142 static GdkColor *get_nick_color(GaimGtkConversation *gtkconv, const char *name) { |
138 static GdkColor col; | 143 static GdkColor col; |
139 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); | 144 GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); |
140 float scale; | 145 float scale; |
4760 return TRUE; | 4765 return TRUE; |
4761 | 4766 |
4762 return FALSE; | 4767 return FALSE; |
4763 } | 4768 } |
4764 | 4769 |
4770 static void gaim_gtkconv_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data) | |
4771 { | |
4772 GtkIMHtmlSmiley *smiley; | |
4773 | |
4774 smiley = (GtkIMHtmlSmiley *)user_data; | |
4775 smiley->icon = gdk_pixbuf_loader_get_animation(loader); | |
4776 | |
4777 if (smiley->icon) | |
4778 g_object_ref(G_OBJECT(smiley->icon)); | |
4779 #ifdef DEBUG_CUSTOM_SMILEY | |
4780 gaim_debug_info("custom-smiley", "%s(): got GdkPixbufAnimation %p for smiley '%s'\n", __FUNCTION__, smiley->icon, smiley->smile); | |
4781 #endif | |
4782 } | |
4783 | |
4784 static void gaim_gtkconv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data) | |
4785 { | |
4786 GtkIMHtmlSmiley *smiley; | |
4787 GtkWidget *icon = NULL; | |
4788 GtkTextChildAnchor *anchor = NULL; | |
4789 GSList *current = NULL; | |
4790 | |
4791 smiley = (GtkIMHtmlSmiley *)user_data; | |
4792 if (!smiley->imhtml) { | |
4793 #ifdef DEBUG_CUSTOM_SMILEY | |
4794 gaim_debug_error("custom-smiley", "%s(): orphan smiley found: %p\n", __FUNCTION__, smiley); | |
4795 #endif | |
4796 g_object_unref(G_OBJECT(loader)); | |
4797 smiley->loader = NULL; | |
4798 return; | |
4799 } | |
4800 | |
4801 for (current = smiley->anchors; current; current = g_slist_next(current)) { | |
4802 | |
4803 icon = gtk_image_new_from_animation(smiley->icon); | |
4804 | |
4805 #ifdef DEBUG_CUSTOM_SMILEY | |
4806 gaim_debug_info("custom-smiley", "%s(): got GtkImage %p from GtkPixbufAnimation %p for smiley '%s'\n", | |
4807 __FUNCTION__, icon, smiley->icon, smiley->smile); | |
4808 #endif | |
4809 if (icon) { | |
4810 gtk_widget_show(icon); | |
4811 | |
4812 anchor = GTK_TEXT_CHILD_ANCHOR(current->data); | |
4813 | |
4814 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(gaim_unescape_html(smiley->smile)), g_free); | |
4815 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley->smile), g_free); | |
4816 | |
4817 if (smiley->imhtml) | |
4818 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor); | |
4819 } | |
4820 | |
4821 } | |
4822 | |
4823 g_slist_free(smiley->anchors); | |
4824 smiley->anchors = NULL; | |
4825 | |
4826 g_object_unref(G_OBJECT(loader)); | |
4827 smiley->loader = NULL; | |
4828 } | |
4829 | |
4765 static gboolean | 4830 static gboolean |
4766 gaim_gtkconv_custom_smiley_add(GaimConversation *conv, const char *smile) | 4831 gaim_gtkconv_custom_smiley_add(GaimConversation *conv, const char *smile) |
4767 { | 4832 { |
4768 GaimGtkConversation *gtkconv; | 4833 GaimGtkConversation *gtkconv; |
4769 GtkIMHtmlSmiley *smiley; | 4834 GtkIMHtmlSmiley *smiley; |
4802 /* Close the old GdkPixbufAnimation, then create a new one for | 4867 /* Close the old GdkPixbufAnimation, then create a new one for |
4803 * the smiley we are about to receive */ | 4868 * the smiley we are about to receive */ |
4804 g_object_unref(G_OBJECT(smiley->icon)); | 4869 g_object_unref(G_OBJECT(smiley->icon)); |
4805 | 4870 |
4806 smiley->loader = gdk_pixbuf_loader_new(); | 4871 smiley->loader = gdk_pixbuf_loader_new(); |
4807 smiley->icon = gdk_pixbuf_loader_get_animation(smiley->loader); | 4872 smiley->icon = NULL; |
4808 if (smiley->icon) | 4873 |
4809 g_object_ref(G_OBJECT(smiley->icon)); | 4874 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(gaim_gtkconv_custom_smiley_allocated), smiley); |
4810 | 4875 g_signal_connect(smiley->loader, "closed", G_CALLBACK(gaim_gtkconv_custom_smiley_closed), smiley); |
4811 /* A custom smiley is already associated */ | 4876 |
4812 return TRUE; | 4877 return TRUE; |
4813 } | 4878 } |
4814 | 4879 |
4815 loader = gdk_pixbuf_loader_new(); | 4880 loader = gdk_pixbuf_loader_new(); |
4816 | 4881 |
4821 smiley->file = NULL; | 4886 smiley->file = NULL; |
4822 smiley->smile = g_strdup(smile); | 4887 smiley->smile = g_strdup(smile); |
4823 smiley->loader = loader; | 4888 smiley->loader = loader; |
4824 smiley->flags = smiley->flags | GTK_IMHTML_SMILEY_CUSTOM; | 4889 smiley->flags = smiley->flags | GTK_IMHTML_SMILEY_CUSTOM; |
4825 | 4890 |
4826 smiley->icon = gdk_pixbuf_loader_get_animation(loader); | 4891 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(gaim_gtkconv_custom_smiley_allocated), smiley); |
4827 if (smiley->icon) | 4892 g_signal_connect(smiley->loader, "closed", G_CALLBACK(gaim_gtkconv_custom_smiley_closed), smiley); |
4828 g_object_ref(G_OBJECT(smiley->icon)); | |
4829 | |
4830 | 4893 |
4831 gtk_imhtml_associate_smiley(GTK_IMHTML(gtkconv->imhtml), sml, smiley); | 4894 gtk_imhtml_associate_smiley(GTK_IMHTML(gtkconv->imhtml), sml, smiley); |
4832 | 4895 |
4833 return TRUE; | 4896 return TRUE; |
4834 } | 4897 } |
4861 { | 4924 { |
4862 GaimGtkConversation *gtkconv; | 4925 GaimGtkConversation *gtkconv; |
4863 GtkIMHtmlSmiley *smiley; | 4926 GtkIMHtmlSmiley *smiley; |
4864 GdkPixbufLoader *loader; | 4927 GdkPixbufLoader *loader; |
4865 const char *sml; | 4928 const char *sml; |
4866 GtkWidget *icon = NULL; | |
4867 GtkTextChildAnchor *anchor = NULL; | |
4868 GtkTextIter end; | |
4869 GtkIMHtml *imhtml; | |
4870 GSList *current = NULL; | |
4871 | 4929 |
4872 g_return_if_fail(conv != NULL); | 4930 g_return_if_fail(conv != NULL); |
4873 g_return_if_fail(smile != NULL); | 4931 g_return_if_fail(smile != NULL); |
4874 | 4932 |
4875 sml = gaim_account_get_protocol_name(conv->account); | 4933 sml = gaim_account_get_protocol_name(conv->account); |
4882 loader = smiley->loader; | 4940 loader = smiley->loader; |
4883 | 4941 |
4884 if (!loader) | 4942 if (!loader) |
4885 return; | 4943 return; |
4886 | 4944 |
4887 smiley->icon = gdk_pixbuf_loader_get_animation(loader); | 4945 |
4888 if (smiley->icon) | |
4889 g_object_ref(G_OBJECT(smiley->icon)); | |
4890 | |
4891 for (current = smiley->anchors; current != NULL; current = g_slist_next(current)) { | |
4892 | |
4893 icon = gtk_image_new_from_animation(smiley->icon); | |
4894 | |
4895 if (icon) { | |
4896 gtk_widget_show(icon); | |
4897 | |
4898 anchor = GTK_TEXT_CHILD_ANCHOR(current->data); | |
4899 | |
4900 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(gaim_unescape_html(smile)), g_free); | |
4901 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smile), g_free); | |
4902 | |
4903 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(gtkconv->imhtml), icon, anchor); | |
4904 } | |
4905 | |
4906 } | |
4907 | |
4908 g_slist_free(smiley->anchors); | |
4909 smiley->anchors = NULL; | |
4910 | |
4911 /* Scroll to the end of the widget in case the smiley height was big... */ | |
4912 /* FIXME: need to test this actually works, previous dealings with scrolling | |
4913 * makes me question it */ | |
4914 imhtml = GTK_IMHTML(gtkconv->imhtml); | |
4915 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(imhtml->text_buffer), &end); | |
4916 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(gtkconv->imhtml), &end, 0, TRUE, 0, 0); | |
4917 | 4946 |
4918 gaim_debug_info("gtkconv", "About to close the smiley pixbuf\n"); | 4947 gaim_debug_info("gtkconv", "About to close the smiley pixbuf\n"); |
4919 | 4948 |
4920 gdk_pixbuf_loader_close(loader, NULL); | 4949 gdk_pixbuf_loader_close(loader, NULL); |
4921 g_object_unref(G_OBJECT(loader)); | 4950 |
4922 smiley->loader = NULL; | |
4923 } | 4951 } |
4924 | 4952 |
4925 /* | 4953 /* |
4926 * Makes sure all the menu items and all the buttons are hidden/shown and | 4954 * Makes sure all the menu items and all the buttons are hidden/shown and |
4927 * sensitive/insensitive. This is called after changing tabs and when an | 4955 * sensitive/insensitive. This is called after changing tabs and when an |