Mercurial > pidgin
comparison libpurple/buddyicon.c @ 20410:522ade544156
propagate im.pidgin.pidgin to im.pidgin.cpw.khc.msnp14
author | Ka-Hing Cheung <khc@hxbc.us> |
---|---|
date | Sun, 06 May 2007 02:17:45 +0000 |
parents | 9862a82206ba |
children | a1858493abe2 |
comparison
equal
deleted
inserted
replaced
20409:7c0a2ef88018 | 20410:522ade544156 |
---|---|
312 | 312 |
313 /* purple_buddy_icon_create() sets account & username */ | 313 /* purple_buddy_icon_create() sets account & username */ |
314 if (icon == NULL) | 314 if (icon == NULL) |
315 icon = purple_buddy_icon_create(account, username); | 315 icon = purple_buddy_icon_create(account, username); |
316 | 316 |
317 /* Take a reference for the caller of this function. */ | |
318 icon->ref_count = 1; | |
319 | |
320 /* purple_buddy_icon_set_data() sets img, but it | 317 /* purple_buddy_icon_set_data() sets img, but it |
321 * references img first, so we need to initialize it */ | 318 * references img first, so we need to initialize it */ |
322 icon->img = NULL; | 319 icon->img = NULL; |
323 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); | 320 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); |
324 | 321 |
370 { | 367 { |
371 PurpleConversation *conv; | 368 PurpleConversation *conv; |
372 PurpleAccount *account; | 369 PurpleAccount *account; |
373 const char *username; | 370 const char *username; |
374 PurpleBuddyIcon *icon_to_set; | 371 PurpleBuddyIcon *icon_to_set; |
375 GSList *sl, *list; | 372 GSList *buddies; |
376 | 373 |
377 g_return_if_fail(icon != NULL); | 374 g_return_if_fail(icon != NULL); |
378 | 375 |
379 account = purple_buddy_icon_get_account(icon); | 376 account = purple_buddy_icon_get_account(icon); |
380 username = purple_buddy_icon_get_username(icon); | 377 username = purple_buddy_icon_get_username(icon); |
381 | 378 |
382 /* If no data exists, then call the functions below with NULL to | 379 /* If no data exists (icon->img == NULL), then call the functions below |
383 * unset the icon. They will then unref the icon and it should be | 380 * with NULL to unset the icon. They will then unref the icon and it should |
384 * destroyed. The only way it wouldn't be destroyed is if someone | 381 * be destroyed. The only way it wouldn't be destroyed is if someone |
385 * else is holding a reference to it, in which case they can kill | 382 * else is holding a reference to it, in which case they can kill |
386 * the icon when they realize it has no data. */ | 383 * the icon when they realize it has no data. */ |
387 icon_to_set = icon->img ? icon : NULL; | 384 icon_to_set = icon->img ? icon : NULL; |
388 | 385 |
389 for (list = sl = purple_find_buddies(account, username); | 386 /* Ensure that icon remains valid throughout */ |
390 sl != NULL; | 387 if (icon) purple_buddy_icon_ref(icon); |
391 sl = sl->next) | 388 |
392 { | 389 buddies = purple_find_buddies(account, username); |
393 PurpleBuddy *buddy = (PurpleBuddy *)sl->data; | 390 while (buddies != NULL) |
391 { | |
392 PurpleBuddy *buddy = (PurpleBuddy *)buddies->data; | |
394 char *old_icon; | 393 char *old_icon; |
395 | 394 |
396 purple_buddy_set_icon(buddy, icon_to_set); | 395 purple_buddy_set_icon(buddy, icon_to_set); |
397 | |
398 | |
399 old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)buddy, | 396 old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)buddy, |
400 "buddy_icon")); | 397 "buddy_icon")); |
401 if (icon->img && purple_buddy_icons_is_caching()) | 398 if (icon->img && purple_buddy_icons_is_caching()) |
402 { | 399 { |
403 const char *filename = purple_imgstore_get_filename(icon->img); | 400 const char *filename = purple_imgstore_get_filename(icon->img); |
423 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); | 420 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); |
424 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum"); | 421 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum"); |
425 } | 422 } |
426 unref_filename(old_icon); | 423 unref_filename(old_icon); |
427 g_free(old_icon); | 424 g_free(old_icon); |
428 } | 425 |
429 | 426 buddies = g_slist_delete_link(buddies, buddies); |
430 g_slist_free(list); | 427 } |
431 | 428 |
432 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); | 429 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); |
433 | 430 |
434 if (conv != NULL) | 431 if (conv != NULL) |
435 purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set); | 432 purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set); |
433 | |
434 /* icon's refcount was incremented above */ | |
435 if (icon) purple_buddy_icon_unref(icon); | |
436 } | 436 } |
437 | 437 |
438 void | 438 void |
439 purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data, | 439 purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data, |
440 size_t len, const char *checksum) | 440 size_t len, const char *checksum) |
452 icon->img = purple_buddy_icon_data_new(data, len, NULL); | 452 icon->img = purple_buddy_icon_data_new(data, len, NULL); |
453 else | 453 else |
454 g_free(data); | 454 g_free(data); |
455 } | 455 } |
456 | 456 |
457 g_free(icon->checksum); | |
457 icon->checksum = g_strdup(checksum); | 458 icon->checksum = g_strdup(checksum); |
458 | 459 |
459 purple_buddy_icon_update(icon); | 460 purple_buddy_icon_update(icon); |
460 | 461 |
461 purple_imgstore_unref(old_img); | 462 purple_imgstore_unref(old_img); |
513 void | 514 void |
514 purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, | 515 purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, |
515 void *icon_data, size_t icon_len, | 516 void *icon_data, size_t icon_len, |
516 const char *checksum) | 517 const char *checksum) |
517 { | 518 { |
518 PurpleBuddyIcon *icon; | 519 GHashTable *icon_cache; |
520 PurpleBuddyIcon *icon = NULL; | |
519 | 521 |
520 g_return_if_fail(account != NULL); | 522 g_return_if_fail(account != NULL); |
521 g_return_if_fail(username != NULL); | 523 g_return_if_fail(username != NULL); |
522 | 524 |
523 icon = purple_buddy_icons_find(account, username); | 525 icon_cache = g_hash_table_lookup(account_cache, account); |
526 | |
527 if (icon_cache != NULL) | |
528 icon = g_hash_table_lookup(icon_cache, username); | |
524 | 529 |
525 if (icon != NULL) | 530 if (icon != NULL) |
526 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); | 531 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); |
527 else | 532 else if (icon_data && icon_len > 0) |
528 { | 533 { |
529 PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum); | 534 if (icon_data != NULL && icon_len > 0) |
530 purple_buddy_icon_unref(icon); | 535 { |
536 PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum); | |
537 | |
538 /* purple_buddy_icon_new() calls | |
539 * purple_buddy_icon_set_data(), which calls | |
540 * purple_buddy_icon_update(), which has the buddy list | |
541 * and conversations take references as appropriate. | |
542 * This function doesn't return icon, so we can't | |
543 * leave a reference dangling. */ | |
544 purple_buddy_icon_unref(icon); | |
545 } | |
546 else | |
547 { | |
548 /* If the buddy list or a conversation was holding a | |
549 * reference, we'd have found the icon in the cache. | |
550 * Since we know we're deleting the icon, we only | |
551 * need a subset of purple_buddy_icon_update(). */ | |
552 | |
553 GSList *buddies = purple_find_buddies(account, username); | |
554 while (buddies != NULL) | |
555 { | |
556 PurpleBuddy *buddy = (PurpleBuddy *)buddies->data; | |
557 | |
558 unref_filename(purple_blist_node_get_string((PurpleBlistNode *)buddy, "buddy_icon")); | |
559 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); | |
560 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum"); | |
561 | |
562 buddies = g_slist_delete_link(buddies, buddies); | |
563 } | |
564 | |
565 } | |
531 } | 566 } |
532 } | 567 } |
533 | 568 |
534 char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon) | 569 char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon) |
535 { | 570 { |
615 char *path = g_build_filename(dirname, protocol_icon_file, NULL); | 650 char *path = g_build_filename(dirname, protocol_icon_file, NULL); |
616 if (read_icon_file(path, &data, &len)) | 651 if (read_icon_file(path, &data, &len)) |
617 { | 652 { |
618 const char *checksum; | 653 const char *checksum; |
619 | 654 |
620 if (icon == NULL) | 655 icon = purple_buddy_icon_create(account, username); |
621 icon = purple_buddy_icon_create(account, username); | |
622 icon->ref_count = 0; | 656 icon->ref_count = 0; |
623 icon->img = NULL; | 657 icon->img = NULL; |
624 checksum = g_strdup(purple_blist_node_get_string((PurpleBlistNode*)b, "icon_checksum")); | 658 checksum = purple_blist_node_get_string((PurpleBlistNode*)b, "icon_checksum"); |
625 purple_buddy_icon_set_data(icon, data, len, checksum); | 659 purple_buddy_icon_set_data(icon, data, len, checksum); |
626 } | 660 } |
627 g_free(path); | 661 g_free(path); |
628 } | 662 } |
629 | 663 |
630 purple_buddy_icons_set_caching(caching); | 664 purple_buddy_icons_set_caching(caching); |
631 } | 665 } |
632 | 666 |
633 return icon; | 667 return purple_buddy_icon_ref(icon); |
634 } | 668 } |
635 | 669 |
636 gboolean | 670 gboolean |
637 purple_buddy_icons_has_custom_icon(PurpleContact *contact) | 671 purple_buddy_icons_has_custom_icon(PurpleContact *contact) |
638 { | 672 { |