Smileys: implement and use new parser, only themes for now

Tue, 01 Apr 2014 03:46:16 +0200

author
Tomasz Wasilczyk <twasilczyk@pidgin.im>
date
Tue, 01 Apr 2014 03:46:16 +0200
changeset 35709
0d7a84931572
parent 35708
8903e6402d5b
child 35710
c1361f7c382b

Smileys: implement and use new parser, only themes for now

libpurple/Makefile.am file | annotate | diff | comparison | revisions
libpurple/smiley-list.c file | annotate | diff | comparison | revisions
libpurple/smiley-list.h file | annotate | diff | comparison | revisions
libpurple/smiley-parser.c file | annotate | diff | comparison | revisions
libpurple/smiley-parser.h file | annotate | diff | comparison | revisions
libpurple/smiley-theme.c file | annotate | diff | comparison | revisions
libpurple/smiley-theme.h file | annotate | diff | comparison | revisions
libpurple/smiley.c file | annotate | diff | comparison | revisions
pidgin/gtkconv.c file | annotate | diff | comparison | revisions
pidgin/gtksmiley-theme.c file | annotate | diff | comparison | revisions
--- a/libpurple/Makefile.am	Tue Apr 01 02:11:17 2014 +0200
+++ b/libpurple/Makefile.am	Tue Apr 01 03:46:16 2014 +0200
@@ -102,6 +102,7 @@
 	server.c \
 	signals.c \
 	smiley-list.c \
+	smiley-parser.c \
 	smiley-theme.c \
 	smiley.c \
 	dnsquery.c \
@@ -179,6 +180,7 @@
 	server.h \
 	signals.h \
 	smiley-list.h \
+	smiley-parser.h \
 	smiley-theme.h \
 	smiley.h \
 	dnsquery.h \
--- a/libpurple/smiley-list.c	Tue Apr 01 02:11:17 2014 +0200
+++ b/libpurple/smiley-list.c	Tue Apr 01 03:46:16 2014 +0200
@@ -41,9 +41,6 @@
 	PROP_LAST
 };
 
-static GObjectClass *parent_class;
-static GParamSpec *properties[PROP_LAST];
-
 static void
 _list_append2(GList **head_p, GList **tail_p, gpointer data)
 {
@@ -84,6 +81,12 @@
  * API implementation
  ******************************************************************************/
 
+PurpleSmileyList *
+purple_smiley_list_new(void)
+{
+	return g_object_new(PURPLE_TYPE_SMILEY_LIST, NULL);
+}
+
 gboolean
 purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley)
 {
@@ -138,6 +141,16 @@
 	g_object_unref(smiley);
 }
 
