Custom smileys: parse and display in toolbar

Wed, 02 Apr 2014 02:15:56 +0200

author
Tomasz Wasilczyk <twasilczyk@pidgin.im>
date
Wed, 02 Apr 2014 02:15:56 +0200
changeset 35716
80bedd712883
parent 35715
2aa79f05247e
child 35717
45bde03f86a6

Custom smileys: parse and display in toolbar

libpurple/smiley-custom.c file | annotate | diff | comparison | revisions
libpurple/smiley-list.c file | annotate | diff | comparison | revisions
libpurple/smiley-parser.c file | annotate | diff | comparison | revisions
libpurple/smiley-parser.h file | annotate | diff | comparison | revisions
pidgin/gtkwebview.c file | annotate | diff | comparison | revisions
pidgin/gtkwebviewtoolbar.c file | annotate | diff | comparison | revisions
pidgin/libpidgin.c file | annotate | diff | comparison | revisions
--- a/libpurple/smiley-custom.c	Wed Apr 02 01:08:17 2014 +0200
+++ b/libpurple/smiley-custom.c	Wed Apr 02 02:15:56 2014 +0200
@@ -22,6 +22,7 @@
 #include "smiley-custom.h"
 
 #include "debug.h"
+#include "smiley-list.h"
 
 #include <glib/gstdio.h>
 
@@ -31,7 +32,7 @@
 static gchar *smileys_dir;
 static gchar *smileys_index;
 
-static PurpleTrie *smileys_trie;
+static PurpleSmileyList *smileys_list;
 static GHashTable *smileys_table;
 static gboolean disable_write = FALSE;
 
@@ -83,6 +84,7 @@
 
 			g_hash_table_insert(smileys_table,
 				g_strdup(shortcut), smiley);
+			purple_smiley_list_add(smileys_list, smiley);
 		}
 
 		smiley_node = purple_xmlnode_get_next_twin(smiley_node);
@@ -216,6 +218,7 @@
 	g_free(file_path);
 
 	g_hash_table_insert(smileys_table, g_strdup(shortcut), smiley);
+	purple_smiley_list_add(smileys_list, smiley);
 	purple_smiley_custom_save();
 
 	return smiley;
@@ -239,6 +242,7 @@
 	}
 
 	g_unlink(purple_smiley_get_path(smiley));
+	purple_smiley_list_remove(smileys_list, smiley);
 	g_hash_table_remove(smileys_table, smiley_shortcut);
 	purple_smiley_custom_save();
 }
@@ -252,7 +256,9 @@
 PurpleTrie *
 purple_smiley_custom_get_trie(void)
 {
-	return smileys_trie;
+	if (g_hash_table_size(smileys_table) == 0)
+		return NULL;
+	return purple_smiley_list_get_trie(smileys_list);
 }
 
 
@@ -267,7 +273,7 @@
 		SMILEYS_DEFAULT_FOLDER, NULL);
 	smileys_index = g_build_filename(purple_user_dir(),
 		SMILEYS_INDEX_FILE, NULL);
-	smileys_trie = purple_trie_new();
+	smileys_list = purple_smiley_list_new();
 	smileys_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 		g_free, g_object_unref);
 
@@ -279,6 +285,6 @@
 {
 	g_free(smileys_dir);
 	g_free(smileys_index);
-	g_object_unref(smileys_trie);
+	g_object_unref(smileys_list);
 	g_hash_table_destroy(smileys_table);
 }
--- a/libpurple/smiley-list.c	Wed Apr 02 01:08:17 2014 +0200
+++ b/libpurple/smiley-list.c	Wed Apr 02 02:15:56 2014 +0200
@@ -23,6 +23,7 @@
 
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "smiley-parser.h"
 #include "trie.h"
 
 #define PURPLE_SMILEY_LIST_GET_PRIVATE(obj) \
@@ -94,6 +95,8 @@
 	PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
 	const gchar *smiley_path;
 	gboolean succ;
+	gchar *tmp = NULL;
+	const gchar *shortcut;
 
 	g_return_val_if_fail(priv != NULL, FALSE);
 	g_return_val_if_fail(PURPLE_IS_SMILEY(smiley), FALSE);
@@ -104,8 +107,11 @@
 		return FALSE;
 	}
 
-	succ = purple_trie_add(priv->trie,
-		purple_smiley_get_shortcut(smiley), smiley);
+	shortcut = purple_smiley_get_shortcut(smiley);
+	if (purple_smiley_parse_escape())
+		shortcut = tmp = g_markup_escape_text(shortcut, -1);
+	succ = purple_trie_add(priv->trie, shortcut, smiley);
+	g_free(tmp);
 	if (!succ)
 		return FALSE;
 
--- a/libpurple/smiley-parser.c	Wed Apr 02 01:08:17 2014 +0200
+++ b/libpurple/smiley-parser.c	Wed Apr 02 02:15:56 2014 +0200
@@ -21,8 +21,32 @@
 
 #include "smiley-parser.h"
 
+#include "smiley-custom.h"
 #include "smiley-theme.h"
 
