# HG changeset patch # User Tim Ringenbach # Date 1126531541 0 # Node ID b47708f46a383310814e29fde06a82f4de82a71a # Parent 4fd0c3a663b83982995887617b8cd9376667a78d [gaim-migrate @ 13773] Here's the rest of that custom smiley receiving patch, with some changes from me. I'm still not all that happy with it, but that's probably not the author's fault, and I don't have time to take it further right now. committer: Tailor Script diff -r 4fd0c3a663b8 -r b47708f46a38 src/Makefile.am --- a/src/Makefile.am Mon Sep 12 06:50:29 2005 +0000 +++ b/src/Makefile.am Mon Sep 12 13:25:41 2005 +0000 @@ -313,6 +313,7 @@ gtksourceiter.h \ gtkstatusbox.h \ gtkstock.h \ + gtkthemes.h \ gtkutils.h \ internal.h \ gtkwhiteboard.h diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkconv.c --- a/src/gtkconv.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkconv.c Mon Sep 12 13:25:41 2005 +0000 @@ -60,6 +60,7 @@ #include "gtkpounce.h" #include "gtkprefs.h" #include "gtkprivacy.h" +#include "gtkthemes.h" #include "gtkutils.h" #include "gtkstock.h" @@ -5686,23 +5687,50 @@ GaimGtkConversation *gtkconv; GtkIMHtmlSmiley *smiley; GdkPixbufLoader *loader; - const char *sml; - - if (conv == NULL || smile == NULL) { + struct smiley_list *list; + const char *sml = NULL, *conv_sml; + + if (!conv || !smile || !*smile) { return FALSE; } - sml = gaim_account_get_protocol_name(conv->account); /* XXX this sucks */ + /* If smileys are off, return false */ + if (gaim_gtkthemes_smileys_disabled()) + return FALSE; + + /* If possible add this smiley to the current theme. + * The addition is only temporary: custom smilies aren't saved to disk. */ + conv_sml = gaim_account_get_protocol_name(conv->account); gtkconv = GAIM_GTK_CONVERSATION(conv); + + for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) { + if (!strcmp(list->sml, conv_sml)) { + sml = list->sml; + break; + } + } + smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); - /* TODO: implement changing a custom smiley in the middle of a conversation */ - if (smiley) { - return FALSE; + + if (!(smiley->flags & GTK_IMHTML_SMILEY_CUSTOM)) { + return FALSE; + } + + /* Close the old GdkPixbufAnimation, then create a new one for + * the smiley we are about to receive */ + g_object_unref(G_OBJECT(smiley->icon)); + + smiley->loader = gdk_pixbuf_loader_new(); + smiley->icon = gdk_pixbuf_loader_get_animation(smiley->loader); + if (smiley->icon) + g_object_ref(G_OBJECT(smiley->icon)); + + /* A custom smiley is already associated */ + return TRUE; } - loader = gdk_pixbuf_loader_new(); /* this is wrong, this file ought not call g_new on GtkIMHtmlSmiley */ @@ -5712,11 +5740,13 @@ smiley->file = NULL; smiley->smile = g_strdup(smile); smiley->loader = loader; + smiley->flags = smiley->flags | GTK_IMHTML_SMILEY_CUSTOM; smiley->icon = gdk_pixbuf_loader_get_animation(loader); if (smiley->icon) g_object_ref(G_OBJECT(smiley->icon)); + gtk_imhtml_associate_smiley(GTK_IMHTML(gtkconv->imhtml), sml, smiley); return TRUE; @@ -5752,6 +5782,11 @@ GtkIMHtmlSmiley *smiley; GdkPixbufLoader *loader; const char *sml; + GtkWidget *icon = NULL; + GtkTextChildAnchor *anchor = NULL; + GtkTextIter end; + GtkIMHtml *imhtml; + GSList *current = NULL; g_return_if_fail(conv != NULL); g_return_if_fail(smile != NULL); @@ -5768,6 +5803,36 @@ if (!loader) return; + smiley->icon = gdk_pixbuf_loader_get_animation(loader); + if (smiley->icon) + g_object_ref(G_OBJECT(smiley->icon)); + + for (current = smiley->anchors; current != NULL; current = g_slist_next(current)) { + + icon = gtk_image_new_from_animation(smiley->icon); + gtk_widget_show(icon); + + if (icon) { + anchor = GTK_TEXT_CHILD_ANCHOR(current->data); + + g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(gaim_unescape_html(smile)), g_free); + g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smile), g_free); + + gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(gtkconv->imhtml), icon, anchor); + } + + } + + g_slist_free(smiley->anchors); + smiley->anchors = NULL; + + /* Scroll to the end of the widget in case the smiley height was big... */ + /* FIXME: need to test this actually works, previous dealings with scrolling + * makes me question it */ + imhtml = GTK_IMHTML(gtkconv->imhtml); + gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(imhtml->text_buffer), &end); + gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(gtkconv->imhtml), &end, 0, TRUE, 0, 0); + gaim_debug_info("gtkconv", "About to close the smiley pixbuf\n"); gdk_pixbuf_loader_close(loader, NULL); @@ -5803,7 +5868,7 @@ g_timeout_add(0, (GSourceFunc)update_send_as_selection, win); - smiley_themeize(gtkconv->imhtml); + gaim_gtkthemes_smiley_themeize(gtkconv->imhtml); update_tab_icon(conv); } diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkdialogs.h --- a/src/gtkdialogs.h Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkdialogs.h Mon Sep 12 13:25:41 2005 +0000 @@ -67,31 +67,12 @@ GaimMessageFlags flags; }; -struct smiley_theme { - char *path; - char *name; - char *desc; - char *icon; - char *author; - - struct smiley_list *list; -}; - /* Globals in gtkmain.c */ extern int docklet_count; -/* Globals in gtkthemes.c */ -extern struct smiley_theme *current_smiley_theme; -extern GSList *smiley_themes; - /* Functions in session.c */ extern void session_init(gchar *, gchar *, gchar *); extern void session_end(); -/* Functions in gtkthemes.c */ -extern void smiley_themeize(GtkWidget *); -extern void smiley_theme_probe(); -extern void load_smiley_theme(const char *file, gboolean load); -extern GSList *get_proto_smileys(const char *id); #endif /* _GAIM_GTKDIALOGS_H_ */ diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkimhtml.c --- a/src/gtkimhtml.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkimhtml.c Mon Sep 12 13:25:41 2005 +0000 @@ -4311,6 +4311,7 @@ GtkWidget *icon = NULL; GtkTextChildAnchor *anchor; char *unescaped = gaim_unescape_html(smiley); + GtkIMHtmlSmiley *imhtml_smiley = gtk_imhtml_smiley_get(imhtml, sml, unescaped); if (imhtml->format_functions & GTK_IMHTML_SMILEY) { annipixbuf = gtk_smiley_tree_image(imhtml, sml, unescaped); @@ -4345,6 +4346,9 @@ gtk_widget_show(icon); gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor); + } else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) { + anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter); + imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor); } else { gtk_text_buffer_insert(imhtml->text_buffer, iter, smiley, -1); } diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkimhtml.h --- a/src/gtkimhtml.h Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkimhtml.h Mon Sep 12 13:25:41 2005 +0000 @@ -72,6 +72,10 @@ GTK_IMHTML_ALL = -1 } GtkIMHtmlButtons; +typedef enum { + GTK_IMHTML_SMILEY_CUSTOM = 1 << 0 +} GtkIMHtmlSmileyFlags; + struct _GtkIMHtml { GtkTextView text_view; GtkTextBuffer *text_buffer; @@ -155,6 +159,8 @@ GdkPixbufAnimation *icon; gboolean hidden; GdkPixbufLoader *loader; + GSList *anchors; + GtkIMHtmlSmileyFlags flags; }; struct _GtkIMHtmlScalable { diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkimhtmltoolbar.c --- a/src/gtkimhtmltoolbar.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkimhtmltoolbar.c Mon Sep 12 13:25:41 2005 +0000 @@ -34,6 +34,7 @@ #include "gtkdialogs.h" #include "gtkimhtmltoolbar.h" +#include "gtkthemes.h" #include "gtkutils.h" static GtkHBoxClass *parent_class = NULL; @@ -652,9 +653,9 @@ } if (toolbar->sml) - smileys = get_proto_smileys(toolbar->sml); + smileys = gaim_gtkthemes_get_proto_smileys(toolbar->sml); else - smileys = get_proto_smileys(NULL); + smileys = gaim_gtkthemes_get_proto_smileys(NULL); while(smileys) { GtkIMHtmlSmiley *smiley = smileys->data; diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkmain.c --- a/src/gtkmain.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkmain.c Mon Sep 12 13:25:41 2005 +0000 @@ -57,6 +57,7 @@ #include "gtkroomlist.h" #include "gtksavedstatuses.h" #include "gtksound.h" +#include "gtkthemes.h" #include "gtkutils.h" #include "gtkstock.h" #include "gtkwhiteboard.h" @@ -215,13 +216,7 @@ char *icon_path; #endif - if (current_smiley_theme == NULL) { - smiley_theme_probe(); - if (smiley_themes != NULL) { - struct smiley_theme *smile = smiley_themes->data; - load_smiley_theme(smile->path, TRUE); - } - } + gaim_gtkthemes_init(); gaim_gtk_blist_setup_sort_methods(); diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkprefs.c --- a/src/gtkprefs.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkprefs.c Mon Sep 12 13:25:41 2005 +0000 @@ -46,6 +46,7 @@ #include "gtkpluginpref.h" #include "gtkprefs.h" #include "gtksound.h" +#include "gtkthemes.h" #include "gtkutils.h" #include "gtkstock.h" @@ -478,12 +479,11 @@ int ind = 0; - smiley_theme_probe(); - - if (!smiley_themes) + gaim_gtkthemes_smiley_theme_probe(); + + if (!(themes = smiley_themes)) return NULL; - themes = smiley_themes; gtk_list_store_clear(smiley_theme_store); @@ -702,7 +702,7 @@ view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(smiley_theme_store)); - gtk_drag_dest_set(view, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, + gtk_drag_dest_set(view, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE); g_signal_connect(G_OBJECT(view), "drag_data_received", G_CALLBACK(theme_dnd_recv), smiley_theme_store); @@ -1832,7 +1832,7 @@ static GtkWidget *plugin_description=NULL, *plugin_details=NULL; -static void prefs_plugin_sel (GtkTreeSelection *sel, GtkTreeModel *model) +static void prefs_plugin_sel (GtkTreeSelection *sel, GtkTreeModel *model) { gchar *buf, *pname, *perr, *pdesc, *pauth, *pweb; GtkTreeIter iter; @@ -1845,11 +1845,11 @@ plug = g_value_get_pointer(&val); pname = g_markup_escape_text(_(plug->info->name), -1); - pdesc = (plug->info->description) ? + pdesc = (plug->info->description) ? g_markup_escape_text(_(plug->info->description), -1) : NULL; pauth = (plug->info->author) ? g_markup_escape_text(_(plug->info->author), -1) : NULL; - pweb = (plug->info->homepage) ? + pweb = (plug->info->homepage) ? g_markup_escape_text(_(plug->info->homepage), -1) : NULL; if (plug->error != NULL) { @@ -2229,7 +2229,7 @@ gpointer data) { if (!strcmp(name, "/gaim/gtk/smileys/theme")) - load_smiley_theme((const char *)value, TRUE); + gaim_gtkthemes_load_smiley_theme((const char *)value, TRUE); } void diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkthemes.c --- a/src/gtkthemes.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkthemes.c Mon Sep 12 13:25:41 2005 +0000 @@ -4,7 +4,7 @@ * Gaim is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -31,22 +31,25 @@ #include "gtkconv.h" #include "gtkdialogs.h" #include "gtkimhtml.h" - -struct smiley_list { - char *sml; - GSList *smileys; - struct smiley_list *next; -}; +#include "gtkthemes.h" GSList *smiley_themes = NULL; struct smiley_theme *current_smiley_theme; -void smiley_themeize(GtkWidget *imhtml) +gboolean gaim_gtkthemes_smileys_disabled() +{ + if (!current_smiley_theme) + return 1; + + return strcmp(current_smiley_theme->name, "none") == 0; +} + +void gaim_gtkthemes_smiley_themeize(GtkWidget *imhtml) { struct smiley_list *list; if (!current_smiley_theme) return; - + gtk_imhtml_remove_smileys(GTK_IMHTML(imhtml)); list = current_smiley_theme->list; while (list) { @@ -60,7 +63,7 @@ } } -void load_smiley_theme(const char *file, gboolean load) +void gaim_gtkthemes_load_smiley_theme(const char *file, gboolean load) { FILE *f = g_fopen(file, "r"); char buf[256]; @@ -196,8 +199,8 @@ GaimConversation *conv = cnv->data; if (GAIM_IS_GTK_CONVERSATION(conv)) { - smiley_themeize(GAIM_GTK_CONVERSATION(conv)->imhtml); - smiley_themeize(GAIM_GTK_CONVERSATION(conv)->entry); + gaim_gtkthemes_smiley_themeize(GAIM_GTK_CONVERSATION(conv)->imhtml); + gaim_gtkthemes_smiley_themeize(GAIM_GTK_CONVERSATION(conv)->entry); } } } @@ -206,7 +209,7 @@ fclose(f); } -void smiley_theme_probe() +void gaim_gtkthemes_smiley_theme_probe() { GDir *dir; const gchar *file; @@ -227,7 +230,7 @@ * We set the second argument to FALSE so that it doesn't load * the theme yet. */ - load_smiley_theme(path, FALSE); + gaim_gtkthemes_load_smiley_theme(path, FALSE); g_free(path); } g_dir_close(dir); @@ -238,7 +241,7 @@ } } -GSList *get_proto_smileys(const char *id) { +GSList *gaim_gtkthemes_get_proto_smileys(const char *id) { GaimPlugin *proto; struct smiley_list *list, *def; @@ -263,3 +266,14 @@ return list ? list->smileys : def->smileys; } + +void gaim_gtkthemes_init() +{ + if (current_smiley_theme == NULL) { + gaim_gtkthemes_smiley_theme_probe(); + if (smiley_themes != NULL) { + struct smiley_theme *smile = smiley_themes->data; + gaim_gtkthemes_load_smiley_theme(smile->path, TRUE); + } + } +} diff -r 4fd0c3a663b8 -r b47708f46a38 src/gtkutils.c --- a/src/gtkutils.c Mon Sep 12 06:50:29 2005 +0000 +++ b/src/gtkutils.c Mon Sep 12 13:25:41 2005 +0000 @@ -57,6 +57,7 @@ #include "gtkdialogs.h" #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" +#include "gtkthemes.h" #include "gtkutils.h" static guint accels_save_timer = 0; @@ -93,7 +94,7 @@ g_signal_connect(G_OBJECT(imhtml), "url_clicked", G_CALLBACK(url_clicked_cb), NULL); - smiley_themeize(imhtml); + gaim_gtkthemes_smiley_themeize(imhtml); gtk_imhtml_set_funcs(GTK_IMHTML(imhtml), >kimhtml_cbs); } @@ -241,7 +242,7 @@ gtk_label_set_pattern(GTK_LABEL(label), "_"); gtk_container_add(GTK_CONTAINER(menuitem), label); gtk_widget_show(label); -/* FIXME: Go back and fix this +/* FIXME: Go back and fix this gtk_widget_add_accelerator(menuitem, "activate", accel, str[0], GDK_MOD1_MASK, GTK_ACCEL_LOCKED); */ @@ -1206,17 +1207,17 @@ monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y); push_in = FALSE; - + /* * The placement of popup menus horizontally works like this (with * RTL in parentheses) * * - If there is enough room to the right (left) of the mouse cursor, * position the menu there. - * - * - Otherwise, if if there is enough room to the left (right) of the + * + * - Otherwise, if if there is enough room to the left (right) of the * mouse cursor, position the menu there. - * + * * - Otherwise if the menu is smaller than the monitor, position it * on the side of the mouse cursor that has the most space available * @@ -1236,7 +1237,7 @@ /* position horizontally */ /* the amount of space we need to position the menu. Note the - * menu is offset "xthickness" pixels + * menu is offset "xthickness" pixels */ needed_width = requisition.width - xthickness; @@ -1300,7 +1301,7 @@ *y = *y - ythickness; else *y = *y + ythickness - requisition.height + 1; - + *y = CLAMP (*y, monitor.y, monitor.y + monitor.height - requisition.height); }