+PurpleTrie *
+purple_smiley_list_get_trie(PurpleSmileyList *list)
+{
+	PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(list);
+
+	g_return_val_if_fail(priv != NULL, NULL);
+
+	return priv->trie;
+}
+
 
 /*******************************************************************************
  * Object stuff
@@ -211,15 +224,11 @@
 {
 	GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
 
-	parent_class = g_type_class_peek_parent(klass);
-
 	g_type_class_add_private(klass, sizeof(PurpleSmileyListPrivate));
 
 	gobj_class->get_property = purple_smiley_list_get_property;
 	gobj_class->set_property = purple_smiley_list_set_property;
 	gobj_class->finalize = purple_smiley_list_finalize;
-
-	g_object_class_install_properties(gobj_class, PROP_LAST, properties);
 }
 
 GType
--- a/libpurple/smiley-list.h	Tue Apr 01 02:11:17 2014 +0200
+++ b/libpurple/smiley-list.h	Tue Apr 01 03:46:16 2014 +0200
@@ -25,6 +25,7 @@
 #include <glib-object.h>
 
 #include "smiley.h"
+#include "trie.h"
 
 typedef struct _PurpleSmileyList PurpleSmileyList;
 typedef struct _PurpleSmileyListClass PurpleSmileyListClass;
@@ -68,12 +69,18 @@
 GType
 purple_smiley_list_get_type(void);
 
+PurpleSmileyList *
+purple_smiley_list_new(void);
+
 gboolean
 purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley);
 
 void
 purple_smiley_list_remove(PurpleSmileyList *list, PurpleSmiley *smiley);
 
+PurpleTrie *
+purple_smiley_list_get_trie(PurpleSmileyList *list);
+
 G_END_DECLS
 
 #endif /* _PURPLE_SMILEY_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/smiley-parser.c	Tue Apr 01 03:46:16 2014 +0200
@@ -0,0 +1,67 @@
+/* purple
+ *
+ * Purple 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "smiley-parser.h"
+
+#include "smiley-theme.h"
+
+static gboolean purple_smiley_parse_cb(GString *out, const gchar *word,
+	gpointer _smiley, gpointer _unused)
+{
+	PurpleSmiley *smiley = _smiley;
+
+	g_string_append_printf(out, "<img alt=\"%s\" src=\"%s\" />",
+		word, purple_smiley_get_path(smiley));
+
+	return TRUE;
+}
+
+gchar *
+purple_smiley_parse(const gchar *message, gpointer ui_data)
+{
+	PurpleSmileyTheme *theme;
+	PurpleSmileyList *theme_smileys;
+	PurpleTrie *theme_trie;
+
+	if (message == NULL || message[0] == '\0') {
+		purple_debug_info("tomo", "no msg");
+		return g_strdup(message);
+	}
+
+	theme = purple_smiley_theme_get_current();
+	if (theme == NULL) {
+		purple_debug_info("tomo", "no theme");
+		return g_strdup(message);
+	}
+
+	theme_smileys = purple_smiley_theme_get_smileys(theme, ui_data);
+	if (theme_smileys == NULL) {
+		purple_debug_info("tomo", "no smileys");
+		return g_strdup(message);
+	}
+
+	theme_trie = purple_smiley_list_get_trie(theme_smileys);
+	g_return_val_if_fail(theme_trie != NULL, g_strdup(message));
+
+	/* TODO: don't replace text within tags, ie. <span style=":)"> */
+	return purple_trie_replace(theme_trie, message,
+		purple_smiley_parse_cb, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/smiley-parser.h	Tue Apr 01 03:46:16 2014 +0200
@@ -0,0 +1,30 @@
+/* purple
+ *
+ * Purple 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#ifndef _PURPLE_SMILEY_PARSER_H_
+#define _PURPLE_SMILEY_PARSER_H_
+
+#include "purple.h"
+
+gchar *
+purple_smiley_parse(const gchar *message, gpointer ui_data);
+
+#endif /* _PURPLE_SMILEY_PARSER_H_ */
--- a/libpurple/smiley-theme.c	Tue Apr 01 02:11:17 2014 +0200
+++ b/libpurple/smiley-theme.c	Tue Apr 01 03:46:16 2014 +0200
@@ -43,6 +43,8 @@
 void
 purple_smiley_theme_set_current(PurpleSmileyTheme *theme)
 {
+	PurpleSmileyThemeClass *klass;
+
 	g_return_if_fail(theme == NULL || PURPLE_IS_SMILEY_THEME(theme));
 
 	if (theme)
@@ -50,6 +52,13 @@
 	if (current)
 		g_object_unref(current);
 	current = theme;
+
+	if (!theme)
+		return;
+	klass = PURPLE_SMILEY_THEME_GET_CLASS(theme);
+	g_return_if_fail(klass != NULL);
+	if (klass->activate)
+		klass->activate(theme);
 }
 
 PurpleSmileyTheme *
--- a/libpurple/smiley-theme.h	Tue Apr 01 02:11:17 2014 +0200
+++ b/libpurple/smiley-theme.h	Tue Apr 01 03:46:16 2014 +0200
@@ -55,6 +55,7 @@
 
 	PurpleSmileyList * (*get_smileys)(PurpleSmileyTheme *theme,
 		gpointer ui_data);
+	void (*activate)(PurpleSmileyTheme *theme);
 
 	void (*purple_reserved1)(void);
 	void (*purple_reserved2)(void);
--- a/libpurple/smiley.c	Tue Apr 01 02:11:17 2014 +0200
+++ b/libpurple/smiley.c	Tue Apr 01 03:46:16 2014 +0200
@@ -138,6 +138,12 @@
 		case PROP_SHORTCUT:
 			g_value_set_string(value, priv->shortcut);
 			break;
+		case PROP_IS_READY:
+			g_value_set_boolean(value, priv->is_ready);
+			break;
+		case PROP_PATH:
+			g_value_set_string(value, priv->path);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
 			break;
@@ -156,6 +162,13 @@
 			g_free(priv->shortcut);
 			priv->shortcut = g_strdup(g_value_get_string(value));
 			break;
+		case PROP_IS_READY:
+			priv->is_ready = g_value_get_boolean(value);
+			break;
+		case PROP_PATH:
+			g_free(priv->path);
+			priv->path = g_strdup(g_value_get_string(value));
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
 			break;
--- a/pidgin/gtkconv.c	Tue Apr 01 02:11:17 2014 +0200
+++ b/pidgin/gtkconv.c	Tue Apr 01 03:46:16 2014 +0200
@@ -41,6 +41,7 @@
 #include "notify.h"
 #include "prpl.h"
 #include "request.h"
+#include "smiley-parser.h"
 #include "theme-loader.h"
 #include "theme-manager.h"
 #include "util.h"
@@ -6710,7 +6711,8 @@
 	gtkconv->last_flags = flags;
 	gtkconv->last_conversed = conv;
 
-	smileyed = pidgin_smiley_parse_markup(displaying, purple_account_get_protocol_id(account));
+	smileyed = purple_smiley_parse(displaying,
+		(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);
--- a/pidgin/gtksmiley-theme.c	Tue Apr 01 02:11:17 2014 +0200
+++ b/pidgin/gtksmiley-theme.c	Tue Apr 01 03:46:16 2014 +0200
@@ -47,6 +47,8 @@
 	gchar *author;
 
 	GdkPixbuf *icon_pixbuf;
+
+	GHashTable *smiley_lists_map;
 } PidginSmileyThemePrivate;
 
 static GObjectClass *parent_class;
@@ -111,18 +113,21 @@
 }
 
 static PidginSmileyThemeIndex *
