pidgin/gtkconv.c

branch
soc.2013.gobjectification.plugins
changeset 37133
832cd077145e
parent 37128
7ffe330ea8ea
parent 35788
afa6d777bc7c
child 37134
07746c9a04bf
--- a/pidgin/gtkconv.c	Thu Apr 03 09:37:53 2014 +0530
+++ b/pidgin/gtkconv.c	Mon Apr 07 20:02:22 2014 +0530
@@ -42,6 +42,7 @@
 #include "plugins.h"
 #include "protocol.h"
 #include "request.h"
+#include "smiley-parser.h"
 #include "theme-loader.h"
 #include "theme-manager.h"
 #include "util.h"
@@ -60,12 +61,10 @@
 #include "gtkpounce.h"
 #include "gtkprefs.h"
 #include "gtkprivacy.h"
-#include "gtkthemes.h"
 #include "gtkutils.h"
 #include "gtkwebview.h"
 #include "pidginstock.h"
 #include "pidgintooltip.h"
-#include "smileyparser.h"
 
 #include "gtknickcolors.h"
 
@@ -139,9 +138,6 @@
 #define BUDDYICON_SIZE_MIN    32
 #define BUDDYICON_SIZE_MAX    96
 
-/* Undef this to turn off "custom-smiley" debug messages */
-#define DEBUG_CUSTOM_SMILEY
-
 #define LUMINANCE(c) (float)((0.3*(c.red))+(0.59*(c.green))+(0.11*(c.blue)))
 
 /* From http://www.w3.org/TR/AERT#color-contrast */
@@ -2355,7 +2351,6 @@
 	PidginConversation *gtkconv;
 	PurpleConversation *old_conv;
 	PidginWebView *entry;
-	const char *protocol_name;
 	PurpleConnectionFlags features;
 
 	g_return_if_fail(conv != NULL);
@@ -2372,13 +2367,14 @@
 	purple_conversation_close_logs(old_conv);
 	gtkconv->active_conv = conv;
 
+	pidgin_webview_switch_active_conversation(
+		PIDGIN_WEBVIEW(gtkconv->entry), conv);
+	pidgin_webview_switch_active_conversation(
+		PIDGIN_WEBVIEW(gtkconv->webview), conv);
 	purple_conversation_set_logging(conv,
 		gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu->logging)));
 
 	entry = PIDGIN_WEBVIEW(gtkconv->entry);
-	protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv));
-	pidgin_webview_set_protocol_name(entry, protocol_name);
-	pidgin_webview_set_protocol_name(PIDGIN_WEBVIEW(gtkconv->webview), protocol_name);
 
 	features = purple_conversation_get_features(conv);
 	if (!(features & PURPLE_CONNECTION_FLAG_HTML))
@@ -5713,8 +5709,6 @@
 
 	_pidgin_widget_set_accessible_name(frame, "Message Input");
 	gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
-	pidgin_webview_set_protocol_name(PIDGIN_WEBVIEW(gtkconv->entry),
-			purple_account_get_protocol_name(purple_conversation_get_account(conv)));
 
 	g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
 	                 G_CALLBACK(entry_popup_menu_cb), gtkconv);
@@ -5767,8 +5761,9 @@
 		PidginConversation *gtkconv = NULL;
 		PurpleAccount *buddyaccount;
 		const char *buddyname;
-
-		n = *(PurpleBlistNode **) data;
+		PurpleBlistNode **data_val = (gpointer)data;
+
+		n = *data_val;
 
 		if (PURPLE_IS_CONTACT(n))
 			b = purple_contact_get_priority_buddy((PurpleContact*)n);
@@ -6087,6 +6082,10 @@
 		pidgin_webview_show_toolbar(PIDGIN_WEBVIEW(gtkconv->entry));
 	else
 		pidgin_webview_hide_toolbar(PIDGIN_WEBVIEW(gtkconv->entry));
+	pidgin_webview_switch_active_conversation(
+		PIDGIN_WEBVIEW(gtkconv->entry), conv);
+	pidgin_webview_switch_active_conversation(
+		PIDGIN_WEBVIEW(gtkconv->webview), conv);
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons"))
 		gtk_widget_show(gtkconv->infopane_hbox);
@@ -6111,9 +6110,6 @@
 	{
 		gtkconv->nick_colors = g_array_ref(generated_nick_colors);
 	}
