summaryrefslogtreecommitdiff
path: root/libpurple/smiley.c
diff options
context:
space:
mode:
authorTomasz Wasilczyk <twasilczyk@pidgin.im>2014-03-29 16:14:34 +0100
committerTomasz Wasilczyk <twasilczyk@pidgin.im>2014-03-29 16:14:34 +0100
commitf4826925ee4008825b5143d85e6825c627760126 (patch)
tree9333ade0bd5995d38199d91b31c268d1e68aabed /libpurple/smiley.c
parentb20d4dac3a710cf2daa767a70f36027fbf6bc1d7 (diff)
downloadpidgin-f4826925ee4008825b5143d85e6825c627760126.tar.gz
Initial generic PurpleSmiley implementation
Diffstat (limited to 'libpurple/smiley.c')
-rw-r--r--libpurple/smiley.c880
1 files changed, 78 insertions, 802 deletions
diff --git a/libpurple/smiley.c b/libpurple/smiley.c
index fc397c010a..617468e461 100644
--- a/libpurple/smiley.c
+++ b/libpurple/smiley.c
@@ -31,363 +31,137 @@
#define PURPLE_SMILEY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SMILEY, PurpleSmileyPrivate))
-/**************************************************************************/
-/* Structs */
-/**************************************************************************/
-
typedef struct {
- PurpleStoredImage *img; /* The id of the stored image with the
- the smiley data. */
- char *shortcut; /* Shortcut associated with the custom
- smiley. This field will work as a
- unique key by this API. */
- char *checksum; /* The smiley checksum. */
+ gchar *shortcut;
+ gchar *path;
+ gboolean is_ready;
} PurpleSmileyPrivate;
-static GHashTable *smiley_shortcut_index = NULL; /* shortcut (char *) => smiley (PurpleSmiley*) */
-static GHashTable *smiley_checksum_index = NULL; /* checksum (char *) => smiley (PurpleSmiley*) */
-
-static guint save_timer = 0;
-static gboolean smileys_loaded = FALSE;
-static char *smileys_dir = NULL;
-
-#define SMILEYS_DEFAULT_FOLDER "custom_smiley"
-#define SMILEYS_LOG_ID "smileys"
-
-#define XML_FILE_NAME "smileys.xml"
-
-#define XML_ROOT_TAG "smileys"
-#define XML_PROFILE_TAG "profile"
-#define XML_PROFILE_NAME_ATTRIB_TAG "name"
-#define XML_ACCOUNT_TAG "account"
-#define XML_ACCOUNT_USERID_ATTRIB_TAG "userid"
-#define XML_SMILEY_SET_TAG "smiley_set"
-#define XML_SMILEY_TAG "smiley"
-#define XML_SHORTCUT_ATTRIB_TAG "shortcut"
-#define XML_CHECKSUM_ATRIB_TAG "checksum"
-#define XML_FILENAME_ATRIB_TAG "filename"
-
-
-/******************************************************************************
- * XML descriptor file layout *
- ******************************************************************************
- *
- * Although we are creating the profile XML structure here, now we
- * won't handle it.
- * So, we just add one profile named "default" that has no associated
- * account elements, and have only the smiley_set that will contain
- * all existent custom smiley.
- *
- * It's our "Highlander Profile" :-)
- *
- ******************************************************************************
- *
- * <smileys>
- * <profile name="john.doe">
- * <account userid="john.doe@jabber.org">
- * <account userid="john.doe@gmail.com">
- * <smiley_set>
- * <smiley shortcut="aaa" checksum="xxxxxxxx" filename="file_name1.gif"/>
- * <smiley shortcut="bbb" checksum="yyyyyyy" filename="file_name2.gif"/>
- * </smiley_set>
- * </profile>
- * </smiley>
- *
- *****************************************************************************/
-
-
-/*********************************************************************
- * Forward declarations *
- *********************************************************************/
-
-static gboolean read_smiley_file(const char *path, guchar **data, size_t *len);
-
-static char *get_file_full_path(const char *filename);
-
-static PurpleSmiley *purple_smiley_create(const char *shortcut);
-
-static void purple_smiley_load_file(const char *shortcut, const char *checksum,
- const char *filename);
-
-static void
-purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data,
- size_t smiley_data_len);
-
-static void
-purple_smiley_data_store(PurpleStoredImage *stored_img);
-
-static void
-purple_smiley_data_unstore(const char *filename);
-
-/*********************************************************************
- * Writing to disk *
- *********************************************************************/
-
-static PurpleXmlNode *
-smiley_to_xmlnode(PurpleSmiley *smiley)
+enum
{
- PurpleSmileyPrivate *priv = NULL;
- PurpleXmlNode *smiley_node = NULL;
-
- smiley_node = purple_xmlnode_new(XML_SMILEY_TAG);
+ PROP_0,
+ PROP_SHORTCUT,
+ PROP_IS_READY,
+ PROP_PATH,
+ PROP_LAST
+};
- if (!smiley_node)
- return NULL;
+enum
+{
+ SIG_READY,
+ SIG_LAST
+};
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
+static guint signals[SIG_LAST];
+static GObjectClass *parent_class;
+static GParamSpec *properties[PROP_LAST];
- purple_xmlnode_set_attrib(smiley_node, XML_SHORTCUT_ATTRIB_TAG,
- priv->shortcut);
+/*******************************************************************************
+ * API implementation
+ ******************************************************************************/
- purple_xmlnode_set_attrib(smiley_node, XML_CHECKSUM_ATRIB_TAG,
- priv->checksum);
+void
+purple_smiley_set_shortcut(PurpleSmiley *smiley, const gchar *shortcut)
+{
+ PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- purple_xmlnode_set_attrib(smiley_node, XML_FILENAME_ATRIB_TAG,
- purple_imgstore_get_filename(priv->img));
+ g_return_if_fail(priv != NULL);
- return smiley_node;
+ g_free(priv->shortcut);
+ priv->shortcut = g_strdup(shortcut);
+ g_object_notify_by_pspec(G_OBJECT(smiley), properties[PROP_SHORTCUT]);
}
-static void
-add_smiley_to_main_node(gpointer key, gpointer value, gpointer user_data)
+const gchar *
+purple_smiley_get_shortcut(const PurpleSmiley *smiley)
{
- PurpleXmlNode *child_node;
-
- child_node = smiley_to_xmlnode(value);
- purple_xmlnode_insert_child((PurpleXmlNode*)user_data, child_node);
-}
+ PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-static PurpleXmlNode *
-smileys_to_xmlnode(void)
-{
- PurpleXmlNode *root_node, *profile_node, *smileyset_node;
-
- root_node = purple_xmlnode_new(XML_ROOT_TAG);
- purple_xmlnode_set_attrib(root_node, "version", "1.0");
-
- /* See the top comments above to understand why initial tag elements
- * are not being considered by now. */
- profile_node = purple_xmlnode_new(XML_PROFILE_TAG);
- if (profile_node) {
- purple_xmlnode_set_attrib(profile_node, XML_PROFILE_NAME_ATTRIB_TAG, "Default");
- purple_xmlnode_insert_child(root_node, profile_node);
-
- smileyset_node = purple_xmlnode_new(XML_SMILEY_SET_TAG);
- if (smileyset_node) {
- purple_xmlnode_insert_child(profile_node, smileyset_node);
- g_hash_table_foreach(smiley_shortcut_index, add_smiley_to_main_node, smileyset_node);
- }
- }
+ g_return_val_if_fail(priv != NULL, NULL);
- return root_node;
+ return priv->shortcut;
}
-static void
-sync_smileys(void)
+gboolean
+purple_smiley_is_ready(const PurpleSmiley *smiley)
{
- PurpleXmlNode *root_node;
- char *data;
-
- if (!smileys_loaded) {
- purple_debug_error(SMILEYS_LOG_ID, "Attempted to save smileys before it "
- "was read!\n");
- return;
- }
+ PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- root_node = smileys_to_xmlnode();
- data = purple_xmlnode_to_formatted_str(root_node, NULL);
- purple_util_write_data_to_file(XML_FILE_NAME, data, -1);
+ g_return_val_if_fail(priv != NULL, FALSE);
- g_free(data);
- purple_xmlnode_free(root_node);
+ return priv->is_ready;
}
-static gboolean
-save_smileys_cb(gpointer data)
+const gchar *
+purple_smiley_get_path(PurpleSmiley *smiley)
{
- sync_smileys();
- save_timer = 0;
- return FALSE;
-}
+ PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-static void
-purple_smileys_save(void)
-{
- if (save_timer == 0)
- save_timer = purple_timeout_add_seconds(5, save_smileys_cb, NULL);
+ g_return_val_if_fail(priv != NULL, FALSE);
+
+ return priv->path;
}
-/*********************************************************************
- * Reading from disk *
- *********************************************************************/
+/*******************************************************************************
+ * Object stuff
+ ******************************************************************************/
static void
-parse_smiley(PurpleXmlNode *smiley_node)
+purple_smiley_init(GTypeInstance *instance, gpointer klass)
{
- const char *shortcut = NULL;
- const char *checksum = NULL;
- const char *filename = NULL;
-
- shortcut = purple_xmlnode_get_attrib(smiley_node, XML_SHORTCUT_ATTRIB_TAG);
- checksum = purple_xmlnode_get_attrib(smiley_node, XML_CHECKSUM_ATRIB_TAG);
- filename = purple_xmlnode_get_attrib(smiley_node, XML_FILENAME_ATRIB_TAG);
-
- if ((shortcut == NULL) || (checksum == NULL) || (filename == NULL))
- return;
-
- purple_smiley_load_file(shortcut, checksum, filename);
+ PurpleSmiley *smiley = PURPLE_SMILEY(instance);
+ PURPLE_DBUS_REGISTER_POINTER(smiley, PurpleSmiley);
}
static void
-purple_smileys_load(void)
-{
- PurpleXmlNode *root_node, *profile_node;
- PurpleXmlNode *smileyset_node = NULL;
- PurpleXmlNode *smiley_node;
-
- smileys_loaded = TRUE;
-
- root_node = purple_util_read_xml_from_file(XML_FILE_NAME,
- _(SMILEYS_LOG_ID));
-
- if (root_node == NULL)
- return;
-
- /* See the top comments above to understand why initial tag elements
- * are not being considered by now. */
- profile_node = purple_xmlnode_get_child(root_node, XML_PROFILE_TAG);
- if (profile_node)
- smileyset_node = purple_xmlnode_get_child(profile_node, XML_SMILEY_SET_TAG);
-
- if (smileyset_node) {
- smiley_node = purple_xmlnode_get_child(smileyset_node, XML_SMILEY_TAG);
- for (; smiley_node != NULL;
- smiley_node = purple_xmlnode_get_next_twin(smiley_node)) {
- parse_smiley(smiley_node);
- }
- }
-
- purple_xmlnode_free(root_node);
-}
-
-/*********************************************************************
- * GObject Stuff *
- *********************************************************************/
-enum
-{
- PROP_0,
- PROP_SHORTCUT,
- PROP_IMGSTORE,
- PROP_LAST
-};
-
-enum
+purple_smiley_finalize(GObject *obj)
{
- SIG_DESTROY,
- SIG_LAST
-};
+ PurpleSmiley *smiley = PURPLE_SMILEY(obj);
+ PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-static guint signals[SIG_LAST];
-static GObjectClass *parent_class;
-static GParamSpec *properties[PROP_LAST];
+ g_free(priv->shortcut);
+ g_free(priv->path);
-static void
-purple_smiley_init(GTypeInstance *instance, gpointer klass)
-{
- PurpleSmiley *smiley = PURPLE_SMILEY(instance);
- PURPLE_DBUS_REGISTER_POINTER(smiley, PurpleSmiley);
+ PURPLE_DBUS_UNREGISTER_POINTER(smiley);
}
static void
-purple_smiley_get_property(GObject *object, guint param_id, GValue *value,
- GParamSpec *spec)
+purple_smiley_get_property(GObject *object, guint par_id, GValue *value,
+ GParamSpec *pspec)
{
PurpleSmiley *smiley = PURPLE_SMILEY(object);
PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- switch (param_id) {
+ switch (par_id) {
case PROP_SHORTCUT:
g_value_set_string(value, priv->shortcut);
break;
- case PROP_IMGSTORE:
- g_value_set_pointer(value, priv->img);
- break;
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
break;
}
}
static void
-purple_smiley_set_property(GObject *object, guint param_id, const GValue *value,
- GParamSpec *spec)
+purple_smiley_set_property(GObject *object, guint par_id, const GValue *value,
+ GParamSpec *pspec)
{
PurpleSmiley *smiley = PURPLE_SMILEY(object);
PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- switch (param_id) {
+ switch (par_id) {
case PROP_SHORTCUT:
- {
- const char *shortcut = g_value_get_string(value);
- purple_smiley_set_shortcut(smiley, shortcut);
- }
- break;
- case PROP_IMGSTORE:
- {
- PurpleStoredImage *img = g_value_get_pointer(value);
-
- purple_imgstore_unref(priv->img);
- g_free(priv->checksum);
-
- priv->img = img;
- if (img) {
- priv->checksum = g_compute_checksum_for_data(
- G_CHECKSUM_SHA1,
- purple_imgstore_get_data(img),
- purple_imgstore_get_size(img));
- purple_smiley_data_store(img);
- } else {
- priv->checksum = NULL;
- }
- }
+ g_free(priv->shortcut);
+ priv->shortcut = g_strdup(g_value_get_string(value));
break;
default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
break;
}
}
static void
-purple_smiley_finalize(GObject *obj)
-{
- PurpleSmiley *smiley = PURPLE_SMILEY(obj);
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- if (g_hash_table_lookup(smiley_shortcut_index, priv->shortcut)) {
- g_hash_table_remove(smiley_shortcut_index, priv->shortcut);
- g_hash_table_remove(smiley_checksum_index, priv->checksum);
- }
-
- g_free(priv->shortcut);
- g_free(priv->checksum);
- if (priv->img)
- purple_smiley_data_unstore(purple_imgstore_get_filename(priv->img));
- purple_imgstore_unref(priv->img);
-
- PURPLE_DBUS_UNREGISTER_POINTER(smiley);
-
- purple_smileys_save();
-}
-
-static void
-purple_smiley_dispose(GObject *gobj)
-{
- g_signal_emit(gobj, signals[SIG_DESTROY], 0);
- parent_class->dispose(gobj);
-}
-
-static void
purple_smiley_class_init(PurpleSmileyClass *klass)
{
GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
@@ -399,27 +173,16 @@ purple_smiley_class_init(PurpleSmileyClass *klass)
gobj_class->get_property = purple_smiley_get_property;
gobj_class->set_property = purple_smiley_set_property;
gobj_class->finalize = purple_smiley_finalize;
- gobj_class->dispose = purple_smiley_dispose;
- /* Shortcut */
properties[PROP_SHORTCUT] = g_param_spec_string("shortcut", "Shortcut",
- "The text-shortcut for the smiley",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /* Stored Image */
- properties[PROP_IMGSTORE] = g_param_spec_pointer("image", "Stored Image",
- "Stored Image. (that'll have to do for now)",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ "The text-shortcut for the smiley", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(gobj_class, PROP_LAST, properties);
- signals[SIG_DESTROY] = g_signal_new("destroy",
- G_OBJECT_CLASS_TYPE(klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ signals[SIG_READY] = g_signal_new("ready", G_OBJECT_CLASS_TYPE(klass),
+ 0, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
GType
@@ -427,504 +190,17 @@ purple_smiley_get_type(void)
{
static GType type = 0;
- if(type == 0) {
+ if (G_UNLIKELY(type == 0)) {
static const GTypeInfo info = {
- sizeof(PurpleSmileyClass),
- NULL,
- NULL,
- (GClassInitFunc)purple_smiley_class_init,
- NULL,
- NULL,
- sizeof(PurpleSmiley),
- 0,
- purple_smiley_init,
- NULL,
+ .class_size = sizeof(PurpleSmileyClass),
+ .class_init = (GClassInitFunc)purple_smiley_class_init,
+ .instance_size = sizeof(PurpleSmiley),
+ .instance_init = purple_smiley_init,
};
type = g_type_register_static(G_TYPE_OBJECT,
- "PurpleSmiley",
- &info, 0);
+ "PurpleSmiley", &info, G_TYPE_FLAG_ABSTRACT);
}
return type;
}
-
-/*********************************************************************
- * Other Stuff *
- *********************************************************************/
-
-static char *get_file_full_path(const char *filename)
-{
- char *path;
-
- path = g_build_filename(purple_smileys_get_storing_dir(), filename, NULL);
-
- if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
- g_free(path);
- return NULL;
- }
-
- return path;
-}
-
-static void
-purple_smiley_load_file(const char *shortcut, const char *checksum, const char *filename)
-{
- PurpleSmiley *smiley = NULL;
- PurpleSmileyPrivate *priv = NULL;
- guchar *smiley_data;
- size_t smiley_data_len;
- char *fullpath = NULL;
-
- g_return_if_fail(shortcut != NULL);
- g_return_if_fail(checksum != NULL);
- g_return_if_fail(filename != NULL);
-
- fullpath = get_file_full_path(filename);
- if (!fullpath) {
- purple_debug_error(SMILEYS_LOG_ID, "Path for filename %s doesn't exist\n", filename);
- return;
- }
-
- smiley = purple_smiley_create(shortcut);
- if (!smiley) {
- g_free(fullpath);
- return;
- }
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- priv->checksum = g_strdup(checksum);
-
- if (read_smiley_file(fullpath, &smiley_data, &smiley_data_len))
- purple_smiley_set_data_impl(smiley, smiley_data,
- smiley_data_len);
- else
- purple_smiley_delete(smiley);
-
- g_free(fullpath);
-
-}
-
-static void
-purple_smiley_data_store(PurpleStoredImage *stored_img)
-{
- const char *dirname;
- char *path;
- FILE *file = NULL;
-
- g_return_if_fail(stored_img != NULL);
-
- if (!smileys_loaded)
- return;
-
- dirname = purple_smileys_get_storing_dir();
- path = g_build_filename(dirname, purple_imgstore_get_filename(stored_img), NULL);
-
- if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
- purple_debug_info(SMILEYS_LOG_ID, "Creating smileys directory.\n");
-
- if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
- purple_debug_error(SMILEYS_LOG_ID,
- "Unable to create directory %s: %s\n",
- dirname, g_strerror(errno));
- }
- }
-
- if ((file = g_fopen(path, "wb")) != NULL) {
- if (!fwrite(purple_imgstore_get_data(stored_img),
- purple_imgstore_get_size(stored_img), 1, file)) {
- purple_debug_error(SMILEYS_LOG_ID, "Error writing %s: %s\n",
- path, g_strerror(errno));
- } else {
- purple_debug_info(SMILEYS_LOG_ID, "Wrote cache file: %s\n", path);
- }
-
- fclose(file);
- } else {
- purple_debug_error(SMILEYS_LOG_ID, "Unable to create file %s: %s\n",
- path, g_strerror(errno));
- g_free(path);
-
- return;
- }
-
- g_free(path);
-}
-
-static void
-purple_smiley_data_unstore(const char *filename)
-{
- const char *dirname;
- char *path;
-
- g_return_if_fail(filename != NULL);
-
- dirname = purple_smileys_get_storing_dir();
- path = g_build_filename(dirname, filename, NULL);
-
- if (g_file_test(path, G_FILE_TEST_EXISTS)) {
- if (g_unlink(path))
- purple_debug_error(SMILEYS_LOG_ID, "Failed to delete %s: %s\n",
- path, g_strerror(errno));
- else
- purple_debug_info(SMILEYS_LOG_ID, "Deleted cache file: %s\n", path);
- }
-
- g_free(path);
-}
-
-static gboolean
-read_smiley_file(const char *path, guchar **data, size_t *len)
-{
- GError *err = NULL;
-
- if (!g_file_get_contents(path, (gchar **)data, len, &err)) {
- purple_debug_error(SMILEYS_LOG_ID, "Error reading %s: %s\n",
- path, err->message);
- g_error_free(err);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static PurpleStoredImage *
-purple_smiley_data_new(guchar *smiley_data, size_t smiley_data_len)
-{
- char *filename;
- PurpleStoredImage *stored_img;
-
- g_return_val_if_fail(smiley_data != NULL, NULL);
- g_return_val_if_fail(smiley_data_len > 0, NULL);
-
- filename = purple_util_get_image_filename(smiley_data, smiley_data_len);
-
- if (filename == NULL) {
- g_free(smiley_data);
- return NULL;
- }
-
- stored_img = purple_imgstore_new(smiley_data, smiley_data_len, filename);
-
- g_free(filename);
-
- return stored_img;
-}
-
-static void
-purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data,
- size_t smiley_data_len)
-{
- PurpleSmileyPrivate *priv = NULL;
- PurpleStoredImage *old_img, *new_img;
- const char *old_filename = NULL;
- const char *new_filename = NULL;
-
- g_return_if_fail(smiley != NULL);
- g_return_if_fail(smiley_data != NULL);
- g_return_if_fail(smiley_data_len > 0);
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- old_img = priv->img;
-
- new_img = purple_smiley_data_new(smiley_data, smiley_data_len);
-
- g_object_set(G_OBJECT(smiley), "image", new_img, NULL);
-
- /* If the old and new image files have different names we need
- * to unstore old image file. */
- if (!old_img)
- return;
-
- old_filename = purple_imgstore_get_filename(old_img);
- new_filename = purple_imgstore_get_filename(priv->img);
-
- if (g_ascii_strcasecmp(old_filename, new_filename))
- purple_smiley_data_unstore(old_filename);
- purple_imgstore_unref(old_img);
-}
-
-
-/*****************************************************************************
- * Public API functions *
- *****************************************************************************/
-
-static PurpleSmiley *
-purple_smiley_create(const char *shortcut)
-{
- PurpleSmiley *smiley;
-
- smiley = PURPLE_SMILEY(g_object_new(PURPLE_TYPE_SMILEY, "shortcut", shortcut, NULL));
-
- return smiley;
-}
-
-PurpleSmiley *
-purple_smiley_new(PurpleStoredImage *img, const char *shortcut)
-{
- PurpleSmiley *smiley = NULL;
-
- g_return_val_if_fail(shortcut != NULL, NULL);
- g_return_val_if_fail(img != NULL, NULL);
-
- smiley = purple_smileys_find_by_shortcut(shortcut);
- if (smiley)
- return smiley;
-
- smiley = purple_smiley_create(shortcut);
- if (!smiley)
- return NULL;
-
- g_object_set(G_OBJECT(smiley), "image", img, NULL);
-
- return smiley;
-}
-
-static PurpleSmiley *
-purple_smiley_new_from_stream(const char *shortcut, guchar *smiley_data,
- size_t smiley_data_len)
-{
- PurpleSmiley *smiley = NULL;
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_val_if_fail(shortcut != NULL, NULL);
- g_return_val_if_fail(smiley_data != NULL, NULL);
- g_return_val_if_fail(smiley_data_len > 0, NULL);
-
- smiley = purple_smileys_find_by_shortcut(shortcut);
- if (smiley)
- return smiley;
-
- /* purple_smiley_create() sets shortcut */
- smiley = purple_smiley_create(shortcut);
- if (!smiley)
- return NULL;
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len);
- purple_smiley_data_store(priv->img);
-
- return smiley;
-}
-
-PurpleSmiley *
-purple_smiley_new_from_file(const char *shortcut, const char *filepath)
-{
- PurpleSmiley *smiley = NULL;
- guchar *smiley_data;
- size_t smiley_data_len;
-
- g_return_val_if_fail(shortcut != NULL, NULL);
- g_return_val_if_fail(filepath != NULL, NULL);
-
- if (read_smiley_file(filepath, &smiley_data, &smiley_data_len)) {
- smiley = purple_smiley_new_from_stream(shortcut, smiley_data,
- smiley_data_len);
- }
-
- return smiley;
-}
-
-void
-purple_smiley_delete(PurpleSmiley *smiley)
-{
- g_return_if_fail(smiley != NULL);
-
- g_object_unref(smiley);
-}
-
-gboolean
-purple_smiley_set_shortcut(PurpleSmiley *smiley, const char *shortcut)
-{
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_val_if_fail(smiley != NULL, FALSE);
- g_return_val_if_fail(shortcut != NULL, FALSE);
-
- /* Check out whether the new shortcut is already being used. */
- if (g_hash_table_lookup(smiley_shortcut_index, shortcut))
- return FALSE;
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- /* Remove the old shortcut. */
- if (priv->shortcut)
- g_hash_table_remove(smiley_shortcut_index, priv->shortcut);
-
- /* Insert the new shortcut. */
- g_hash_table_insert(smiley_shortcut_index, g_strdup(shortcut), smiley);
-
- g_free(priv->shortcut);
- priv->shortcut = g_strdup(shortcut);
-
- g_object_notify_by_pspec(G_OBJECT(smiley), properties[PROP_SHORTCUT]);
-
- purple_smileys_save();
-
- return TRUE;
-}
-
-void
-purple_smiley_set_data(PurpleSmiley *smiley, guchar *smiley_data,
- size_t smiley_data_len)
-{
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_if_fail(smiley != NULL);
- g_return_if_fail(smiley_data != NULL);
- g_return_if_fail(smiley_data_len > 0);
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- /* Remove the previous entry */
- g_hash_table_remove(smiley_checksum_index, priv->checksum);
-
- /* Update the file data. This also updates the checksum. */
- purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len);
-
- /* Reinsert the index item. */
- g_hash_table_insert(smiley_checksum_index, g_strdup(priv->checksum), smiley);
-
- purple_smileys_save();
-}
-
-PurpleStoredImage *
-purple_smiley_get_stored_image(const PurpleSmiley *smiley)
-{
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- return purple_imgstore_ref(priv->img);
-}
-
-const char *purple_smiley_get_shortcut(const PurpleSmiley *smiley)
-{
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_val_if_fail(smiley != NULL, NULL);
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- return priv->shortcut;
-}
-
-const char *
-purple_smiley_get_checksum(const PurpleSmiley *smiley)
-{
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_val_if_fail(smiley != NULL, NULL);
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
- return priv->checksum;
-}
-
-gconstpointer
-purple_smiley_get_data(const PurpleSmiley *smiley, size_t *len)
-{
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_val_if_fail(smiley != NULL, NULL);
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- if (priv->img) {
- if (len != NULL)
- *len = purple_imgstore_get_size(priv->img);
-
- return purple_imgstore_get_data(priv->img);
- }
-
- return NULL;
-}
-
-const char *
-purple_smiley_get_extension(const PurpleSmiley *smiley)
-{
- PurpleSmileyPrivate *priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- if (priv->img != NULL)
- return purple_imgstore_get_extension(priv->img);
-
- return NULL;
-}
-
-char *purple_smiley_get_full_path(PurpleSmiley *smiley)
-{
- PurpleSmileyPrivate *priv = NULL;
-
- g_return_val_if_fail(smiley != NULL, NULL);
-
- priv = PURPLE_SMILEY_GET_PRIVATE(smiley);
-
- if (priv->img == NULL)
- return NULL;
-
- return get_file_full_path(purple_imgstore_get_filename(priv->img));
-}
-
-static void add_smiley_to_list(gpointer key, gpointer value, gpointer user_data)
-{
- GList** returninglist = (GList**)user_data;
-
- *returninglist = g_list_append(*returninglist, value);
-}
-
-GList *
-purple_smileys_get_all(void)
-{
- GList *returninglist = NULL;
-
- g_hash_table_foreach(smiley_shortcut_index, add_smiley_to_list, &returninglist);
-
- return returninglist;
-}
-
-PurpleSmiley *
-purple_smileys_find_by_shortcut(const char *shortcut)
-{
- g_return_val_if_fail(shortcut != NULL, NULL);
-
- return g_hash_table_lookup(smiley_shortcut_index, shortcut);
-}
-
-PurpleSmiley *
-purple_smileys_find_by_checksum(const char *checksum)
-{
- g_return_val_if_fail(checksum != NULL, NULL);
-
- return g_hash_table_lookup(smiley_checksum_index, checksum);
-}
-
-const char *
-purple_smileys_get_storing_dir(void)
-{
- return smileys_dir;
-}
-
-void
-purple_smileys_init(void)
-{
- smiley_shortcut_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- smiley_checksum_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
- smileys_dir = g_build_filename(purple_user_dir(), SMILEYS_DEFAULT_FOLDER, NULL);
-
- purple_smileys_load();
-}
-
-void
-purple_smileys_uninit(void)
-{
- if (save_timer != 0) {
- purple_timeout_remove(save_timer);
- save_timer = 0;
- sync_smileys();
- }
-
- g_hash_table_destroy(smiley_shortcut_index);
- g_hash_table_destroy(smiley_checksum_index);
- g_free(smileys_dir);
-}
-