Mercurial > pidgin.yaz
comparison pidgin/gtkconv.c @ 22889:019052a807a3
Introduce API for GtkIMHtmlSmiley. Use this to prevent leaking remote custom emoticons.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Tue, 18 Mar 2008 00:47:52 +0000 |
parents | e04a69cf1d8e |
children | 48e33e3673e2 |
comparison
equal
deleted
inserted
replaced
22888:98167ea7c093 | 22889:019052a807a3 |
---|---|
155 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); | 155 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); |
156 static void update_typing_icon(PidginConversation *gtkconv); | 156 static void update_typing_icon(PidginConversation *gtkconv); |
157 static void update_typing_message(PidginConversation *gtkconv, const char *message); | 157 static void update_typing_message(PidginConversation *gtkconv, const char *message); |
158 static const char *item_factory_translate_func (const char *path, gpointer func_data); | 158 static const char *item_factory_translate_func (const char *path, gpointer func_data); |
159 gboolean pidgin_conv_has_focus(PurpleConversation *conv); | 159 gboolean pidgin_conv_has_focus(PurpleConversation *conv); |
160 static void pidgin_conv_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data); | |
161 static void pidgin_conv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data); | |
162 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); | 160 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); |
163 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); | 161 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); |
164 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); | 162 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
165 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); | 163 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); |
166 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); | 164 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); |
5983 return TRUE; | 5981 return TRUE; |
5984 | 5982 |
5985 return FALSE; | 5983 return FALSE; |
5986 } | 5984 } |
5987 | 5985 |
5988 static void pidgin_conv_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data) | |
5989 { | |
5990 GtkIMHtmlSmiley *smiley; | |
5991 | |
5992 smiley = (GtkIMHtmlSmiley *)user_data; | |
5993 smiley->icon = gdk_pixbuf_loader_get_animation(loader); | |
5994 | |
5995 if (smiley->icon) | |
5996 g_object_ref(G_OBJECT(smiley->icon)); | |
5997 #ifdef DEBUG_CUSTOM_SMILEY | |
5998 purple_debug_info("custom-smiley", "pidgin_conv_custom_smiley_allocated(): got GdkPixbufAnimation %p for smiley '%s'\n", smiley->icon, smiley->smile); | |
5999 #endif | |
6000 } | |
6001 | |
6002 static void pidgin_conv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data) | |
6003 { | |
6004 GtkIMHtmlSmiley *smiley; | |
6005 GtkWidget *icon = NULL; | |
6006 GtkTextChildAnchor *anchor = NULL; | |
6007 GSList *current = NULL; | |
6008 | |
6009 smiley = (GtkIMHtmlSmiley *)user_data; | |
6010 if (!smiley->imhtml) { | |
6011 #ifdef DEBUG_CUSTOM_SMILEY | |
6012 purple_debug_error("custom-smiley", "pidgin_conv_custom_smiley_closed(): orphan smiley found: %p\n", smiley); | |
6013 #endif | |
6014 g_object_unref(G_OBJECT(loader)); | |
6015 smiley->loader = NULL; | |
6016 return; | |
6017 } | |
6018 | |
6019 for (current = smiley->anchors; current; current = g_slist_next(current)) { | |
6020 | |
6021 icon = gtk_image_new_from_animation(smiley->icon); | |
6022 | |
6023 #ifdef DEBUG_CUSTOM_SMILEY | |
6024 purple_debug_info("custom-smiley", "pidgin_conv_custom_smiley_closed(): got GtkImage %p from GtkPixbufAnimation %p for smiley '%s'\n", | |
6025 icon, smiley->icon, smiley->smile); | |
6026 #endif | |
6027 if (icon) { | |
6028 GList *wids; | |
6029 gtk_widget_show(icon); | |
6030 | |
6031 anchor = GTK_TEXT_CHILD_ANCHOR(current->data); | |
6032 wids = gtk_text_child_anchor_get_widgets(anchor); | |
6033 | |
6034 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", purple_unescape_html(smiley->smile), g_free); | |
6035 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley->smile), g_free); | |
6036 | |
6037 if (smiley->imhtml) { | |
6038 if (wids) { | |
6039 GList *children = gtk_container_get_children(GTK_CONTAINER(wids->data)); | |
6040 g_list_foreach(children, (GFunc)gtk_widget_destroy, NULL); | |
6041 g_list_free(children); | |
6042 gtk_container_add(GTK_CONTAINER(wids->data), icon); | |
6043 } else | |
6044 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor); | |
6045 } | |
6046 g_list_free(wids); | |
6047 } | |
6048 | |
6049 } | |
6050 | |
6051 g_slist_free(smiley->anchors); | |
6052 smiley->anchors = NULL; | |
6053 | |
6054 g_object_unref(G_OBJECT(loader)); | |
6055 smiley->loader = NULL; | |
6056 } | |
6057 | |
6058 static gboolean | 5986 static gboolean |
6059 add_custom_smiley_for_imhtml(GtkIMHtml *imhtml, const char *sml, const char *smile) | 5987 add_custom_smiley_for_imhtml(GtkIMHtml *imhtml, const char *sml, const char *smile) |
6060 { | 5988 { |
6061 GtkIMHtmlSmiley *smiley; | 5989 GtkIMHtmlSmiley *smiley; |
6062 GdkPixbufLoader *loader; | |
6063 | 5990 |
6064 smiley = gtk_imhtml_smiley_get(imhtml, sml, smile); | 5991 smiley = gtk_imhtml_smiley_get(imhtml, sml, smile); |
6065 | 5992 |
6066 if (smiley) { | 5993 if (smiley) { |
6067 | |
6068 if (!(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) { | 5994 if (!(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) { |
6069 return FALSE; | 5995 return FALSE; |
6070 } | 5996 } |
6071 | 5997 gtk_imhtml_smiley_reload(smiley); |
6072 /* Close the old GdkPixbufAnimation, then create a new one for | |
6073 * the smiley we are about to receive */ | |
6074 g_object_unref(G_OBJECT(smiley->icon)); | |
6075 | |
6076 /* XXX: Is it necessary to _unref the loader first? */ | |
6077 smiley->loader = gdk_pixbuf_loader_new(); | |
6078 smiley->icon = NULL; | |
6079 | |
6080 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(pidgin_conv_custom_smiley_allocated), smiley); | |
6081 g_signal_connect(smiley->loader, "closed", G_CALLBACK(pidgin_conv_custom_smiley_closed), smiley); | |
6082 | |
6083 return TRUE; | 5998 return TRUE; |
6084 } | 5999 } |
6085 | 6000 |
6086 loader = gdk_pixbuf_loader_new(); | 6001 smiley = gtk_imhtml_smiley_create(NULL, smile, FALSE, GTK_IMHTML_SMILEY_CUSTOM); |
6087 | |
6088 /* this is wrong, this file ought not call g_new on GtkIMHtmlSmiley */ | |
6089 /* Let gtk_imhtml have a gtk_imhtml_smiley_new function, and let | |
6090 GtkIMHtmlSmiley by opaque */ | |
6091 smiley = g_new0(GtkIMHtmlSmiley, 1); | |
6092 smiley->file = NULL; | |
6093 smiley->smile = g_strdup(smile); | |
6094 smiley->loader = loader; | |
6095 smiley->flags = smiley->flags | GTK_IMHTML_SMILEY_CUSTOM; | |
6096 | |
6097 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(pidgin_conv_custom_smiley_allocated), smiley); | |
6098 g_signal_connect(smiley->loader, "closed", G_CALLBACK(pidgin_conv_custom_smiley_closed), smiley); | |
6099 | |
6100 gtk_imhtml_associate_smiley(imhtml, sml, smiley); | 6002 gtk_imhtml_associate_smiley(imhtml, sml, smiley); |
6003 g_signal_connect_swapped(imhtml, "destroy", G_CALLBACK(gtk_imhtml_smiley_destroy), smiley); | |
6101 | 6004 |
6102 return TRUE; | 6005 return TRUE; |
6103 } | 6006 } |
6104 | 6007 |
6105 static gboolean | 6008 static gboolean |