| 157 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); |
157 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); |
| 158 static void update_typing_icon(PidginConversation *gtkconv); |
158 static void update_typing_icon(PidginConversation *gtkconv); |
| 159 static void update_typing_message(PidginConversation *gtkconv, const char *message); |
159 static void update_typing_message(PidginConversation *gtkconv, const char *message); |
| 160 static const char *item_factory_translate_func (const char *path, gpointer func_data); |
160 static const char *item_factory_translate_func (const char *path, gpointer func_data); |
| 161 gboolean pidgin_conv_has_focus(PurpleConversation *conv); |
161 gboolean pidgin_conv_has_focus(PurpleConversation *conv); |
| 162 static void pidgin_conv_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data); |
|
| 163 static void pidgin_conv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data); |
|
| 164 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); |
162 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); |
| 165 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); |
163 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); |
| 166 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
164 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
| 167 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); |
165 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); |
| 168 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); |
166 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); |
| 5644 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; |
5646 gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; |
| 5645 } |
5647 } |
| 5646 |
5648 |
| 5647 if (!(flags & PURPLE_MESSAGE_RECV)) |
5649 if (!(flags & PURPLE_MESSAGE_RECV)) |
| 5648 { |
5650 { |
| 5649 /* Temporarily revert to the original smiley-data to avoid showing up |
5651 /* We want to see our own smileys. Need to revert it after send*/ |
| 5650 * custom smileys of the buddy when sending message |
5652 pidgin_themes_smiley_themeize_custom(gtkconv->imhtml); |
| 5651 */ |
|
| 5652 tree = GTK_IMHTML(gtkconv->imhtml)->default_smilies; |
|
| 5653 GTK_IMHTML(gtkconv->imhtml)->default_smilies = |
|
| 5654 GTK_IMHTML(gtkconv->entry)->default_smilies; |
|
| 5655 smiley_data = GTK_IMHTML(gtkconv->imhtml)->smiley_data; |
|
| 5656 GTK_IMHTML(gtkconv->imhtml)->smiley_data = GTK_IMHTML(gtkconv->entry)->smiley_data; |
|
| 5657 } |
5653 } |
| 5658 |
5654 |
| 5659 /* TODO: These colors should not be hardcoded so log.c can use them */ |
5655 /* TODO: These colors should not be hardcoded so log.c can use them */ |
| 5660 if (flags & PURPLE_MESSAGE_RAW) { |
5656 if (flags & PURPLE_MESSAGE_RAW) { |
| 5661 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); |
5657 gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); |
| 6126 return TRUE; |
6121 return TRUE; |
| 6127 |
6122 |
| 6128 return FALSE; |
6123 return FALSE; |
| 6129 } |
6124 } |
| 6130 |
6125 |
| 6131 static void pidgin_conv_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data) |
|
| 6132 { |
|
| 6133 GtkIMHtmlSmiley *smiley; |
|
| 6134 |
|
| 6135 smiley = (GtkIMHtmlSmiley *)user_data; |
|
| 6136 smiley->icon = gdk_pixbuf_loader_get_animation(loader); |
|
| 6137 |
|
| 6138 if (smiley->icon) |
|
| 6139 g_object_ref(G_OBJECT(smiley->icon)); |
|
| 6140 #ifdef DEBUG_CUSTOM_SMILEY |
|
| 6141 purple_debug_info("custom-smiley", "pidgin_conv_custom_smiley_allocated(): got GdkPixbufAnimation %p for smiley '%s'\n", smiley->icon, smiley->smile); |
|
| 6142 #endif |
|
| 6143 } |
|
| 6144 |
|
| 6145 static void pidgin_conv_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data) |
|
| 6146 { |
|
| 6147 GtkIMHtmlSmiley *smiley; |
|
| 6148 GtkWidget *icon = NULL; |
|
| 6149 GtkTextChildAnchor *anchor = NULL; |
|
| 6150 GSList *current = NULL; |
|
| 6151 |
|
| 6152 smiley = (GtkIMHtmlSmiley *)user_data; |
|
| 6153 if (!smiley->imhtml) { |
|
| 6154 #ifdef DEBUG_CUSTOM_SMILEY |
|
| 6155 purple_debug_error("custom-smiley", "pidgin_conv_custom_smiley_closed(): orphan smiley found: %p\n", smiley); |
|
| 6156 #endif |
|
| 6157 g_object_unref(G_OBJECT(loader)); |
|
| 6158 smiley->loader = NULL; |
|
| 6159 return; |
|
| 6160 } |
|
| 6161 |
|
| 6162 for (current = smiley->anchors; current; current = g_slist_next(current)) { |
|
| 6163 |
|
| 6164 icon = gtk_image_new_from_animation(smiley->icon); |
|
| 6165 |
|
| 6166 #ifdef DEBUG_CUSTOM_SMILEY |
|
| 6167 purple_debug_info("custom-smiley", "pidgin_conv_custom_smiley_closed(): got GtkImage %p from GtkPixbufAnimation %p for smiley '%s'\n", |
|
| 6168 icon, smiley->icon, smiley->smile); |
|
| 6169 #endif |
|
| 6170 if (icon) { |
|
| 6171 GList *wids; |
|
| 6172 gtk_widget_show(icon); |
|
| 6173 |
|
| 6174 anchor = GTK_TEXT_CHILD_ANCHOR(current->data); |
|
| 6175 wids = gtk_text_child_anchor_get_widgets(anchor); |
|
| 6176 |
|
| 6177 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", purple_unescape_html(smiley->smile), g_free); |
|
| 6178 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley->smile), g_free); |
|
| 6179 |
|
| 6180 if (smiley->imhtml) { |
|
| 6181 if (wids) { |
|
| 6182 GList *children = gtk_container_get_children(GTK_CONTAINER(wids->data)); |
|
| 6183 g_list_foreach(children, (GFunc)gtk_widget_destroy, NULL); |
|
| 6184 g_list_free(children); |
|
| 6185 gtk_container_add(GTK_CONTAINER(wids->data), icon); |
|
| 6186 } else |
|
| 6187 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor); |
|
| 6188 } |
|
| 6189 g_list_free(wids); |
|
| 6190 } |
|
| 6191 |
|
| 6192 } |
|
| 6193 |
|
| 6194 g_slist_free(smiley->anchors); |
|
| 6195 smiley->anchors = NULL; |
|
| 6196 |
|
| 6197 g_object_unref(G_OBJECT(loader)); |
|
| 6198 smiley->loader = NULL; |
|
| 6199 } |
|
| 6200 |
|
| 6201 static gboolean |
6126 static gboolean |
| 6202 add_custom_smiley_for_imhtml(GtkIMHtml *imhtml, const char *sml, const char *smile) |
6127 add_custom_smiley_for_imhtml(GtkIMHtml *imhtml, const char *sml, const char *smile) |
| 6203 { |
6128 { |
| 6204 GtkIMHtmlSmiley *smiley; |
6129 GtkIMHtmlSmiley *smiley; |
| 6205 GdkPixbufLoader *loader; |
|
| 6206 |
6130 |
| 6207 smiley = gtk_imhtml_smiley_get(imhtml, sml, smile); |
6131 smiley = gtk_imhtml_smiley_get(imhtml, sml, smile); |
| 6208 |
6132 |
| 6209 if (smiley) { |
6133 if (smiley) { |
| 6210 |
|
| 6211 if (!(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) { |
6134 if (!(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) { |
| 6212 return FALSE; |
6135 return FALSE; |
| 6213 } |
6136 } |
| 6214 |
6137 gtk_imhtml_smiley_reload(smiley); |
| 6215 /* Close the old GdkPixbufAnimation, then create a new one for |
|
| 6216 * the smiley we are about to receive */ |
|
| 6217 g_object_unref(G_OBJECT(smiley->icon)); |
|
| 6218 |
|
| 6219 /* XXX: Is it necessary to _unref the loader first? */ |
|
| 6220 smiley->loader = gdk_pixbuf_loader_new(); |
|
| 6221 smiley->icon = NULL; |
|
| 6222 |
|
| 6223 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(pidgin_conv_custom_smiley_allocated), smiley); |
|
| 6224 g_signal_connect(smiley->loader, "closed", G_CALLBACK(pidgin_conv_custom_smiley_closed), smiley); |
|
| 6225 |
|
| 6226 return TRUE; |
6138 return TRUE; |
| 6227 } |
6139 } |
| 6228 |
6140 |
| 6229 loader = gdk_pixbuf_loader_new(); |
6141 smiley = gtk_imhtml_smiley_create(NULL, smile, FALSE, GTK_IMHTML_SMILEY_CUSTOM); |
| 6230 |
|
| 6231 /* this is wrong, this file ought not call g_new on GtkIMHtmlSmiley */ |
|
| 6232 /* Let gtk_imhtml have a gtk_imhtml_smiley_new function, and let |
|
| 6233 GtkIMHtmlSmiley by opaque */ |
|
| 6234 smiley = g_new0(GtkIMHtmlSmiley, 1); |
|
| 6235 smiley->file = NULL; |
|
| 6236 smiley->smile = g_strdup(smile); |
|
| 6237 smiley->loader = loader; |
|
| 6238 smiley->flags = smiley->flags | GTK_IMHTML_SMILEY_CUSTOM; |
|
| 6239 |
|
| 6240 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(pidgin_conv_custom_smiley_allocated), smiley); |
|
| 6241 g_signal_connect(smiley->loader, "closed", G_CALLBACK(pidgin_conv_custom_smiley_closed), smiley); |
|
| 6242 |
|
| 6243 gtk_imhtml_associate_smiley(imhtml, sml, smiley); |
6142 gtk_imhtml_associate_smiley(imhtml, sml, smiley); |
| |
6143 g_signal_connect_swapped(imhtml, "destroy", G_CALLBACK(gtk_imhtml_smiley_destroy), smiley); |
| 6244 |
6144 |
| 6245 return TRUE; |
6145 return TRUE; |
| 6246 } |
6146 } |
| 6247 |
6147 |
| 6248 static gboolean |
6148 static gboolean |
| 6462 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) |
6362 if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) |
| 6463 conv->features |= PURPLE_CONNECTION_NO_IMAGES; |
6363 conv->features |= PURPLE_CONNECTION_NO_IMAGES; |
| 6464 |
6364 |
| 6465 if(conv->features & PURPLE_CONNECTION_NO_IMAGES) |
6365 if(conv->features & PURPLE_CONNECTION_NO_IMAGES) |
| 6466 buttons &= ~GTK_IMHTML_IMAGE; |
6366 buttons &= ~GTK_IMHTML_IMAGE; |
| |
6367 |
| |
6368 if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) |
| |
6369 buttons |= GTK_IMHTML_CUSTOM_SMILEY; |
| |
6370 else |
| |
6371 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; |
| 6467 |
6372 |
| 6468 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); |
6373 gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->entry), buttons); |
| 6469 if (account != NULL) |
6374 if (account != NULL) |
| 6470 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); |
6375 gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); |
| 6471 |
6376 |