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 "&lt;AUTO-REPLY&gt; : " 69 #define AUTO_RESPONSE "&lt;AUTO-REPLY&gt; : "
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