comparison pidgin/gtkutils.c @ 29471:d83ee160ffb6

propagate from branch 'im.pidgin.pidgin' (head eb9385f349a20856b9d3f9911dbc8024caa44052) to branch 'im.pidgin.pidgin.next.minor' (head 439fb2dd7a285d9ca645f65f36ef0f037abe7311)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Wed, 19 Aug 2009 00:46:04 +0000
parents d4036e0f58d6
children dfd8d82313be 07718e5eb8ce 2dcff225172e
comparison
equal deleted inserted replaced
29470:7a3458436140 29471:d83ee160ffb6
52 #include "notify.h" 52 #include "notify.h"
53 #include "prefs.h" 53 #include "prefs.h"
54 #include "prpl.h" 54 #include "prpl.h"
55 #include "request.h" 55 #include "request.h"
56 #include "signals.h" 56 #include "signals.h"
57 #include "sound.h"
57 #include "util.h" 58 #include "util.h"
58 59
59 #include "gtkaccount.h" 60 #include "gtkaccount.h"
60 #include "gtkprefs.h" 61 #include "gtkprefs.h"
61 62
356 pidgin_set_accessible_label (menuitem, label); 357 pidgin_set_accessible_label (menuitem, label);
357 return menuitem; 358 return menuitem;
358 } 359 }
359 360
360 GtkWidget *pidgin_new_check_item(GtkWidget *menu, const char *str, 361 GtkWidget *pidgin_new_check_item(GtkWidget *menu, const char *str,
361 GtkSignalFunc sf, gpointer data, gboolean checked) 362 GCallback cb, gpointer data, gboolean checked)
362 { 363 {
363 GtkWidget *menuitem; 364 GtkWidget *menuitem;
364 menuitem = gtk_check_menu_item_new_with_mnemonic(str); 365 menuitem = gtk_check_menu_item_new_with_mnemonic(str);
365 366
366 if (menu) 367 if (menu)
367 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 368 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
368 369
369 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), checked); 370 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), checked);
370 371
371 if (sf) 372 if (cb)
372 g_signal_connect(G_OBJECT(menuitem), "activate", sf, data); 373 g_signal_connect(G_OBJECT(menuitem), "activate", cb, data);
373 374
374 gtk_widget_show_all(menuitem); 375 gtk_widget_show_all(menuitem);
375 376
376 return menuitem; 377 return menuitem;
377 } 378 }
437 438
438 return button; 439 return button;
439 } 440 }
440 441
441 442
442 GtkWidget *pidgin_new_item_from_stock(GtkWidget *menu, const char *str, const char *icon, GtkSignalFunc sf, gpointer data, guint accel_key, guint accel_mods, char *mod) 443 GtkWidget *pidgin_new_item_from_stock(GtkWidget *menu, const char *str, const char *icon, GCallback cb, gpointer data, guint accel_key, guint accel_mods, char *mod)
443 { 444 {
444 GtkWidget *menuitem; 445 GtkWidget *menuitem;
445 /* 446 /*
446 GtkWidget *hbox; 447 GtkWidget *hbox;
447 GtkWidget *label; 448 GtkWidget *label;
454 menuitem = gtk_image_menu_item_new_with_mnemonic(str); 455 menuitem = gtk_image_menu_item_new_with_mnemonic(str);
455 456
456 if (menu) 457 if (menu)
457 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 458 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
458 459
459 if (sf) 460 if (cb)
460 g_signal_connect(G_OBJECT(menuitem), "activate", sf, data); 461 g_signal_connect(G_OBJECT(menuitem), "activate", cb, data);
461 462
462 if (icon != NULL) { 463 if (icon != NULL) {
463 image = gtk_image_new_from_stock(icon, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); 464 image = gtk_image_new_from_stock(icon, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
464 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); 465 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
465 } 466 }
523 { 524 {
524 GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)); 525 GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
525 GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu)); 526 GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu));
526 if (p_item) 527 if (p_item)
527 (*p_item) = item; 528 (*p_item) = item;
528 return g_object_get_data(G_OBJECT(item), "aop_per_item_data"); 529 return item ? g_object_get_data(G_OBJECT(item), "aop_per_item_data") : NULL;
529 } 530 }
530 531
531 static void 532 static void
532 aop_menu_cb(GtkWidget *optmenu, GCallback cb) 533 aop_menu_cb(GtkWidget *optmenu, GCallback cb)
533 { 534 {
948 { 949 {
949 purple_debug(PURPLE_DEBUG_MISC, "accels", 950 purple_debug(PURPLE_DEBUG_MISC, "accels",
950 "accel changed, scheduling save.\n"); 951 "accel changed, scheduling save.\n");
951 952
952 if (!accels_save_timer) 953 if (!accels_save_timer)
953 accels_save_timer = g_timeout_add(5000, pidgin_save_accels, 954 accels_save_timer = purple_timeout_add_seconds(5, pidgin_save_accels,
954 NULL); 955 NULL);
955 } 956 }
956 957
957 gboolean 958 gboolean
958 pidgin_save_accels(gpointer data) 959 pidgin_save_accels(gpointer data)
1462 purple_notify_error(NULL, NULL, 1463 purple_notify_error(NULL, NULL,
1463 _("Failed to load image"), 1464 _("Failed to load image"),
1464 str); 1465 str);
1465 g_free(str); 1466 g_free(str);
1466 1467
1467 return; 1468 break;
1468 } 1469 }
1469 1470
1470 buddy = purple_find_buddy(data->account, data->who); 1471 buddy = purple_find_buddy(data->account, data->who);
1471 if (!buddy) { 1472 if (!buddy) {
1472 purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n"); 1473 purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n");
1492 str); 1493 str);
1493 1494
1494 g_error_free(err); 1495 g_error_free(err);
1495 g_free(str); 1496 g_free(str);
1496 1497
1497 return; 1498 break;
1498 } 1499 }
1499 id = purple_imgstore_add_with_id(filedata, size, data->filename); 1500 id = purple_imgstore_add_with_id(filedata, size, data->filename);
1500 1501
1501 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter, 1502 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter,
1502 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer)); 1503 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer));
1625 account, who, NULL, 1626 account, who, NULL,
1626 data, 1627 data,
1627 _("Set as buddy icon"), DND_BUDDY_ICON, 1628 _("Set as buddy icon"), DND_BUDDY_ICON,
1628 (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), 1629 (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE),
1629 NULL); 1630 NULL);
1630 gdk_pixbuf_unref(pb); 1631 g_object_unref(G_OBJECT(pb));
1631 return; 1632 return;
1632 } 1633 }
1633 1634
1634 #ifndef _WIN32 1635 #ifndef _WIN32
1635 /* Are we trying to send a .desktop file? */ 1636 /* Are we trying to send a .desktop file? */
1675 /* I don't know if we really want to do anything here. Most of the desktop item types are crap like 1676 /* I don't know if we really want to do anything here. Most of the desktop item types are crap like
1676 * "MIME Type" (I have no clue how that would be a desktop item) and "Comment"... nothing we can really 1677 * "MIME Type" (I have no clue how that would be a desktop item) and "Comment"... nothing we can really
1677 * send. The only logical one is "Application," but do we really want to send a binary and nothing else? 1678 * send. The only logical one is "Application," but do we really want to send a binary and nothing else?
1678 * Probably not. I'll just give an error and return. */ 1679 * Probably not. I'll just give an error and return. */
1679 /* The original patch sent the icon used by the launcher. That's probably wrong */ 1680 /* The original patch sent the icon used by the launcher. That's probably wrong */
1680 purple_notify_error(NULL, NULL, _("Cannot send launcher"), _("You dragged a desktop launcher. " 1681 purple_notify_error(NULL, NULL, _("Cannot send launcher"),
1681 "Most likely you wanted to send whatever this launcher points to instead of this launcher" 1682 _("You dragged a desktop launcher. Most "
1682 " itself.")); 1683 "likely you wanted to send the target "
1684 "of this launcher instead of this "
1685 "launcher itself."));
1683 break; 1686 break;
1684 } 1687 }
1685 purple_desktop_item_unref(item); 1688 purple_desktop_item_unref(item);
1686 return; 1689 return;
1687 } 1690 }
1713 1716
1714 GdkPixbuf * pidgin_create_status_icon(PurpleStatusPrimitive prim, GtkWidget *w, const char *size) 1717 GdkPixbuf * pidgin_create_status_icon(PurpleStatusPrimitive prim, GtkWidget *w, const char *size)
1715 { 1718 {
1716 GtkIconSize icon_size = gtk_icon_size_from_name(size); 1719 GtkIconSize icon_size = gtk_icon_size_from_name(size);
1717 GdkPixbuf *pixbuf = NULL; 1720 GdkPixbuf *pixbuf = NULL;
1718 1721 const char *stock = pidgin_stock_id_from_status_primitive(prim);
1719 if (prim == PURPLE_STATUS_UNAVAILABLE) 1722
1720 pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_BUSY, 1723 pixbuf = gtk_widget_render_icon (w, stock ? stock : PIDGIN_STOCK_STATUS_AVAILABLE,
1721 icon_size, "GtkWidget"); 1724 icon_size, "GtkWidget");
1722 else if (prim == PURPLE_STATUS_AWAY)
1723 pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AWAY,
1724 icon_size, "GtkWidget");
1725 else if (prim == PURPLE_STATUS_EXTENDED_AWAY)
1726 pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_XA,
1727 icon_size, "GtkWidget");
1728 else if (prim == PURPLE_STATUS_INVISIBLE)
1729 pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_INVISIBLE,
1730 icon_size, "GtkWidget");
1731 else if (prim == PURPLE_STATUS_OFFLINE)
1732 pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_OFFLINE,
1733 icon_size, "GtkWidget");
1734 else
1735 pixbuf = gtk_widget_render_icon (w, PIDGIN_STOCK_STATUS_AVAILABLE,
1736 icon_size, "GtkWidget");
1737 return pixbuf; 1725 return pixbuf;
1738 1726 }
1739 } 1727
1740 1728 static const char *
1729 stock_id_from_status_primitive_idle(PurpleStatusPrimitive prim, gboolean idle)
1730 {
1731 const char *stock = NULL;
1732 switch (prim) {
1733 case PURPLE_STATUS_UNSET:
1734 stock = NULL;
1735 break;
1736 case PURPLE_STATUS_UNAVAILABLE:
1737 stock = idle ? PIDGIN_STOCK_STATUS_BUSY_I : PIDGIN_STOCK_STATUS_BUSY;
1738 break;
1739 case PURPLE_STATUS_AWAY:
1740 stock = idle ? PIDGIN_STOCK_STATUS_AWAY_I : PIDGIN_STOCK_STATUS_AWAY;
1741 break;
1742 case PURPLE_STATUS_EXTENDED_AWAY:
1743 stock = idle ? PIDGIN_STOCK_STATUS_XA_I : PIDGIN_STOCK_STATUS_XA;
1744 break;
1745 case PURPLE_STATUS_INVISIBLE:
1746 stock = PIDGIN_STOCK_STATUS_INVISIBLE;
1747 break;
1748 case PURPLE_STATUS_OFFLINE:
1749 stock = idle ? PIDGIN_STOCK_STATUS_OFFLINE_I : PIDGIN_STOCK_STATUS_OFFLINE;
1750 break;
1751 default:
1752 stock = idle ? PIDGIN_STOCK_STATUS_AVAILABLE_I : PIDGIN_STOCK_STATUS_AVAILABLE;
1753 break;
1754 }
1755 return stock;
1756 }
1757
1758 const char *
1759 pidgin_stock_id_from_status_primitive(PurpleStatusPrimitive prim)
1760 {
1761 return stock_id_from_status_primitive_idle(prim, FALSE);
1762 }
1763
1764 const char *
1765 pidgin_stock_id_from_presence(PurplePresence *presence)
1766 {
1767 PurpleStatus *status;
1768 PurpleStatusType *type;
1769 PurpleStatusPrimitive prim;
1770 gboolean idle;
1771
1772 g_return_val_if_fail(presence, NULL);
1773
1774 status = purple_presence_get_active_status(presence);
1775 type = purple_status_get_type(status);
1776 prim = purple_status_type_get_primitive(type);
1777
1778 idle = purple_presence_is_idle(presence);
1779
1780 return stock_id_from_status_primitive_idle(prim, idle);
1781 }
1741 1782
1742 GdkPixbuf * 1783 GdkPixbuf *
1743 pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size) 1784 pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size)
1744 { 1785 {
1745 PurplePlugin *prpl; 1786 PurplePlugin *prpl;
2448 #endif /* FILECHOOSER */ 2489 #endif /* FILECHOOSER */
2449 const char *current_folder; 2490 const char *current_folder;
2450 2491
2451 dialog->callback = callback; 2492 dialog->callback = callback;
2452 dialog->data = data; 2493 dialog->data = data;
2453
2454 if (dialog->icon_filesel != NULL) {
2455 gtk_window_present(GTK_WINDOW(dialog->icon_filesel));
2456 return NULL;
2457 }
2458 2494
2459 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder"); 2495 current_folder = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder");
2460 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ 2496 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
2461 2497
2462 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"), 2498 dialog->icon_filesel = gtk_file_chooser_dialog_new(_("Buddy Icon"),
2946 #else 2982 #else
2947 /* do something else? */ 2983 /* do something else? */
2948 #endif 2984 #endif
2949 } 2985 }
2950 2986
2951 GSList *minidialogs = NULL; 2987 static GSList *minidialogs = NULL;
2952 2988
2953 static void * 2989 static void *
2954 pidgin_utils_get_handle(void) 2990 pidgin_utils_get_handle(void)
2955 { 2991 {
2956 static int handle; 2992 static int handle;
3541 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 3577 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3542 3578
3543 return TRUE; 3579 return TRUE;
3544 } 3580 }
3545 3581
3582 static void
3583 file_open_uri(GtkIMHtml *imhtml, const char *uri)
3584 {
3585 /* Copied from gtkft.c:open_button_cb */
3586 #ifdef _WIN32
3587 /* If using Win32... */
3588 int code;
3589 if (G_WIN32_HAVE_WIDECHAR_API()) {
3590 wchar_t *wc_filename = g_utf8_to_utf16(
3591 uri, -1, NULL, NULL, NULL);
3592
3593 code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL,
3594 SW_SHOW);
3595
3596 g_free(wc_filename);
3597 } else {
3598 char *l_filename = g_locale_from_utf8(
3599 uri, -1, NULL, NULL, NULL);
3600
3601 code = (int)ShellExecuteA(NULL, NULL, l_filename, NULL, NULL,
3602 SW_SHOW);
3603
3604 g_free(l_filename);
3605 }
3606
3607 if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC)
3608 {
3609 purple_notify_error(imhtml, NULL,
3610 _("There is no application configured to open this type of file."), NULL);
3611 }
3612 else if (code < 32)
3613 {
3614 purple_notify_error(imhtml, NULL,
3615 _("An error occurred while opening the file."), NULL);
3616 purple_debug_warning("gtkutils", "filename: %s; code: %d\n", uri, code);
3617 }
3618 #else
3619 char *command = NULL;
3620 char *tmp = NULL;
3621 GError *error = NULL;
3622
3623 if (purple_running_gnome())
3624 {
3625 char *escaped = g_shell_quote(uri);
3626 command = g_strdup_printf("gnome-open %s", escaped);
3627 g_free(escaped);
3628 }
3629 else if (purple_running_kde())
3630 {
3631 char *escaped = g_shell_quote(uri);
3632
3633 if (purple_str_has_suffix(uri, ".desktop"))
3634 command = g_strdup_printf("kfmclient openURL %s 'text/plain'", escaped);
3635 else
3636 command = g_strdup_printf("kfmclient openURL %s", escaped);
3637 g_free(escaped);
3638 }
3639 else
3640 {
3641 purple_notify_uri(NULL, uri);
3642 return;
3643 }
3644
3645 if (purple_program_is_valid(command))
3646 {
3647 gint exit_status;
3648 if (!g_spawn_command_line_sync(command, NULL, NULL, &exit_status, &error))
3649 {
3650 tmp = g_strdup_printf(_("Error launching %s: %s"),
3651 uri, error->message);
3652 purple_notify_error(imhtml, NULL, _("Unable to open file."), tmp);
3653 g_free(tmp);
3654 g_error_free(error);
3655 }
3656 if (exit_status != 0)
3657 {
3658 char *primary = g_strdup_printf(_("Error running %s"), command);
3659 char *secondary = g_strdup_printf(_("Process returned error code %d"),
3660 exit_status);
3661 purple_notify_error(imhtml, NULL, primary, secondary);
3662 g_free(tmp);
3663 }
3664 }
3665 #endif
3666 }
3667
3668 #define FILELINKSIZE (sizeof("file://") - 1)
3669 static gboolean
3670 file_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
3671 {
3672 const char *uri = gtk_imhtml_link_get_url(link) + FILELINKSIZE;
3673 file_open_uri(imhtml, uri);
3674 return TRUE;
3675 }
3676
3677 static gboolean
3678 open_containing_cb(GtkIMHtml *imhtml, const char *url)
3679 {
3680 char *dir = g_path_get_dirname(url + FILELINKSIZE);
3681 file_open_uri(imhtml, dir);
3682 g_free(dir);
3683 return TRUE;
3684 }
3685
3686 static gboolean
3687 file_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu)
3688 {
3689 GtkWidget *img, *item;
3690 const char *url;
3691
3692 url = gtk_imhtml_link_get_url(link);
3693
3694 /* Open File */
3695 img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU);
3696 item = gtk_image_menu_item_new_with_mnemonic(_("_Open File"));
3697 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3698 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
3699 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3700
3701 /* Open Containing Directory */
3702 #if GTK_CHECK_VERSION(2,6,0)
3703 img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
3704 item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
3705 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3706 #else
3707 item = gtk_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
3708 #endif
3709 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url);
3710 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3711
3712 return TRUE;
3713 }
3714
3715 #define AUDIOLINKSIZE (sizeof("audio://") - 1)
3716 static gboolean
3717 audio_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
3718 {
3719 const char *uri;
3720 PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv");
3721 if (!conv) /* no playback in debug window */
3722 return TRUE;
3723 uri = gtk_imhtml_link_get_url(link) + AUDIOLINKSIZE;
3724 purple_sound_play_file(uri, NULL);
3725 return TRUE;
3726 }
3727
3728 static void
3729 savefile_write_cb(gpointer user_data, char *file)
3730 {
3731 char *temp_file = user_data;
3732 gchar *contents;
3733 gsize length;
3734 GError *error;
3735
3736 if (!g_file_get_contents(temp_file, &contents, &length, &error)) {
3737 purple_debug_error("gtkutils", "Unable to read contents of %s: %s\n",
3738 temp_file, error->message);
3739 g_error_free(error);
3740 return;
3741 }
3742
3743 if (!purple_util_write_data_to_file_absolute(file, contents, length)) {
3744 purple_debug_error("gtkutils", "Unable to write contents to %s\n",
3745 file);
3746 }
3747 }
3748
3749 static gboolean
3750 save_file_cb(GtkWidget *item, const char *url)
3751 {
3752 PidginConversation *conv = g_object_get_data(G_OBJECT(item), "gtkconv");
3753 if (!conv)
3754 return TRUE;
3755 purple_request_file(conv->active_conv, _("Save File"), NULL, TRUE,
3756 G_CALLBACK(savefile_write_cb), NULL,
3757 conv->active_conv->account, NULL, conv->active_conv,
3758 (void *)url);
3759 return TRUE;
3760 }
3761
3762 static gboolean
3763 audio_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu)
3764 {
3765 GtkWidget *img, *item;
3766 const char *url;
3767 PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv");
3768 if (!conv) /* No menu in debug window */
3769 return TRUE;
3770
3771 url = gtk_imhtml_link_get_url(link);
3772
3773 /* Play Sound */
3774 #if GTK_CHECK_VERSION(2,6,0)
3775 img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
3776 item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound"));
3777 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3778 #else
3779 item = gtk_menu_item_new_with_mnemonic(_("_Play Sound"));
3780 #endif
3781 g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
3782 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3783
3784 /* Save File */
3785 img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU);
3786 item = gtk_image_menu_item_new_with_mnemonic(_("_Save File"));
3787 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
3788 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(save_file_cb), (gpointer)(url+AUDIOLINKSIZE));
3789 g_object_set_data(G_OBJECT(item), "gtkconv", conv);
3790 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3791
3792 return TRUE;
3793 }
3794
3546 /* XXX: The following two functions are for demonstration purposes only! */ 3795 /* XXX: The following two functions are for demonstration purposes only! */
3547 static gboolean 3796 static gboolean
3548 open_dialog(GtkIMHtml *imhtml, GtkIMHtmlLink *link) 3797 open_dialog(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
3549 { 3798 {
3550 const char *url; 3799 const char *url;
3581 3830
3582 tmp = g_find_program_in_path("gconftool-2"); 3831 tmp = g_find_program_in_path("gconftool-2");
3583 if (tmp == NULL) 3832 if (tmp == NULL)
3584 return FALSE; 3833 return FALSE;
3585 3834
3835 g_free(tmp);
3586 tmp = NULL; 3836 tmp = NULL;
3837
3587 if (!g_spawn_command_line_sync("gconftool-2 --all-dirs /desktop/gnome/url-handlers", 3838 if (!g_spawn_command_line_sync("gconftool-2 --all-dirs /desktop/gnome/url-handlers",
3588 &tmp, &err, NULL, NULL)) 3839 &tmp, &err, NULL, NULL))
3589 { 3840 {
3590 g_free(tmp); 3841 g_free(tmp);
3591 g_free(err); 3842 g_free(err);
3645 gtk_imhtml_class_register_protocol("https://", url_clicked_cb, link_context_menu); 3896 gtk_imhtml_class_register_protocol("https://", url_clicked_cb, link_context_menu);
3646 gtk_imhtml_class_register_protocol("ftp://", url_clicked_cb, link_context_menu); 3897 gtk_imhtml_class_register_protocol("ftp://", url_clicked_cb, link_context_menu);
3647 gtk_imhtml_class_register_protocol("gopher://", url_clicked_cb, link_context_menu); 3898 gtk_imhtml_class_register_protocol("gopher://", url_clicked_cb, link_context_menu);
3648 gtk_imhtml_class_register_protocol("mailto:", url_clicked_cb, copy_email_address); 3899 gtk_imhtml_class_register_protocol("mailto:", url_clicked_cb, copy_email_address);
3649 3900
3901 gtk_imhtml_class_register_protocol("file://", file_clicked_cb, file_context_menu);
3902 gtk_imhtml_class_register_protocol("audio://", audio_clicked_cb, audio_context_menu);
3903
3650 /* Example custom URL handler. */ 3904 /* Example custom URL handler. */
3651 gtk_imhtml_class_register_protocol("open://", open_dialog, dummy); 3905 gtk_imhtml_class_register_protocol("open://", open_dialog, dummy);
3652 3906
3653 /* If we're under GNOME, try registering the system URL handlers. */ 3907 /* If we're under GNOME, try registering the system URL handlers. */
3654 if (purple_running_gnome()) 3908 if (purple_running_gnome())
3671 g_list_free(gnome_url_handlers); 3925 g_list_free(gnome_url_handlers);
3672 gnome_url_handlers = NULL; 3926 gnome_url_handlers = NULL;
3673 return; 3927 return;
3674 } 3928 }
3675 3929
3930 gtk_imhtml_class_register_protocol("audio://", NULL, NULL);
3931 gtk_imhtml_class_register_protocol("file://", NULL, NULL);
3932
3676 gtk_imhtml_class_register_protocol("http://", NULL, NULL); 3933 gtk_imhtml_class_register_protocol("http://", NULL, NULL);
3677 gtk_imhtml_class_register_protocol("https://", NULL, NULL); 3934 gtk_imhtml_class_register_protocol("https://", NULL, NULL);
3678 gtk_imhtml_class_register_protocol("ftp://", NULL, NULL); 3935 gtk_imhtml_class_register_protocol("ftp://", NULL, NULL);
3679 gtk_imhtml_class_register_protocol("mailto:", NULL, NULL); 3936 gtk_imhtml_class_register_protocol("mailto:", NULL, NULL);
3680 gtk_imhtml_class_register_protocol("gopher://", NULL, NULL); 3937 gtk_imhtml_class_register_protocol("gopher://", NULL, NULL);