-pidgin_smiley_theme_index_parse(const gchar *index_path, gboolean load_contents)
+pidgin_smiley_theme_index_parse(const gchar *theme_path, gboolean load_contents)
 {
 	PidginSmileyThemeIndex *index;
 	PidginSmileyThemeIndexProtocol *proto = NULL;
+	gchar *index_path;
 	FILE *file;
 	int line_no = 0;
 	gboolean inv_frm = FALSE;
 
+	index_path = g_build_filename(theme_path, "theme", NULL);
 	file = g_fopen(index_path, "r");
 	if (!file) {
 		purple_debug_error("gtksmiley-theme",
 			"Failed to open index file %s", index_path);
+		g_free(index_path);
 		return NULL;
 	}
 
@@ -253,6 +258,7 @@
 		index = NULL;
 	}
 
+	g_free(index_path);
 	return index;
 }
 
@@ -267,7 +273,6 @@
 	PidginSmileyThemePrivate *priv;
 	PidginSmileyThemeIndex *index;
 	GList *it;
-	gchar *index_path;
 
 	/* it's not super-efficient, but we don't expect huge amount of
 	 * installed themes */
@@ -280,16 +285,12 @@
 			return;
 	}
 
-	index_path = g_build_filename(theme_path, "theme", NULL);
-
 	theme = g_object_new(PIDGIN_TYPE_SMILEY_THEME, NULL);
 	priv = PIDGIN_SMILEY_THEME_GET_PRIVATE(theme);
 
 	priv->path = g_strdup(theme_path);
 
