comparison pidgin/gtkutils.c @ 16483:5e47b3427b28

propagate from branch 'im.pidgin.rlaager.gaim_migration' (head dcc40d46afbe3f87cc674e4fb1526ac722bc35cb) to branch 'im.pidgin.pidgin' (head 0ef5b6c44115778e329fd628324124f872f5253b)
author Sean Egan <seanegan@gmail.com>
date Fri, 27 Apr 2007 02:14:44 +0000
parents 08db93bbd798 24bbd7e46bfe
children 814be4aa9dc6
comparison
equal deleted inserted replaced
16467:b2044e10915a 16483:5e47b3427b28
76 { 76 {
77 g_idle_add(url_clicked_idle_cb, g_strdup(uri)); 77 g_idle_add(url_clicked_idle_cb, g_strdup(uri));
78 } 78 }
79 79
80 static GtkIMHtmlFuncs gtkimhtml_cbs = { 80 static GtkIMHtmlFuncs gtkimhtml_cbs = {
81 (GtkIMHtmlGetImageFunc)purple_imgstore_get, 81 (GtkIMHtmlGetImageFunc)purple_imgstore_find_by_id,
82 (GtkIMHtmlGetImageDataFunc)purple_imgstore_get_data, 82 (GtkIMHtmlGetImageDataFunc)purple_imgstore_get_data,
83 (GtkIMHtmlGetImageSizeFunc)purple_imgstore_get_size, 83 (GtkIMHtmlGetImageSizeFunc)purple_imgstore_get_size,
84 (GtkIMHtmlGetImageFilenameFunc)purple_imgstore_get_filename, 84 (GtkIMHtmlGetImageFilenameFunc)purple_imgstore_get_filename,
85 purple_imgstore_ref, 85 purple_imgstore_ref_by_id,
86 purple_imgstore_unref, 86 purple_imgstore_unref_by_id,
87 }; 87 };
88 88
89 void 89 void
90 pidgin_setup_imhtml(GtkWidget *imhtml) 90 pidgin_setup_imhtml(GtkWidget *imhtml)
91 { 91 {
1348 g_error_free(err); 1348 g_error_free(err);
1349 g_free(str); 1349 g_free(str);
1350 1350
1351 return; 1351 return;
1352 } 1352 }
1353 id = purple_imgstore_add(filedata, size, data->filename); 1353 id = purple_imgstore_add_with_id(filedata, size, data->filename);
1354 g_free(filedata);
1355 1354
1356 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter, 1355 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter,
1357 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer)); 1356 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer));
1358 gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter); 1357 gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter);
1359 purple_imgstore_unref(id); 1358 purple_imgstore_unref_by_id(id);
1360 1359
1361 break; 1360 break;
1362 } 1361 }
1363 free(data->filename); 1362 free(data->filename);
1364 free(data->who); 1363 free(data->who);
2416 return TRUE; 2415 return TRUE;
2417 return FALSE; 2416 return FALSE;
2418 } 2417 }
2419 #endif 2418 #endif
2420 2419
2421 char * 2420 gpointer
2422 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path) 2421 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len)
2423 { 2422 {
2424 PurplePluginProtocolInfo *prpl_info; 2423 PurplePluginProtocolInfo *prpl_info;
2425 #if GTK_CHECK_VERSION(2,2,0) 2424 #if GTK_CHECK_VERSION(2,2,0)
2426 char **prpl_formats; 2425 char **prpl_formats;
2427 int width, height; 2426 int width, height;
2428 char **pixbuf_formats = NULL; 2427 char **pixbuf_formats = NULL;
2429 struct stat st;
2430 GdkPixbufFormat *format; 2428 GdkPixbufFormat *format;
2431 GdkPixbuf *pixbuf; 2429 GdkPixbuf *pixbuf;
2432 #if !GTK_CHECK_VERSION(2,4,0) 2430 #if !GTK_CHECK_VERSION(2,4,0)
2433 GdkPixbufLoader *loader; 2431 GdkPixbufLoader *loader;
2434 #endif 2432 #endif
2435 #endif 2433 #endif
2436 gchar *contents; 2434 gchar *contents;
2437 gsize length; 2435 gsize length;
2438 const char *dirname;
2439 char *random;
2440 char *filename;
2441 2436
2442 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 2437 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
2443 2438
2444 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); 2439 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL);
2445 2440
2446 dirname = purple_buddy_icons_get_cache_dir();
2447 if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
2448 purple_debug_info("buddyicon", "Creating icon cache directory.\n");
2449
2450 if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
2451 purple_debug_error("buddyicon",
2452 "Unable to create directory %s: %s\n",
2453 dirname, strerror(errno));
2454 return NULL;
2455 }
2456 }
2457
2458 random = g_strdup_printf("%x", g_random_int());
2459 filename = g_build_filename(dirname, random, NULL);
2460 2441
2461 #if GTK_CHECK_VERSION(2,2,0) 2442 #if GTK_CHECK_VERSION(2,2,0)
2462 #if GTK_CHECK_VERSION(2,4,0) 2443 #if GTK_CHECK_VERSION(2,4,0)
2463 format = gdk_pixbuf_get_file_info(path, &width, &height); 2444 format = gdk_pixbuf_get_file_info(path, &width, &height);
2464 #else 2445 #else
2485 prpl_info->icon_spec.max_width >= width && 2466 prpl_info->icon_spec.max_width >= width &&
2486 prpl_info->icon_spec.min_height <= height && 2467 prpl_info->icon_spec.min_height <= height &&
2487 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ 2468 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */
2488 #endif 2469 #endif
2489 { 2470 {
2490 FILE *image;
2491
2492 #if GTK_CHECK_VERSION(2,2,0) 2471 #if GTK_CHECK_VERSION(2,2,0)
2493 g_strfreev(prpl_formats); 2472 g_strfreev(prpl_formats);
2494 g_strfreev(pixbuf_formats); 2473 g_strfreev(pixbuf_formats);
2495 #endif 2474 #endif
2496 2475 /* We don't need to scale the image. */
2497 /* We don't need to scale the image, so copy it to the cache folder verbatim */
2498 2476
2499 contents = NULL; 2477 contents = NULL;
2500 if (!g_file_get_contents(path, &contents, &length, NULL) || 2478 if (!g_file_get_contents(path, &contents, &length, NULL))
2501 (image = g_fopen(filename, "wb")) == NULL)
2502 { 2479 {
2503 g_free(random);
2504 g_free(filename);
2505 g_free(contents); 2480 g_free(contents);
2506 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2507 g_object_unref(G_OBJECT(pixbuf));
2508 #endif
2509 return NULL;
2510 }
2511
2512 if (fwrite(contents, 1, length, image) != length)
2513 {
2514 fclose(image);
2515 g_unlink(filename);
2516
2517 g_free(random);
2518 g_free(filename);
2519 g_free(contents);
2520 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2521 g_object_unref(G_OBJECT(pixbuf));
2522 #endif
2523 return NULL;
2524 }
2525 fclose(image);
2526 g_free(contents);
2527
2528 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) 2481 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2529 g_object_unref(G_OBJECT(pixbuf)); 2482 g_object_unref(G_OBJECT(pixbuf));
2530 #endif 2483 #endif
2484 return NULL;
2485 }
2531 } 2486 }
2532 #if GTK_CHECK_VERSION(2,2,0) 2487 #if GTK_CHECK_VERSION(2,2,0)
2533 else 2488 else
2534 { 2489 {
2535 int i; 2490 int i;
2536 GError *error = NULL; 2491 GError *error = NULL;
2537 GdkPixbuf *scale; 2492 GdkPixbuf *scale;
2538 gboolean success = FALSE; 2493 gboolean success = FALSE;
2494 char *filename = NULL;
2539 2495
2540 g_strfreev(pixbuf_formats); 2496 g_strfreev(pixbuf_formats);
2541 2497
2542 pixbuf = gdk_pixbuf_new_from_file(path, &error); 2498 pixbuf = gdk_pixbuf_new_from_file(path, &error);
2543 if (error) { 2499 if (error) {
2544 purple_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message); 2500 purple_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message);
2545 g_error_free(error); 2501 g_error_free(error);
2546 g_free(random);
2547 g_free(filename);
2548 g_strfreev(prpl_formats); 2502 g_strfreev(prpl_formats);
2549 return NULL; 2503 return NULL;
2550 } 2504 }
2551 2505
2552 if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) && 2506 if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) &&
2565 g_object_unref(G_OBJECT(pixbuf)); 2519 g_object_unref(G_OBJECT(pixbuf));
2566 pixbuf = scale; 2520 pixbuf = scale;
2567 } 2521 }
2568 2522
2569 for (i = 0; prpl_formats[i]; i++) { 2523 for (i = 0; prpl_formats[i]; i++) {
2524 FILE *fp;
2525
2526 g_free(filename);
2527 fp = purple_mkstemp(&filename, TRUE);
2528 if (!fp)
2529 {
2530 g_free(filename);
2531 return NULL;
2532 }
2533 fclose(fp);
2534
2570 purple_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename); 2535 purple_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename);
2571 /* The "compression" param wasn't supported until gdk-pixbuf 2.8. 2536 /* The "compression" param wasn't supported until gdk-pixbuf 2.8.
2572 * Using it in previous versions causes the save to fail (and an assert message). */ 2537 * Using it in previous versions causes the save to fail (and an assert message). */
2573 if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2 2538 if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2
2574 && gdk_pixbuf_minor_version >= 8)) 2539 && gdk_pixbuf_minor_version >= 8))
2593 } 2558 }
2594 g_strfreev(prpl_formats); 2559 g_strfreev(prpl_formats);
2595 g_object_unref(G_OBJECT(pixbuf)); 2560 g_object_unref(G_OBJECT(pixbuf));
2596 if (!success) { 2561 if (!success) {
2597 purple_debug_error("buddyicon", "Could not convert icon to usable format.\n"); 2562 purple_debug_error("buddyicon", "Could not convert icon to usable format.\n");
2598 g_free(random); 2563 return NULL;
2564 }
2565
2566 contents = NULL;
2567 if (!g_file_get_contents(filename, &contents, &length, NULL))
2568 {
2569 purple_debug_error("buddyicon",
2570 "Could not read '%s', which we just wrote to disk.\n",
2571 filename);
2572
2573 g_free(contents);
2599 g_free(filename); 2574 g_free(filename);
2600 return NULL; 2575 return NULL;
2601 } 2576 }
2602 } 2577
2603 2578 g_unlink(filename);
2604 if (g_stat(filename, &st) != 0) {
2605 purple_debug_error("buddyicon",
2606 "Could not stat '%s', which we just wrote to disk: %s\n",
2607 filename, strerror(errno));
2608 g_free(random);
2609 g_free(filename); 2579 g_free(filename);
2610 return NULL; 2580 }
2611 } 2581
2612 2582 /* Check the image size */
2613 /* Check the file size */
2614 /* 2583 /*
2615 * TODO: If the file is too big, it would be cool if we checked if 2584 * TODO: If the file is too big, it would be cool if we checked if
2616 * the prpl supported jpeg, and then we could convert to that 2585 * the prpl supported jpeg, and then we could convert to that
2617 * and use a lower quality setting. 2586 * and use a lower quality setting.
2618 */ 2587 */
2619 if ((prpl_info->icon_spec.max_filesize != 0) && 2588 if ((prpl_info->icon_spec.max_filesize != 0) &&
2620 (st.st_size > prpl_info->icon_spec.max_filesize)) 2589 (length > prpl_info->icon_spec.max_filesize))
2621 { 2590 {
2622 gchar *tmp; 2591 gchar *tmp;
2623 tmp = g_strdup_printf(_("The file '%s' is too large for %s. Please try a smaller image.\n"), 2592 tmp = g_strdup_printf(_("The file '%s' is too large for %s. Please try a smaller image.\n"),
2624 path, plugin->info->name); 2593 path, plugin->info->name);
2625 purple_notify_error(NULL, _("Icon Error"), 2594 purple_notify_error(NULL, _("Icon Error"),
2626 _("Could not set icon"), tmp); 2595 _("Could not set icon"), tmp);
2627 purple_debug_info("buddyicon", 2596 purple_debug_info("buddyicon",
2628 "'%s' was converted to an image which is %" G_GSIZE_FORMAT 2597 "'%s' was converted to an image which is %" G_GSIZE_FORMAT
2629 " bytes, but the maximum icon size for %s is %" G_GSIZE_FORMAT 2598 " bytes, but the maximum icon size for %s is %" G_GSIZE_FORMAT
2630 " bytes\n", path, st.st_size, plugin->info->name, 2599 " bytes\n", path, length, plugin->info->name,
2631 prpl_info->icon_spec.max_filesize); 2600 prpl_info->icon_spec.max_filesize);
2632 g_free(tmp); 2601 g_free(tmp);
2633 g_free(random);
2634 g_free(filename);
2635 return NULL; 2602 return NULL;
2636 } 2603 }
2637 2604
2638 g_free(filename); 2605 if (len)
2639 return random; 2606 *len = length;
2607 return contents;
2640 #else 2608 #else
2641 /* 2609 /*
2642 * The chosen icon wasn't the right size, and we're using 2610 * The chosen icon wasn't the right size, and we're using
2643 * GTK+ 2.0 so we can't scale it. 2611 * GTK+ 2.0 so we can't scale it.
2644 */ 2612 */
2787 } 2755 }
2788 #endif /* ! Gtk 2.6.0 */ 2756 #endif /* ! Gtk 2.6.0 */
2789 2757
2790 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) 2758 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename)
2791 { 2759 {
2792 PurpleConversation *conv;
2793 PurpleBuddy *buddy; 2760 PurpleBuddy *buddy;
2794 PurpleBlistNode *node; 2761 PurpleContact *contact;
2795 char *path = NULL; 2762 gpointer data = NULL;
2763 size_t len = 0;
2796 2764
2797 buddy = purple_find_buddy(account, who); 2765 buddy = purple_find_buddy(account, who);
2798 if (!buddy) { 2766 if (!buddy) {
2799 purple_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n"); 2767 purple_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n");
2800 return; 2768 return;
2801 } 2769 }
2802 2770
2803 node = (PurpleBlistNode*)purple_buddy_get_contact(buddy); 2771 contact = purple_buddy_get_contact(buddy);
2804 path = (char*)purple_blist_node_get_string(node, "custom_buddy_icon");
2805 if (path) {
2806 struct stat st;
2807 if (g_stat(path, &st) == 0)
2808 g_unlink(path);
2809 path = NULL;
2810 }
2811 2772
2812 if (filename) { 2773 if (filename) {
2813 char *newfile; 2774 const char *prpl_id = purple_account_get_protocol_id(account);
2814 2775 PurplePlugin *prpl = purple_find_prpl(prpl_id);
2815 newfile = pidgin_convert_buddy_icon(purple_find_prpl(purple_account_get_protocol_id(account)), 2776
2816 filename); 2777 data = pidgin_convert_buddy_icon(prpl, filename, &len);
2817 path = purple_buddy_icons_get_full_path(newfile); 2778
2818 g_free(newfile); 2779 /* We don't want to delete the old icon if the new one didn't load. */
2819 } 2780 if (data == NULL)
2820 2781 return;
2821 purple_blist_node_set_string(node, "custom_buddy_icon", path); 2782 }
2822 g_free(path); 2783
2823 2784 purple_buddy_icons_set_custom_icon(contact, data, len);
2824 /* Update the conversation */
2825 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
2826 if (conv)
2827 purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);
2828
2829 /* Update the buddylist */
2830 if (buddy)
2831 purple_blist_update_buddy_icon(buddy);
2832 } 2785 }
2833 2786
2834 char *pidgin_make_pretty_arrows(const char *str) 2787 char *pidgin_make_pretty_arrows(const char *str)
2835 { 2788 {
2836 char *ret; 2789 char *ret;