# HG changeset patch # User Richard Laager # Date 1178229469 0 # Node ID 56823a55581a8bb008849d423e0a489523e1b728 # Parent 41f85148a60ff77e9990340fc340212af6f18a31 Rework purple_buddy_icons_find() to return a reference for the caller, which is clearer and more consistent with other functions. Also, update purple_buddy_icons_set_for_user() to behave properly when called to clear an icon that isn't already in memory. diff -r 41f85148a60f -r 56823a55581a libpurple/buddyicon.c --- a/libpurple/buddyicon.c Thu May 03 15:37:25 2007 +0000 +++ b/libpurple/buddyicon.c Thu May 03 21:57:49 2007 +0000 @@ -314,9 +314,6 @@ if (icon == NULL) icon = purple_buddy_icon_create(account, username); - /* Take a reference for the caller of this function. */ - icon->ref_count = 1; - /* purple_buddy_icon_set_data() sets img, but it * references img first, so we need to initialize it */ icon->img = NULL; @@ -514,19 +511,53 @@ void *icon_data, size_t icon_len, const char *checksum) { - PurpleBuddyIcon *icon; + GHashTable *icon_cache; + PurpleBuddyIcon *icon = NULL; g_return_if_fail(account != NULL); g_return_if_fail(username != NULL); - icon = purple_buddy_icons_find(account, username); + icon_cache = g_hash_table_lookup(account_cache, account); + + if (icon_cache != NULL) + icon = g_hash_table_lookup(icon_cache, username); if (icon != NULL) purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); else { - PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum); - purple_buddy_icon_unref(icon); + if (icon_data != NULL && icon_len > 0) + { + PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum); + + /* purple_buddy_icon_new() calls + * purple_buddy_icon_set_data(), which calls + * purple_buddy_icon_update(), which has the buddy list + * and conversations take references as appropriate. + * This function doesn't return icon, so we can't + * leave a reference dangling. */ + purple_buddy_icon_unref(icon); + } + else + { + /* If the buddy list or a conversation was holding a + * reference, we'd have found the icon in the cache. + * Since we know we're deleting the icon, we only + * need a subset of purple_buddy_icon_update(). */ + + GSList *buddies = purple_find_buddies(account, username); + while (buddies != NULL) + { + PurpleBuddy *buddy = (PurpleBuddy *)buddies->data; + + unref_filename(purple_blist_node_get_string((PurpleBlistNode *)buddy, "buddy_icon")); + purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); + purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum"); + + buddies = g_slist_delete_link(buddies, buddies); + } + + } } } @@ -629,7 +660,7 @@ purple_buddy_icons_set_caching(caching); } - return icon; + return purple_buddy_icon_ref(icon); } gboolean diff -r 41f85148a60f -r 56823a55581a libpurple/buddyicon.h --- a/libpurple/buddyicon.h Thu May 03 15:37:25 2007 +0000 +++ b/libpurple/buddyicon.h Thu May 03 21:57:49 2007 +0000 @@ -54,7 +54,7 @@ * @param icon_len The buddy icon length. * @param checksum A protocol checksum from the prpl or @c NULL. * - * @return The buddy icon structure. + * @return The buddy icon structure, with a reference for the caller. */ PurpleBuddyIcon *purple_buddy_icon_new(PurpleAccount *account, const char *username, void *icon_data, size_t icon_len, @@ -209,7 +209,8 @@ * @param account The account the user is on. * @param username The username of the user. * - * @return The icon data if found, or @c NULL if not found. + * @return The icon (with a reference for the caller) if found, or @c NULL if + * not found. */ PurpleBuddyIcon * purple_buddy_icons_find(PurpleAccount *account, const char *username); diff -r 41f85148a60f -r 56823a55581a libpurple/conversation.c --- a/libpurple/conversation.c Thu May 03 15:37:25 2007 +0000 +++ b/libpurple/conversation.c Thu May 03 21:57:49 2007 +0000 @@ -279,7 +279,11 @@ ims = g_list_append(ims, conv); if ((icon = purple_buddy_icons_find(account, name))) + { purple_conv_im_set_icon(conv->u.im, icon); + /* purple_conv_im_set_icon refs the icon. */ + purple_buddy_icon_unref(icon); + } if (purple_prefs_get_bool("/purple/logging/log_ims")) { diff -r 41f85148a60f -r 56823a55581a libpurple/protocols/qq/buddy_info.c --- a/libpurple/protocols/qq/buddy_info.c Thu May 03 15:37:25 2007 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Thu May 03 21:57:49 2007 +0000 @@ -601,11 +601,14 @@ static void _qq_update_buddy_icon(PurpleAccount *account, const gchar *name, gint face) { - PurpleBuddyIcon *icon = purple_buddy_icons_find(account, name); + PurpleBuddy *buddy; gchar *icon_num_str = face_to_icon_str(face); - const gchar *old_icon_num = purple_buddy_icon_get_checksum(icon); + const gchar *old_icon_num = NULL; - if (icon == NULL || old_icon_num == NULL || + if ((buddy = purple_find_buddy(account, name))) + old_icon_num = purple_buddy_icons_get_checksum_for_user(buddy); + + if (old_icon_num == NULL || strcmp(icon_num_str, old_icon_num)) { gchar *icon_path; diff -r 41f85148a60f -r 56823a55581a pidgin/gtkblist.c --- a/pidgin/gtkblist.c Thu May 03 15:37:25 2007 +0000 +++ b/pidgin/gtkblist.c Thu May 03 21:57:49 2007 +0000 @@ -2160,7 +2160,7 @@ { GdkPixbuf *buf, *ret = NULL; GdkPixbufLoader *loader; - PurpleBuddyIcon *icon; + PurpleBuddyIcon *icon = NULL; const guchar *data = NULL; gsize len; PurpleBuddy *buddy = NULL; @@ -2197,9 +2197,9 @@ } if (data == NULL) { - if (!(icon = purple_buddy_get_icon(buddy))) - if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ - return NULL; + /* Not sure I like this...*/ + if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) + return NULL; data = purple_buddy_icon_get_data(icon, &len); if(data == NULL) @@ -2211,6 +2211,7 @@ gdk_pixbuf_loader_close(loader, NULL); purple_imgstore_unref(custom_img); + purple_buddy_icon_unref(icon); buf = gdk_pixbuf_loader_get_pixbuf(loader); if (buf)