Remove useless comparison
[pidgin-git.git] / libpurple / smiley.c
blobbb7acd037a9c1fd587411a200add5d3bf0795c0e
1 /**
2 * @file smiley.c Simley API
3 * @ingroup core
4 */
6 /* purple
8 * Purple is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
27 #include "internal.h"
28 #include "dbus-maybe.h"
29 #include "debug.h"
30 #include "imgstore.h"
31 #include "smiley.h"
32 #include "util.h"
33 #include "xmlnode.h"
35 /**************************************************************************/
36 /* Main structures, members and constants */
37 /**************************************************************************/
39 struct _PurpleSmiley
41 GObject parent;
42 PurpleStoredImage *img; /**< The id of the stored image with the
43 the smiley data. */
44 char *shortcut; /**< Shortcut associated with the custom
45 smiley. This field will work as a
46 unique key by this API. */
47 char *checksum; /**< The smiley checksum. */
50 struct _PurpleSmileyClass
52 GObjectClass parent_class;
55 static GHashTable *smiley_shortcut_index = NULL; /* shortcut (char *) => smiley (PurpleSmiley*) */
56 static GHashTable *smiley_checksum_index = NULL; /* checksum (char *) => smiley (PurpleSmiley*) */
58 static guint save_timer = 0;
59 static gboolean smileys_loaded = FALSE;
60 static char *smileys_dir = NULL;
62 #define SMILEYS_DEFAULT_FOLDER "custom_smiley"
63 #define SMILEYS_LOG_ID "smileys"
65 #define XML_FILE_NAME "smileys.xml"
67 #define XML_ROOT_TAG "smileys"
68 #define XML_PROFILE_TAG "profile"
69 #define XML_PROFILE_NAME_ATTRIB_TAG "name"
70 #define XML_ACCOUNT_TAG "account"
71 #define XML_ACCOUNT_USERID_ATTRIB_TAG "userid"
72 #define XML_SMILEY_SET_TAG "smiley_set"
73 #define XML_SMILEY_TAG "smiley"
74 #define XML_SHORTCUT_ATTRIB_TAG "shortcut"
75 #define XML_CHECKSUM_ATRIB_TAG "checksum"
76 #define XML_FILENAME_ATRIB_TAG "filename"
79 /******************************************************************************
80 * XML descriptor file layout *
81 ******************************************************************************
83 * Although we are creating the profile XML structure here, now we
84 * won't handle it.
85 * So, we just add one profile named "default" that has no associated
86 * account elements, and have only the smiley_set that will contain
87 * all existent custom smiley.
89 * It's our "Highlander Profile" :-)
91 ******************************************************************************
93 * <smileys>
94 * <profile name="john.doe">
95 * <account userid="john.doe@jabber.org">
96 * <account userid="john.doe@gmail.com">
97 * <smiley_set>
98 * <smiley shortcut="aaa" checksum="xxxxxxxx" filename="file_name1.gif"/>
99 * <smiley shortcut="bbb" checksum="yyyyyyy" filename="file_name2.gif"/>
100 * </smiley_set>
101 * </profile>
102 * </smiley>
104 *****************************************************************************/
107 /*********************************************************************
108 * Forward declarations *
109 *********************************************************************/
111 static gboolean read_smiley_file(const char *path, guchar **data, size_t *len);
113 static char *get_file_full_path(const char *filename);
115 static PurpleSmiley *purple_smiley_create(const char *shortcut);
117 static void purple_smiley_load_file(const char *shortcut, const char *checksum,
118 const char *filename);
120 static void
121 purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data,
122 size_t smiley_data_len);
124 static void
125 purple_smiley_data_store(PurpleStoredImage *stored_img);
127 static void
128 purple_smiley_data_unstore(const char *filename);
130 /*********************************************************************
131 * Writing to disk *
132 *********************************************************************/
134 static xmlnode *
135 smiley_to_xmlnode(PurpleSmiley *smiley)
137 xmlnode *smiley_node = NULL;
139 smiley_node = xmlnode_new(XML_SMILEY_TAG);
141 if (!smiley_node)
142 return NULL;
144 xmlnode_set_attrib(smiley_node, XML_SHORTCUT_ATTRIB_TAG,
145 smiley->shortcut);
147 xmlnode_set_attrib(smiley_node, XML_CHECKSUM_ATRIB_TAG,
148 smiley->checksum);
150 xmlnode_set_attrib(smiley_node, XML_FILENAME_ATRIB_TAG,
151 purple_imgstore_get_filename(smiley->img));
153 return smiley_node;
156 static void
157 add_smiley_to_main_node(gpointer key, gpointer value, gpointer user_data)
159 xmlnode *child_node;
161 child_node = smiley_to_xmlnode(value);
162 xmlnode_insert_child((xmlnode*)user_data, child_node);
165 static xmlnode *
166 smileys_to_xmlnode(void)
168 xmlnode *root_node, *profile_node, *smileyset_node;
170 root_node = xmlnode_new(XML_ROOT_TAG);
171 xmlnode_set_attrib(root_node, "version", "1.0");
173 /* See the top comments above to understand why initial tag elements
174 * are not being considered by now. */
175 profile_node = xmlnode_new(XML_PROFILE_TAG);
176 if (profile_node) {
177 xmlnode_set_attrib(profile_node, XML_PROFILE_NAME_ATTRIB_TAG, "Default");
178 xmlnode_insert_child(root_node, profile_node);
180 smileyset_node = xmlnode_new(XML_SMILEY_SET_TAG);
181 if (smileyset_node) {
182 xmlnode_insert_child(profile_node, smileyset_node);
183 g_hash_table_foreach(smiley_shortcut_index, add_smiley_to_main_node, smileyset_node);
187 return root_node;
190 static void
191 sync_smileys(void)
193 xmlnode *root_node;
194 char *data;
196 if (!smileys_loaded) {
197 purple_debug_error(SMILEYS_LOG_ID, "Attempted to save smileys before it "
198 "was read!\n");
199 return;
202 root_node = smileys_to_xmlnode();
203 data = xmlnode_to_formatted_str(root_node, NULL);
204 purple_util_write_data_to_file(XML_FILE_NAME, data, -1);
206 g_free(data);
207 xmlnode_free(root_node);
210 static gboolean
211 save_smileys_cb(gpointer data)
213 sync_smileys();
214 save_timer = 0;
215 return FALSE;
218 static void
219 purple_smileys_save(void)
221 if (save_timer == 0)
222 save_timer = purple_timeout_add_seconds(5, save_smileys_cb, NULL);
226 /*********************************************************************
227 * Reading from disk *
228 *********************************************************************/
230 static void
231 parse_smiley(xmlnode *smiley_node)
233 const char *shortcut = NULL;
234 const char *checksum = NULL;
235 const char *filename = NULL;
237 shortcut = xmlnode_get_attrib(smiley_node, XML_SHORTCUT_ATTRIB_TAG);
238 checksum = xmlnode_get_attrib(smiley_node, XML_CHECKSUM_ATRIB_TAG);
239 filename = xmlnode_get_attrib(smiley_node, XML_FILENAME_ATRIB_TAG);
241 if ((shortcut == NULL) || (checksum == NULL) || (filename == NULL))
242 return;
244 purple_smiley_load_file(shortcut, checksum, filename);
247 static void
248 purple_smileys_load(void)
250 xmlnode *root_node, *profile_node;
251 xmlnode *smileyset_node = NULL;
252 xmlnode *smiley_node;
254 smileys_loaded = TRUE;
256 root_node = purple_util_read_xml_from_file(XML_FILE_NAME,
257 _(SMILEYS_LOG_ID));
259 if (root_node == NULL)
260 return;
262 /* See the top comments above to understand why initial tag elements
263 * are not being considered by now. */
264 profile_node = xmlnode_get_child(root_node, XML_PROFILE_TAG);
265 if (profile_node)
266 smileyset_node = xmlnode_get_child(profile_node, XML_SMILEY_SET_TAG);
268 if (smileyset_node) {
269 smiley_node = xmlnode_get_child(smileyset_node, XML_SMILEY_TAG);
270 for (; smiley_node != NULL;
271 smiley_node = xmlnode_get_next_twin(smiley_node)) {
272 parse_smiley(smiley_node);
276 xmlnode_free(root_node);
279 /*********************************************************************
280 * GObject Stuff *
281 *********************************************************************/
282 enum
284 PROP_0,
285 PROP_SHORTCUT,
286 PROP_IMGSTORE
289 #define PROP_SHORTCUT_S "shortcut"
290 #define PROP_IMGSTORE_S "image"
292 enum
294 SIG_DESTROY,
295 SIG_LAST
298 static guint signals[SIG_LAST];
299 static GObjectClass *parent_class;
301 static void
302 purple_smiley_init(GTypeInstance *instance, gpointer klass)
304 PurpleSmiley *smiley = PURPLE_SMILEY(instance);
305 PURPLE_DBUS_REGISTER_POINTER(smiley, PurpleSmiley);
308 static void
309 purple_smiley_get_property(GObject *object, guint param_id, GValue *value,
310 GParamSpec *spec)
312 PurpleSmiley *smiley = PURPLE_SMILEY(object);
313 switch (param_id) {
314 case PROP_SHORTCUT:
315 g_value_set_string(value, smiley->shortcut);
316 break;
317 case PROP_IMGSTORE:
318 g_value_set_pointer(value, smiley->img);
319 break;
320 default:
321 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec);
322 break;
326 static void
327 purple_smiley_set_property(GObject *object, guint param_id, const GValue *value,
328 GParamSpec *spec)
330 PurpleSmiley *smiley = PURPLE_SMILEY(object);
331 switch (param_id) {
332 case PROP_SHORTCUT:
334 const char *shortcut = g_value_get_string(value);
335 purple_smiley_set_shortcut(smiley, shortcut);
337 break;
338 case PROP_IMGSTORE:
340 PurpleStoredImage *img = g_value_get_pointer(value);
342 purple_imgstore_unref(smiley->img);
343 g_free(smiley->checksum);
345 smiley->img = img;
346 if (img) {
347 smiley->checksum = purple_util_get_image_checksum(
348 purple_imgstore_get_data(img),
349 purple_imgstore_get_size(img));
350 purple_smiley_data_store(img);
351 } else {
352 smiley->checksum = NULL;
355 g_object_notify(object, PROP_IMGSTORE_S);
357 break;
358 default:
359 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, spec);
360 break;
364 static void
365 purple_smiley_finalize(GObject *obj)
367 PurpleSmiley *smiley = PURPLE_SMILEY(obj);
369 if (g_hash_table_lookup(smiley_shortcut_index, smiley->shortcut)) {
370 g_hash_table_remove(smiley_shortcut_index, smiley->shortcut);
371 g_hash_table_remove(smiley_checksum_index, smiley->checksum);
374 g_free(smiley->shortcut);
375 g_free(smiley->checksum);
376 if (smiley->img)
377 purple_smiley_data_unstore(purple_imgstore_get_filename(smiley->img));
378 purple_imgstore_unref(smiley->img);
380 PURPLE_DBUS_UNREGISTER_POINTER(smiley);
382 purple_smileys_save();
385 static void
386 purple_smiley_dispose(GObject *gobj)
388 g_signal_emit(gobj, signals[SIG_DESTROY], 0);
389 parent_class->dispose(gobj);
392 static void
393 purple_smiley_class_init(PurpleSmileyClass *klass)
395 GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
396 GParamSpec *pspec;
398 parent_class = g_type_class_peek_parent(klass);
400 gobj_class->get_property = purple_smiley_get_property;
401 gobj_class->set_property = purple_smiley_set_property;
402 gobj_class->finalize = purple_smiley_finalize;
403 gobj_class->dispose = purple_smiley_dispose;
405 /* Shortcut */
406 pspec = g_param_spec_string(PROP_SHORTCUT_S, _("Shortcut"),
407 _("The text-shortcut for the smiley"),
408 NULL,
409 G_PARAM_READWRITE);
410 g_object_class_install_property(gobj_class, PROP_SHORTCUT, pspec);
412 /* Stored Image */
413 pspec = g_param_spec_pointer(PROP_IMGSTORE_S, _("Stored Image"),
414 _("Stored Image. (that'll have to do for now)"),
415 G_PARAM_READWRITE);
416 g_object_class_install_property(gobj_class, PROP_IMGSTORE, pspec);
418 signals[SIG_DESTROY] = g_signal_new("destroy",
419 G_OBJECT_CLASS_TYPE(klass),
420 G_SIGNAL_RUN_LAST,
421 0, NULL, NULL,
422 g_cclosure_marshal_VOID__VOID,
423 G_TYPE_NONE, 0);
426 GType
427 purple_smiley_get_type(void)
429 static GType type = 0;
431 if(type == 0) {
432 static const GTypeInfo info = {
433 sizeof(PurpleSmileyClass),
434 NULL,
435 NULL,
436 (GClassInitFunc)purple_smiley_class_init,
437 NULL,
438 NULL,
439 sizeof(PurpleSmiley),
441 purple_smiley_init,
442 NULL,
445 type = g_type_register_static(G_TYPE_OBJECT,
446 "PurpleSmiley",
447 &info, 0);
450 return type;
453 /*********************************************************************
454 * Other Stuff *
455 *********************************************************************/
457 static char *get_file_full_path(const char *filename)
459 char *path;
461 path = g_build_filename(purple_smileys_get_storing_dir(), filename, NULL);
463 if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
464 g_free(path);
465 return NULL;
468 return path;
471 static void
472 purple_smiley_load_file(const char *shortcut, const char *checksum, const char *filename)
474 PurpleSmiley *smiley = NULL;
475 guchar *smiley_data;
476 size_t smiley_data_len;
477 char *fullpath = NULL;
479 g_return_if_fail(shortcut != NULL);
480 g_return_if_fail(checksum != NULL);
481 g_return_if_fail(filename != NULL);
483 fullpath = get_file_full_path(filename);
484 if (!fullpath) {
485 purple_debug_error(SMILEYS_LOG_ID, "Path for filename %s doesn't exist\n", filename);
486 return;
489 smiley = purple_smiley_create(shortcut);
490 if (!smiley) {
491 g_free(fullpath);
492 return;
495 smiley->checksum = g_strdup(checksum);
497 if (read_smiley_file(fullpath, &smiley_data, &smiley_data_len))
498 purple_smiley_set_data_impl(smiley, smiley_data,
499 smiley_data_len);
500 else
501 purple_smiley_delete(smiley);
503 g_free(fullpath);
507 static void
508 purple_smiley_data_store(PurpleStoredImage *stored_img)
510 const char *dirname;
511 char *path;
512 FILE *file = NULL;
514 g_return_if_fail(stored_img != NULL);
516 if (!smileys_loaded)
517 return;
519 dirname = purple_smileys_get_storing_dir();
520 path = g_build_filename(dirname, purple_imgstore_get_filename(stored_img), NULL);
522 if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
523 purple_debug_info(SMILEYS_LOG_ID, "Creating smileys directory.\n");
525 if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
526 purple_debug_error(SMILEYS_LOG_ID,
527 "Unable to create directory %s: %s\n",
528 dirname, g_strerror(errno));
532 if ((file = g_fopen(path, "wb")) != NULL) {
533 if (!fwrite(purple_imgstore_get_data(stored_img),
534 purple_imgstore_get_size(stored_img), 1, file)) {
535 purple_debug_error(SMILEYS_LOG_ID, "Error writing %s: %s\n",
536 path, g_strerror(errno));
537 } else {
538 purple_debug_info(SMILEYS_LOG_ID, "Wrote cache file: %s\n", path);
541 fclose(file);
542 } else {
543 purple_debug_error(SMILEYS_LOG_ID, "Unable to create file %s: %s\n",
544 path, g_strerror(errno));
545 g_free(path);
547 return;
550 g_free(path);
553 static void
554 purple_smiley_data_unstore(const char *filename)
556 const char *dirname;
557 char *path;
559 g_return_if_fail(filename != NULL);
561 dirname = purple_smileys_get_storing_dir();
562 path = g_build_filename(dirname, filename, NULL);
564 if (g_file_test(path, G_FILE_TEST_EXISTS)) {
565 if (g_unlink(path))
566 purple_debug_error(SMILEYS_LOG_ID, "Failed to delete %s: %s\n",
567 path, g_strerror(errno));
568 else
569 purple_debug_info(SMILEYS_LOG_ID, "Deleted cache file: %s\n", path);
572 g_free(path);
575 static gboolean
576 read_smiley_file(const char *path, guchar **data, size_t *len)
578 GError *err = NULL;
580 if (!g_file_get_contents(path, (gchar **)data, len, &err)) {
581 purple_debug_error(SMILEYS_LOG_ID, "Error reading %s: %s\n",
582 path, err->message);
583 g_error_free(err);
585 return FALSE;
588 return TRUE;
591 static PurpleStoredImage *
592 purple_smiley_data_new(guchar *smiley_data, size_t smiley_data_len)
594 char *filename;
595 PurpleStoredImage *stored_img;
597 g_return_val_if_fail(smiley_data != NULL, NULL);
598 g_return_val_if_fail(smiley_data_len > 0, NULL);
600 filename = purple_util_get_image_filename(smiley_data, smiley_data_len);
602 if (filename == NULL) {
603 g_free(smiley_data);
604 return NULL;
607 stored_img = purple_imgstore_add(smiley_data, smiley_data_len, filename);
609 g_free(filename);
611 return stored_img;
614 static void
615 purple_smiley_set_data_impl(PurpleSmiley *smiley, guchar *smiley_data,
616 size_t smiley_data_len)
618 PurpleStoredImage *old_img, *new_img;
619 const char *old_filename = NULL;
620 const char *new_filename = NULL;
622 g_return_if_fail(smiley != NULL);
623 g_return_if_fail(smiley_data != NULL);
624 g_return_if_fail(smiley_data_len > 0);
626 old_img = smiley->img;
628 new_img = purple_smiley_data_new(smiley_data, smiley_data_len);
630 g_object_set(G_OBJECT(smiley), PROP_IMGSTORE_S, new_img, NULL);
632 /* If the old and new image files have different names we need
633 * to unstore old image file. */
634 if (!old_img)
635 return;
637 old_filename = purple_imgstore_get_filename(old_img);
638 new_filename = purple_imgstore_get_filename(smiley->img);
640 if (g_ascii_strcasecmp(old_filename, new_filename))
641 purple_smiley_data_unstore(old_filename);
642 purple_imgstore_unref(old_img);
646 /*****************************************************************************
647 * Public API functions *
648 *****************************************************************************/
650 static PurpleSmiley *
651 purple_smiley_create(const char *shortcut)
653 PurpleSmiley *smiley;
655 smiley = PURPLE_SMILEY(g_object_new(PURPLE_TYPE_SMILEY, PROP_SHORTCUT_S, shortcut, NULL));
657 return smiley;
660 PurpleSmiley *
661 purple_smiley_new(PurpleStoredImage *img, const char *shortcut)
663 PurpleSmiley *smiley = NULL;
665 g_return_val_if_fail(shortcut != NULL, NULL);
666 g_return_val_if_fail(img != NULL, NULL);
668 smiley = purple_smileys_find_by_shortcut(shortcut);
669 if (smiley)
670 return smiley;
672 smiley = purple_smiley_create(shortcut);
673 if (!smiley)
674 return NULL;
676 g_object_set(G_OBJECT(smiley), PROP_IMGSTORE_S, img, NULL);
678 return smiley;
681 static PurpleSmiley *
682 purple_smiley_new_from_stream(const char *shortcut, guchar *smiley_data,
683 size_t smiley_data_len)
685 PurpleSmiley *smiley;
687 g_return_val_if_fail(shortcut != NULL, NULL);
688 g_return_val_if_fail(smiley_data != NULL, NULL);
689 g_return_val_if_fail(smiley_data_len > 0, NULL);
691 smiley = purple_smileys_find_by_shortcut(shortcut);
692 if (smiley)
693 return smiley;
695 /* purple_smiley_create() sets shortcut */
696 smiley = purple_smiley_create(shortcut);
697 if (!smiley)
698 return NULL;
700 purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len);
702 purple_smiley_data_store(smiley->img);
704 return smiley;
707 PurpleSmiley *
708 purple_smiley_new_from_file(const char *shortcut, const char *filepath)
710 PurpleSmiley *smiley = NULL;
711 guchar *smiley_data;
712 size_t smiley_data_len;
714 g_return_val_if_fail(shortcut != NULL, NULL);
715 g_return_val_if_fail(filepath != NULL, NULL);
717 if (read_smiley_file(filepath, &smiley_data, &smiley_data_len)) {
718 smiley = purple_smiley_new_from_stream(shortcut, smiley_data,
719 smiley_data_len);
722 return smiley;
725 void
726 purple_smiley_delete(PurpleSmiley *smiley)
728 g_return_if_fail(smiley != NULL);
730 g_object_unref(smiley);
733 gboolean
734 purple_smiley_set_shortcut(PurpleSmiley *smiley, const char *shortcut)
736 g_return_val_if_fail(smiley != NULL, FALSE);
737 g_return_val_if_fail(shortcut != NULL, FALSE);
739 /* Check out whether the new shortcut is already being used. */
740 if (g_hash_table_lookup(smiley_shortcut_index, shortcut))
741 return FALSE;
743 /* Remove the old shortcut. */
744 if (smiley->shortcut)
745 g_hash_table_remove(smiley_shortcut_index, smiley->shortcut);
747 /* Insert the new shortcut. */
748 g_hash_table_insert(smiley_shortcut_index, g_strdup(shortcut), smiley);
750 g_free(smiley->shortcut);
751 smiley->shortcut = g_strdup(shortcut);
753 g_object_notify(G_OBJECT(smiley), PROP_SHORTCUT_S);
755 purple_smileys_save();
757 return TRUE;
760 void
761 purple_smiley_set_data(PurpleSmiley *smiley, guchar *smiley_data,
762 size_t smiley_data_len)
764 g_return_if_fail(smiley != NULL);
765 g_return_if_fail(smiley_data != NULL);
766 g_return_if_fail(smiley_data_len > 0);
768 /* Remove the previous entry */
769 g_hash_table_remove(smiley_checksum_index, smiley->checksum);
771 /* Update the file data. This also updates the checksum. */
772 purple_smiley_set_data_impl(smiley, smiley_data, smiley_data_len);
774 /* Reinsert the index item. */
775 g_hash_table_insert(smiley_checksum_index, g_strdup(smiley->checksum), smiley);
777 purple_smileys_save();
780 PurpleStoredImage *
781 purple_smiley_get_stored_image(const PurpleSmiley *smiley)
783 return purple_imgstore_ref(smiley->img);
786 const char *purple_smiley_get_shortcut(const PurpleSmiley *smiley)
788 g_return_val_if_fail(smiley != NULL, NULL);
790 return smiley->shortcut;
793 const char *
794 purple_smiley_get_checksum(const PurpleSmiley *smiley)
796 g_return_val_if_fail(smiley != NULL, NULL);
798 return smiley->checksum;
801 gconstpointer
802 purple_smiley_get_data(const PurpleSmiley *smiley, size_t *len)
804 g_return_val_if_fail(smiley != NULL, NULL);
806 if (smiley->img) {
807 if (len != NULL)
808 *len = purple_imgstore_get_size(smiley->img);
810 return purple_imgstore_get_data(smiley->img);
813 return NULL;
816 const char *
817 purple_smiley_get_extension(const PurpleSmiley *smiley)
819 if (smiley->img != NULL)
820 return purple_imgstore_get_extension(smiley->img);
822 return NULL;
825 char *purple_smiley_get_full_path(PurpleSmiley *smiley)
827 g_return_val_if_fail(smiley != NULL, NULL);
829 if (smiley->img == NULL)
830 return NULL;
832 return get_file_full_path(purple_imgstore_get_filename(smiley->img));
835 static void add_smiley_to_list(gpointer key, gpointer value, gpointer user_data)
837 GList** returninglist = (GList**)user_data;
839 *returninglist = g_list_append(*returninglist, value);
842 GList *
843 purple_smileys_get_all(void)
845 GList *returninglist = NULL;
847 g_hash_table_foreach(smiley_shortcut_index, add_smiley_to_list, &returninglist);
849 return returninglist;
852 PurpleSmiley *
853 purple_smileys_find_by_shortcut(const char *shortcut)
855 g_return_val_if_fail(shortcut != NULL, NULL);
857 return g_hash_table_lookup(smiley_shortcut_index, shortcut);
860 PurpleSmiley *
861 purple_smileys_find_by_checksum(const char *checksum)
863 g_return_val_if_fail(checksum != NULL, NULL);
865 return g_hash_table_lookup(smiley_checksum_index, checksum);
868 const char *
869 purple_smileys_get_storing_dir(void)
871 return smileys_dir;
874 void
875 purple_smileys_init(void)
877 smiley_shortcut_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
878 smiley_checksum_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
880 smileys_dir = g_build_filename(purple_user_dir(), SMILEYS_DEFAULT_FOLDER, NULL);
882 purple_smileys_load();
885 void
886 purple_smileys_uninit(void)
888 if (save_timer != 0) {
889 purple_timeout_remove(save_timer);
890 save_timer = 0;
891 sync_smileys();
894 g_hash_table_destroy(smiley_shortcut_index);
895 g_hash_table_destroy(smiley_checksum_index);
896 g_free(smileys_dir);