-	index = pidgin_smiley_theme_index_parse(index_path, FALSE);
-
-	g_free(index_path);
+	index = pidgin_smiley_theme_index_parse(theme_path, FALSE);
 
 	if (!index->name || index->name[0] == '\0') {
 		purple_debug_warning("gtksmiley-theme",
@@ -425,16 +426,85 @@
 	return priv->author;
 }
 
+static void
+pidgin_smiley_theme_activate_impl(PurpleSmileyTheme *theme)
+{
+	PidginSmileyThemePrivate *priv = PIDGIN_SMILEY_THEME_GET_PRIVATE(theme);
+	PidginSmileyThemeIndex *index;
+	GHashTable *smap;
+	GList *it, *it2, *it3;
+
+	g_return_if_fail(priv != NULL);
+
+	if (priv->smiley_lists_map)
+		return;
+
+	priv->smiley_lists_map = smap = g_hash_table_new_full(
+		g_str_hash, g_str_equal, g_free, g_object_unref);
+
+	index = pidgin_smiley_theme_index_parse(priv->path, TRUE);
+
+	for (it = index->protocols; it; it = g_list_next(it)) {
+		PidginSmileyThemeIndexProtocol *proto_idx = it->data;
+		PurpleSmileyList *proto_smileys;
+
+		proto_smileys = g_hash_table_lookup(smap, proto_idx->name);
+		if (!proto_smileys) {
+			proto_smileys = purple_smiley_list_new();
+			g_hash_table_insert(smap,
+				g_strdup(proto_idx->name), proto_smileys);
+		}
+
+		for (it2 = proto_idx->smileys; it2; it2 = g_list_next(it2)) {
+			PidginSmileyThemeIndexSmiley *smiley_idx = it2->data;
+			gchar *smiley_path;
+
+			smiley_path = g_build_filename(
+				priv->path, smiley_idx->file, NULL);
+			if (!g_file_test(smiley_path, G_FILE_TEST_EXISTS)) {
+				purple_debug_warning("gtksmiley-theme",
+					"Smiley %s is missing", smiley_path);
+				continue;
+			}
+
+			for (it3 = smiley_idx->shortcuts; it3;
+				it3 = g_list_next(it3))
+			{
+				PurpleSmiley *smiley;
+				gchar *shortcut = it3->data;
+
+				smiley = purple_smiley_new(
+					shortcut, smiley_path);
+				purple_smiley_list_add(proto_smileys, smiley);
+				g_object_unref(smiley);
+			}
+		}
+	}
+
+	pidgin_smiley_theme_index_free(index);
+}
+
 static PurpleSmileyList *
 pidgin_smiley_theme_get_smileys_impl(PurpleSmileyTheme *theme, gpointer ui_data)
 {
-	return NULL;
+	PidginSmileyThemePrivate *priv = PIDGIN_SMILEY_THEME_GET_PRIVATE(theme);
+	PurpleSmileyList *smileys;
+
+	pidgin_smiley_theme_activate_impl(theme);
+
+	smileys = g_hash_table_lookup(priv->smiley_lists_map, ui_data);
+	if (smileys != NULL)
+		return smileys;
+
+	return g_hash_table_lookup(priv->smiley_lists_map, "default");
 }
 
 void
 pidgin_smiley_theme_init(void)
 {
+	GList *it;
 	const gchar *user_smileys_dir;
+	const gchar *theme_name;
 
 	probe_dirs = g_new0(gchar*, 3);
 	probe_dirs[0] = g_build_filename(
@@ -445,7 +515,18 @@
 	if (!g_file_test(user_smileys_dir, G_FILE_TEST_IS_DIR))
 		g_mkdir(user_smileys_dir, S_IRUSR | S_IWUSR | S_IXUSR);
 
-	/* TODO: load configured theme */
+	/* setting theme by name (copy-paste from gtkprefs) */
+	pidgin_smiley_theme_probe();
+	theme_name = purple_prefs_get_string(
+		PIDGIN_PREFS_ROOT "/smileys/theme");
+	for (it = smiley_themes; it; it = g_list_next(it)) {
+		PidginSmileyTheme *theme = it->data;
+
+		if (g_strcmp0(pidgin_smiley_theme_get_name(theme), theme_name))
+			continue;
+
+		purple_smiley_theme_set_current(PURPLE_SMILEY_THEME(theme));
+	}
 }
 
 void
@@ -478,6 +559,8 @@
 	g_free(priv->author);
 	if (priv->icon_pixbuf)
 		g_object_unref(priv->icon_pixbuf);
+	if (priv->smiley_lists_map)
+		g_hash_table_destroy(priv->smiley_lists_map);
 
 	G_OBJECT_CLASS(parent_class)->finalize(obj);
 }
@@ -495,6 +578,7 @@
 	gobj_class->finalize = pidgin_smiley_theme_finalize;
 
 	pst_class->get_smileys = pidgin_smiley_theme_get_smileys_impl;
+	pst_class->activate = pidgin_smiley_theme_activate_impl;
 }
 
 GType

mercurial