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