| 5327 } |
5327 } |
| 5328 |
5328 |
| 5329 if (flags & PURPLE_CONNECTION_NO_IMAGES) |
5329 if (flags & PURPLE_CONNECTION_NO_IMAGES) |
| 5330 buttons &= ~GTK_IMHTML_IMAGE; |
5330 buttons &= ~GTK_IMHTML_IMAGE; |
| 5331 |
5331 |
| |
5332 if (flags & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) |
| |
5333 buttons |= GTK_IMHTML_CUSTOM_SMILEY; |
| |
5334 else |
| |
5335 buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; |
| |
5336 |
| 5332 gtk_imhtml_set_format_functions(imhtml, buttons); |
5337 gtk_imhtml_set_format_functions(imhtml, buttons); |
| 5333 } |
5338 } |
| 5334 |
5339 |
| 5335 |
5340 /******* |
| |
5341 * GtkIMHtmlSmiley functions |
| |
5342 *******/ |
| |
5343 static void gtk_custom_smiley_allocated(GdkPixbufLoader *loader, gpointer user_data) |
| |
5344 { |
| |
5345 GtkIMHtmlSmiley *smiley; |
| |
5346 |
| |
5347 smiley = (GtkIMHtmlSmiley *)user_data; |
| |
5348 smiley->icon = gdk_pixbuf_loader_get_animation(loader); |
| |
5349 |
| |
5350 if (smiley->icon) |
| |
5351 g_object_ref(G_OBJECT(smiley->icon)); |
| |
5352 #ifdef DEBUG_CUSTOM_SMILEY |
| |
5353 purple_debug_info("custom-smiley", "gtk_custom_smiley_allocated(): got GdkPixbufAnimation %p for smiley '%s'\n", smiley->icon, smiley->smile); |
| |
5354 #endif |
| |
5355 } |
| |
5356 |
| |
5357 static void gtk_custom_smiley_closed(GdkPixbufLoader *loader, gpointer user_data) |
| |
5358 { |
| |
5359 GtkIMHtmlSmiley *smiley; |
| |
5360 GtkWidget *icon = NULL; |
| |
5361 GtkTextChildAnchor *anchor = NULL; |
| |
5362 GSList *current = NULL; |
| |
5363 |
| |
5364 smiley = (GtkIMHtmlSmiley *)user_data; |
| |
5365 if (!smiley->imhtml) { |
| |
5366 #ifdef DEBUG_CUSTOM_SMILEY |
| |
5367 purple_debug_error("custom-smiley", "gtk_custom_smiley_closed(): orphan smiley found: %p\n", smiley); |
| |
5368 #endif |
| |
5369 g_object_unref(G_OBJECT(loader)); |
| |
5370 smiley->loader = NULL; |
| |
5371 return; |
| |
5372 } |
| |
5373 |
| |
5374 for (current = smiley->anchors; current; current = g_slist_next(current)) { |
| |
5375 |
| |
5376 icon = gtk_image_new_from_animation(smiley->icon); |
| |
5377 |
| |
5378 #ifdef DEBUG_CUSTOM_SMILEY |
| |
5379 purple_debug_info("custom-smiley", "gtk_custom_smiley_closed(): got GtkImage %p from GtkPixbufAnimation %p for smiley '%s'\n", |
| |
5380 icon, smiley->icon, smiley->smile); |
| |
5381 #endif |
| |
5382 if (icon) { |
| |
5383 GList *wids; |
| |
5384 gtk_widget_show(icon); |
| |
5385 |
| |
5386 anchor = GTK_TEXT_CHILD_ANCHOR(current->data); |
| |
5387 wids = gtk_text_child_anchor_get_widgets(anchor); |
| |
5388 |
| |
5389 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", purple_unescape_html(smiley->smile), g_free); |
| |
5390 g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley->smile), g_free); |
| |
5391 |
| |
5392 if (smiley->imhtml) { |
| |
5393 if (wids) { |
| |
5394 GList *children = gtk_container_get_children(GTK_CONTAINER(wids->data)); |
| |
5395 g_list_foreach(children, (GFunc)gtk_widget_destroy, NULL); |
| |
5396 g_list_free(children); |
| |
5397 gtk_container_add(GTK_CONTAINER(wids->data), icon); |
| |
5398 } else |
| |
5399 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor); |
| |
5400 } |
| |
5401 g_list_free(wids); |
| |
5402 } |
| |
5403 |
| |
5404 } |
| |
5405 |
| |
5406 g_slist_free(smiley->anchors); |
| |
5407 smiley->anchors = NULL; |
| |
5408 |
| |
5409 g_object_unref(G_OBJECT(loader)); |
| |
5410 smiley->loader = NULL; |
| |
5411 } |
| |
5412 |
| |
5413 static void |
| |
5414 gtk_custom_smiley_size_prepared(GdkPixbufLoader *loader, gint width, gint height, gpointer data) |
| |
5415 { |
| |
5416 #define CUSTOM_SMILEY_SIZE 96 /* XXX: Should this be a theme setting? */ |
| |
5417 if (width <= CUSTOM_SMILEY_SIZE && height <= CUSTOM_SMILEY_SIZE) |
| |
5418 return; |
| |
5419 |
| |
5420 if (width >= height) { |
| |
5421 height = height * CUSTOM_SMILEY_SIZE / width; |
| |
5422 width = CUSTOM_SMILEY_SIZE; |
| |
5423 } else { |
| |
5424 width = width * CUSTOM_SMILEY_SIZE / height; |
| |
5425 height = CUSTOM_SMILEY_SIZE; |
| |
5426 } |
| |
5427 |
| |
5428 gdk_pixbuf_loader_set_size(loader, width, height); |
| |
5429 } |
| |
5430 |
| |
5431 void |
| |
5432 gtk_imhtml_smiley_reload(GtkIMHtmlSmiley *smiley) |
| |
5433 { |
| |
5434 if (smiley->icon) |
| |
5435 g_object_unref(smiley->icon); |
| |
5436 if (smiley->loader) |
| |
5437 g_object_unref(smiley->loader); /* XXX: does this crash? */ |
| |
5438 |
| |
5439 smiley->icon = NULL; |
| |
5440 smiley->loader = NULL; |
| |
5441 |
| |
5442 if (smiley->file) { |
| |
5443 /* We do not use the pixbuf loader for a smiley that can be loaded |
| |
5444 * from a file. (e.g., local custom smileys) |
| |
5445 */ |
| |
5446 return; |
| |
5447 } |
| |
5448 |
| |
5449 smiley->loader = gdk_pixbuf_loader_new(); |
| |
5450 |
| |
5451 g_signal_connect(smiley->loader, "area_prepared", G_CALLBACK(gtk_custom_smiley_allocated), smiley); |
| |
5452 g_signal_connect(smiley->loader, "closed", G_CALLBACK(gtk_custom_smiley_closed), smiley); |
| |
5453 g_signal_connect(smiley->loader, "size_prepared", G_CALLBACK(gtk_custom_smiley_size_prepared), smiley); |
| |
5454 } |
| |
5455 |
| |
5456 GtkIMHtmlSmiley *gtk_imhtml_smiley_create(const char *file, const char *shortcut, gboolean hide, |
| |
5457 GtkIMHtmlSmileyFlags flags) |
| |
5458 { |
| |
5459 GtkIMHtmlSmiley *smiley = g_new0(GtkIMHtmlSmiley, 1); |
| |
5460 smiley->file = g_strdup(file); |
| |
5461 smiley->smile = g_strdup(shortcut); |
| |
5462 smiley->hidden = hide; |
| |
5463 smiley->flags = flags; |
| |
5464 gtk_imhtml_smiley_reload(smiley); |
| |
5465 return smiley; |
| |
5466 } |
| |
5467 |
| |
5468 void gtk_imhtml_smiley_destroy(GtkIMHtmlSmiley *smiley) |
| |
5469 { |
| |
5470 g_free(smiley->smile); |
| |
5471 g_free(smiley->file); |
| |
5472 if (smiley->icon) |
| |
5473 g_object_unref(smiley->icon); |
| |
5474 if (smiley->loader) |
| |
5475 g_object_unref(smiley->loader); |
| |
5476 g_free(smiley); |
| |
5477 } |
| |
5478 |