+static gboolean escape_checked = FALSE;
+static gboolean escape_value;
+
+gboolean
+purple_smiley_parse_escape(void)
+{
+	GHashTable *ui_info;
+
+	if (escape_checked)
+		return escape_value;
+
+	ui_info = purple_core_get_ui_info();
+	if (!ui_info)
+		escape_value = FALSE;
+	else {
+		escape_value = GPOINTER_TO_INT(g_hash_table_lookup(ui_info,
+			"smiley-parser-escape"));
+	}
+
+	escape_checked = TRUE;
+	return escape_value;
+}
+
 static gboolean purple_smiley_parse_cb(GString *out, const gchar *word,
 	gpointer _smiley, gpointer _unused)
 {
@@ -38,24 +62,42 @@
 purple_smiley_parse(const gchar *message, gpointer ui_data)
 {
 	PurpleSmileyTheme *theme;
-	PurpleSmileyList *theme_smileys;
-	PurpleTrie *theme_trie;
+	PurpleSmileyList *theme_smileys = NULL;
+	PurpleTrie *theme_trie = NULL, *custom_trie;
+	GSList *tries = NULL, tries_theme, tries_custom;
 
 	if (message == NULL || message[0] == '\0')
 		return g_strdup(message);
 
+	custom_trie = purple_smiley_custom_get_trie();
+
 	theme = purple_smiley_theme_get_current();
-	if (theme == NULL)
-		return g_strdup(message);
+	if (theme != NULL)
+		theme_smileys = purple_smiley_theme_get_smileys(theme, ui_data);
 
-	theme_smileys = purple_smiley_theme_get_smileys(theme, ui_data);
-	if (theme_smileys == NULL)
+	if (theme_smileys != NULL)
+		theme_trie = purple_smiley_list_get_trie(theme_smileys);
+
+	if (theme_trie == NULL && custom_trie == NULL)
 		return g_strdup(message);
 
-	theme_trie = purple_smiley_list_get_trie(theme_smileys);
-	g_return_val_if_fail(theme_trie != NULL, g_strdup(message));
+	/* Create a tries list on stack. */
+	tries_theme.data = theme_trie;
+	tries_custom.data = custom_trie;
+	tries_theme.next = tries_custom.next = NULL;
+	if (custom_trie != NULL)
+		tries = &tries_custom;
+	if (theme_trie != NULL) {
+		if (tries)
+			tries->next = &tries_theme;
+		else
+			tries = &tries_theme;
+	}
+
+	/* XXX: should we parse custom smileys,
+	 * if protocol doesn't support it? */
 
 	/* TODO: don't replace text within tags, ie. <span style=":)"> */
-	return purple_trie_replace(theme_trie, message,
+	return purple_trie_multi_replace(tries, message,
 		purple_smiley_parse_cb, NULL);
 }
--- a/libpurple/smiley-parser.h	Wed Apr 02 01:08:17 2014 +0200
+++ b/libpurple/smiley-parser.h	Wed Apr 02 02:15:56 2014 +0200
@@ -24,6 +24,9 @@
 
 #include "purple.h"
 
+gboolean
+purple_smiley_parse_escape(void);
+
 gchar *
 purple_smiley_parse(const gchar *message, gpointer ui_data);
 
--- a/pidgin/gtkwebview.c	Wed Apr 02 01:08:17 2014 +0200
+++ b/pidgin/gtkwebview.c	Wed Apr 02 02:15:56 2014 +0200
@@ -1884,7 +1884,8 @@
 	PidginWebViewPriv *priv = PIDGIN_WEBVIEW_GET_PRIVATE(webview);
 
 	g_return_if_fail(priv != NULL);
-	g_return_if_fail(priv->toolbar != NULL);
+	if (priv->toolbar == NULL)
+		return;
 
 	pidgin_webviewtoolbar_switch_active_conversation(priv->toolbar, conv);
 }
--- a/pidgin/gtkwebviewtoolbar.c	Wed Apr 02 01:08:17 2014 +0200
+++ b/pidgin/gtkwebviewtoolbar.c	Wed Apr 02 02:15:56 2014 +0200
@@ -27,6 +27,7 @@
 #include "prefs.h"
 #include "request.h"
 #include "pidginstock.h"
+#include "smiley-custom.h"
 #include "smiley-list.h"
 #include "util.h"
 #include "debug.h"
@@ -821,13 +822,11 @@
 {
 	PidginWebViewToolbarPriv *priv = PIDGIN_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar);
 	PurpleSmileyList *smileys_from_theme;
-	GList *unique_smileys;
+	GList *theme_smileys, *custom_smileys = NULL;
+	PidginWebViewButtons webview_format;
 
 	GtkWidget *dialog, *vbox;
 	GtkWidget *smiley_table = NULL;
-#if 0
-	const GSList *custom_smileys = NULL;
-#endif
 	gboolean supports_custom = FALSE;
 	GtkRequisition req;
 	GtkWidget *scrolled, *viewport;
@@ -838,36 +837,30 @@
 		return;
 	}
 