-
-	if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY)
-		pidgin_themes_smiley_themeize_custom(gtkconv->entry);
 }
 
 static void
@@ -6584,6 +6580,94 @@
 	return g_string_free(str, FALSE);
 }
 
+static gulong
+pidgin_smiley_get_unique_id(PurpleSmiley *smiley)
+{
+	static gulong max_id = 0;
+	gulong id;
+	g_return_val_if_fail(smiley != NULL, 0);
+
+	id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(smiley),
+		"pidgin-conv-smiley-unique-id"));
+	if (id != 0)
+		return id;
+
+	id = ++max_id;
+
+	g_object_set_data(G_OBJECT(smiley), "pidgin-conv-smiley-unique-id",
+		GINT_TO_POINTER(id));
+
+	return id;
+}
+
+static void
+pidgin_conv_remote_smiley_got(PurpleSmiley *smiley, gpointer _conv)
+{
+	PurpleConversation *conv = _conv;
+	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+	PurpleStoredImage *img;
+	gulong smiley_id;
+	int image_id;
+	gchar *js;
+
+	if (!gtkconv)
+		return;
+
+	img = purple_smiley_get_image(smiley);
+	smiley_id = pidgin_smiley_get_unique_id(smiley);
+	image_id = purple_imgstore_add_with_id(img);
+
+	purple_debug_info("gtkconv", "Smiley '%s' (%ld) is ready for display",
+		purple_smiley_get_shortcut(smiley), smiley_id);
+
+	js = g_strdup_printf("emoticonIsReady(%ld, '"
+		PURPLE_STORED_IMAGE_PROTOCOL "%d')", smiley_id, image_id);
+	pidgin_webview_safe_execute_script(
+		PIDGIN_WEBVIEW(gtkconv->webview), js);
+	g_free(js);
+}
+
+static gboolean
+pidgin_conv_write_smiley(GString *out, PurpleSmiley *smiley,
+	PurpleConversation *conv, gpointer _proto_name)
+{
+	gchar *escaped_shortcut;
+	const gchar *path = purple_smiley_get_path(smiley);
+	const gchar *path_prefix = "";
+
+#ifdef _WIN32
+	path_prefix = "file:///";
+#endif
+
+	escaped_shortcut = g_markup_escape_text(
+		purple_smiley_get_shortcut(smiley), -1);
+
+	if (purple_smiley_is_ready(smiley) && path) {
+		g_string_append_printf(out,
+			"<img class=\"emoticon\" alt=\"%s\" title=\"%s\" "
+			"src=\"%s%s\" />", escaped_shortcut,
+			escaped_shortcut, path_prefix, path);
+	} else if (purple_smiley_is_ready(smiley) && !path) {
+		PurpleStoredImage *img = purple_smiley_get_image(smiley);
+		int imgid = purple_imgstore_add_with_id(img);
+
+		g_string_append_printf(out, "<img class=\"emoticon\" "
+			"alt=\"%s\" title=\"%s\" src=\""
+			PURPLE_STORED_IMAGE_PROTOCOL "%d\" />",
+			escaped_shortcut, escaped_shortcut, imgid);
+	} else {
+		g_string_append_printf(out, "<span class=\"emoticon pending "
+			"emoticon-id-%ld\">%s</span>",
+			pidgin_smiley_get_unique_id(smiley), escaped_shortcut);
+		g_signal_connect_object(smiley, "ready",
+			G_CALLBACK(pidgin_conv_remote_smiley_got), conv, 0);
+	}
+
+	g_free(escaped_shortcut);
+
+	return TRUE;
+}
+
 static void
 pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias,
 						const char *message, PurpleMessageFlags flags,
@@ -6710,7 +6794,9 @@
 	gtkconv->last_flags = flags;
 	gtkconv->last_conversed = conv;
 
-	smileyed = pidgin_smiley_parse_markup(displaying, purple_account_get_protocol_id(account));
+	smileyed = purple_smiley_parse(conv, displaying, (flags & PURPLE_MESSAGE_RECV),
+		pidgin_conv_write_smiley,
+		(gpointer)purple_account_get_protocol_name(account));
 	msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime);
 	escape = pidgin_webview_quote_js_string(msg ? msg : "");
 	script = g_strdup_printf("%s(%s)", func, escape);
@@ -6774,12 +6860,6 @@
 		gtk_font_options |= GTK_IMHTML_USE_POINTSIZE;
 	}
 
