diff options
author | Tomasz Wasilczyk <twasilczyk@pidgin.im> | 2014-03-29 16:14:34 +0100 |
---|---|---|
committer | Tomasz Wasilczyk <twasilczyk@pidgin.im> | 2014-03-29 16:14:34 +0100 |
commit | f4826925ee4008825b5143d85e6825c627760126 (patch) | |
tree | 9333ade0bd5995d38199d91b31c268d1e68aabed /libpurple/smiley.c | |
parent | b20d4dac3a710cf2daa767a70f36027fbf6bc1d7 (diff) | |
download | pidgin-f4826925ee4008825b5143d85e6825c627760126.tar.gz |
Initial generic PurpleSmiley implementation
Diffstat (limited to 'libpurple/smiley.c')
-rw-r--r-- | libpurple/smiley.c | 880 |
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); -} - |