+	webview_format = pidgin_webview_get_format_functions(
+		PIDGIN_WEBVIEW(toolbar->webview));
+
 	smileys_from_theme = pidgin_smiley_theme_for_conv(priv->active_conv);
-	unique_smileys = purple_smiley_list_get_unique(smileys_from_theme);
+	theme_smileys = purple_smiley_list_get_unique(smileys_from_theme);
 	/* TODO: remove hidden */
 
-#if 0
-	supports_custom = (pidgin_webview_get_format_functions(PIDGIN_WEBVIEW(toolbar->webview)) & PIDGIN_WEBVIEW_CUSTOM_SMILEY);
-	if (toolbar->webview && supports_custom) {
-		const GSList *iterator = NULL;
-		custom_smileys = pidgin_smileys_get_all();
-
-		for (iterator = custom_smileys ; iterator ;
-			 iterator = g_slist_next(iterator)) {
-			PidginWebViewSmiley *smiley = (PidginWebViewSmiley *)iterator->data;
-			unique_smileys = g_slist_prepend(unique_smileys, smiley);
-		}
-	}
-#endif
+	supports_custom = (webview_format & PIDGIN_WEBVIEW_CUSTOM_SMILEY);
+	if (supports_custom)
+		custom_smileys = purple_smiley_custom_get_all();
 
 	dialog = pidgin_create_dialog(_("Smile!"), 0, "smiley_dialog", FALSE);
 	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
 	vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog), FALSE, 0);
 
-	if (unique_smileys != NULL) {
+	if (theme_smileys != NULL || custom_smileys != NULL) {
 		struct smiley_button_list *ls;
 		int max_line_width, num_lines, button_width = 0;
 
 		/* We use hboxes packed in a vbox */
 		ls = NULL;
 		max_line_width = 0;
-		num_lines = floor(sqrt(g_list_length(unique_smileys)));
+		num_lines = floor(sqrt(g_list_length(theme_smileys) +
+			g_list_length(custom_smileys)));
 		smiley_table = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
 
 		if (supports_custom) {
@@ -884,12 +877,12 @@
 
 #if 0
 		/* create list of smileys sorted by height */
-		while (unique_smileys) {
-			PidginWebViewSmiley *smiley = (PidginWebViewSmiley *)unique_smileys->data;
+		while (theme_smileys) {
+			PidginWebViewSmiley *smiley = (PidginWebViewSmiley *)theme_smileys->data;
 			if (!pidgin_webview_smiley_get_hidden(smiley)) {
 				ls = sort_smileys(ls, toolbar, &max_line_width, smiley);
 			}
-			unique_smileys = g_slist_delete_link(unique_smileys, unique_smileys);
+			theme_smileys = g_slist_delete_link(theme_smileys, theme_smileys);
 		}
 #else
 		max_line_width = 300;
@@ -899,14 +892,14 @@
 		max_line_width = MAX(button_width, max_line_width / num_lines);
 
 		/* pack buttons of the list */
-		add_smiley_list(toolbar, smiley_table, unique_smileys, max_line_width);
-#if 0
+		add_smiley_list(toolbar, smiley_table, theme_smileys, max_line_width);
 		if (supports_custom) {
-			gtk_box_pack_start(GTK_BOX(smiley_table), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL), TRUE, FALSE, 0);
-			add_smiley_list(smiley_table, ls, max_line_width, TRUE);
+			gtk_box_pack_start(GTK_BOX(smiley_table),
+				gtk_separator_new(GTK_ORIENTATION_HORIZONTAL),
+				TRUE, FALSE, 0);
+			add_smiley_list(toolbar, smiley_table,
+				custom_smileys, max_line_width);
 		}
-#endif
-		g_list_free(unique_smileys);
 
 		gtk_widget_add_events(dialog, GDK_KEY_PRESS_MASK);
 	} else {
@@ -915,6 +908,9 @@
 		g_signal_connect(G_OBJECT(dialog), "button-press-event", (GCallback)smiley_dialog_input_cb, toolbar);
 	}
 
+	g_list_free(theme_smileys);
+	g_list_free(custom_smileys);
+
 	scrolled = pidgin_make_scrollable(smiley_table, GTK_POLICY_NEVER, GTK_POLICY_NEVER, GTK_SHADOW_NONE, -1, -1);
 	gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
 	gtk_widget_show(smiley_table);
--- a/pidgin/libpidgin.c	Wed Apr 02 01:08:17 2014 +0200
+++ b/pidgin/libpidgin.c	Wed Apr 02 02:15:56 2014 +0200
@@ -354,6 +354,8 @@
 		 */
 		g_hash_table_insert(ui_info, "prpl-aim-distid", GINT_TO_POINTER(1550));
 		g_hash_table_insert(ui_info, "prpl-icq-distid", GINT_TO_POINTER(1550));
+
+		g_hash_table_insert(ui_info, "smiley-parser-escape", GINT_TO_POINTER(TRUE));
 	}
 
 	return ui_info;

mercurial