-	if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY))
-	{
-		/* We want to see our own smileys. Need to revert it after send*/
-		pidgin_themes_smiley_themeize_custom(gtkconv->webview);
-	}
-
 	/* TODO: These colors should not be hardcoded so log.c can use them */
 	if (flags & PURPLE_MESSAGE_RAW) {
 		pidgin_webview_append_html(PIDGIN_WEBVIEW(gtkconv->webview), message);
@@ -6935,15 +7015,6 @@
 		gtkconv_set_unseen(gtkconv, unseen);
 	}
 
-#if 0
-	if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_FLAG_ALLOW_CUSTOM_SMILEY))
-	{
-		/* Restore the smiley-data */
-		pidgin_themes_smiley_themeize(gtkconv->webview);
-	}
-#endif
-
-
 	/* on rejoin only request message history from after this message */
 	if (flags & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV) &&
 		PURPLE_IS_CHAT_CONVERSATION(conv)) {
@@ -7202,154 +7273,6 @@
 	return FALSE;
 }
 
-static gboolean
-add_custom_smiley_for_webview(PidginWebView *webview, const char *sml, const char *smile)
-{
-	PidginWebViewSmiley *smiley;
-
-	smiley = pidgin_webview_smiley_find(webview, sml, smile);
-
-	if (smiley) {
-		if (!(pidgin_webview_smiley_get_flags(smiley) & PIDGIN_WEBVIEW_SMILEY_CUSTOM))
-			return FALSE;
-
-		pidgin_webview_smiley_reload(smiley);
-		return TRUE;
-	}
-
-	smiley = pidgin_webview_smiley_create(NULL, smile, FALSE,
-	                                   PIDGIN_WEBVIEW_SMILEY_CUSTOM);
-	pidgin_webview_associate_smiley(webview, sml, smiley);
-	g_signal_connect_swapped(webview, "destroy",
-	                         G_CALLBACK(pidgin_webview_smiley_destroy), smiley);
-
-	return TRUE;
-}
-
-static gboolean
-pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote)
-{
-	PidginConversation *gtkconv;
-	struct PidginSmileyList *list;
-	const char *sml = NULL, *conv_sml;
-
-	if (!conv || !smile || !*smile) {
-		return FALSE;
-	}
-
-	/* If smileys are off, return false */
-	if (pidgin_themes_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 = purple_account_get_protocol_name(purple_conversation_get_account(conv));
-	gtkconv = PIDGIN_CONVERSATION(conv);
-
-	for (list = (struct PidginSmileyList *)current_smiley_theme->list; list; list = list->next) {
-		if (!strcmp(list->sml, conv_sml)) {
-			sml = list->sml;
-			break;
-		}
-	}
-
-	if (!add_custom_smiley_for_webview(PIDGIN_WEBVIEW(gtkconv->webview), sml, smile))
-		return FALSE;
-
-	if (!remote)	/* If it's a local custom smiley, then add it for the entry */
-		if (!add_custom_smiley_for_webview(PIDGIN_WEBVIEW(gtkconv->entry), sml, smile))
-			return FALSE;
-
-	return TRUE;
-}
-
-static void
-pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile,
-                                      const guchar *data, gsize size)
-{
-/* TODO WEBKIT */
-#if 0
-	PidginConversation *gtkconv;
-	GtkIMHtmlSmiley *smiley;
-	const char *sml;
-	GError *error = NULL;
-
-	sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
-	gtkconv = PIDGIN_CONVERSATION(conv);
-	smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
-
-	if (!smiley)
-		return;
-
-	smiley->data = g_realloc(smiley->data, smiley->datasize + size);
-	g_memmove((guchar *)smiley->data + smiley->datasize, data, size);
-	smiley->datasize += size;
-
-	if (!smiley->loader)
-		return;
-
-	if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) {
-		purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() "
-				"failed with size=%" G_GSIZE_FORMAT ": %s\n", size,
-				error ? error->message : "(no error message)");
-		if (error)
-			g_error_free(error);
-		/* We must stop using the GdkPixbufLoader because trying to load
-		   certain invalid GIFs with at least gdk-pixbuf 2.23.3 can return
-		   a GdkPixbuf that will cause some operations (like
-		   gdk_pixbuf_scale_simple()) to consume memory in an infinite loop.
-		   But we also don't want to set smiley->loader to NULL because our
-		   code might expect it to be set.  So create a new loader. */
-		g_object_unref(G_OBJECT(smiley->loader));
-		smiley->loader = gdk_pixbuf_loader_new();
-	}
-#endif /* if 0 */
-}
-
-static void
-pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile)
-{
-/* TODO WEBKIT */
-#if 0
-	PidginConversation *gtkconv;
-	GtkIMHtmlSmiley *smiley;
-	const char *sml;
-	GError *error = NULL;
-
-	g_return_if_fail(conv  != NULL);
-	g_return_if_fail(smile != NULL);
-
-	sml = purple_account_get_protocol_name(purple_conversation_get_account(conv));
-	gtkconv = PIDGIN_CONVERSATION(conv);
-	smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile);
-
-	if (!smiley)
-		return;
-
-	if (!smiley->loader)
-		return;
-
-	purple_debug_info("gtkconv", "About to close the smiley pixbuf\n");
-
-	if (!gdk_pixbuf_loader_close(smiley->loader, &error) || error) {
-		purple_debug_warning("gtkconv", "gdk_pixbuf_loader_close() "
-				"failed: %s\n",
-				error ? error->message : "(no error message)");
-		if (error)
-			g_error_free(error);
-		/* We must stop using the GdkPixbufLoader because if we tried to
-		   load certain invalid GIFs with all current versions of GDK (as
-		   of 2011-06-15) then it's possible the loader will contain data
-		   that could cause some operations (like gdk_pixbuf_scale_simple())
-		   to consume memory in an infinite loop.  But we also don't want
-		   to set smiley->loader to NULL because our code might expect it
-		   to be set.  So create a new loader. */
-		g_object_unref(G_OBJECT(smiley->loader));
-		smiley->loader = gdk_pixbuf_loader_new();
-	}
-#endif /* if 0 */
-}
-
 static void
 pidgin_conv_send_confirm(PurpleConversation *conv, const char *message)
 {
@@ -7491,8 +7414,6 @@
 			buttons &= ~PIDGIN_WEBVIEW_CUSTOM_SMILEY;
 
 		pidgin_webview_set_format_functions(PIDGIN_WEBVIEW(gtkconv->entry), buttons);
-		if (account != NULL)
-			pidgin_webview_set_protocol_name(PIDGIN_WEBVIEW(gtkconv->entry), purple_account_get_protocol_id(account));
 
 		/* Deal with menu items */
 		gtk_action_set_sensitive(win->menu->view_log, TRUE);
@@ -7627,11 +7548,6 @@
 		}
 	}
 
-#if 0
-	if (fields & PIDGIN_CONV_SMILEY_THEME)
-		pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview);
-#endif
-
 	if ((fields & PIDGIN_CONV_COLORIZE_TITLE) ||
 			(fields & PIDGIN_CONV_SET_TITLE) ||
 			(fields & PIDGIN_CONV_TOPIC))
@@ -7749,7 +7665,7 @@
 		gtk_label_set_text(GTK_LABEL(gtkconv->menu_label), title);
 		if (pidgin_conv_window_is_active_conversation(conv)) {
 			const char* current_title = gtk_window_get_title(GTK_WINDOW(win->window));
-			if (current_title == NULL || strcmp(current_title, title) != 0)
+			if (current_title == NULL || g_strcmp0(current_title, title) != 0)
 				gtk_window_set_title(GTK_WINDOW(win->window), title);
 		}
 
@@ -7846,9 +7762,6 @@
 	pidgin_conv_chat_update_user,     /* chat_update_user     */
 	pidgin_conv_present_conversation, /* present              */
 	pidgin_conv_has_focus,            /* has_focus            */
-	pidgin_conv_custom_smiley_add,    /* custom_smiley_add    */
-	pidgin_conv_custom_smiley_write,  /* custom_smiley_write  */
-	pidgin_conv_custom_smiley_close,  /* custom_smiley_close  */
 	pidgin_conv_send_confirm,         /* send_confirm         */
 	NULL,
 	NULL,
@@ -8784,6 +8697,7 @@
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike", FALSE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck", TRUE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", TRUE);
+	/* TODO: it's about *remote* smileys, not local ones */
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/resize_custom_smileys", TRUE);
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/custom_smileys_size", 96);
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines", 2);

mercurial