Another big rewrite of this stuff. Now all (well, most) attachments get a
* mail-display.c, mail-format.c: Another big rewrite of this stuff. Now all (well, most) attachments get a small icon with a description and a (non-obvious) right-click pop-up menu with options to save, open in an external program, or show/hide inline. TODO: antialias the icon, add more options to the pop-up for certain MIME types, add an icon to the headers, fix PGP to work like everything else, fix message/external-body to work again, add some icon caching action, etc, etc. svn path=/trunk/; revision=5326
This commit is contained in:
@ -1,3 +1,15 @@
|
||||
2000-09-11 Dan Winship <danw@helixcode.com>
|
||||
|
||||
* mail-display.c, mail-format.c: Another big rewrite of this
|
||||
stuff. Now all (well, most) attachments get a small icon with a
|
||||
description and a (non-obvious) right-click pop-up menu with
|
||||
options to save, open in an external program, or show/hide inline.
|
||||
|
||||
TODO: antialias the icon, add more options to the pop-up for
|
||||
certain MIME types, add an icon to the headers, fix PGP to work
|
||||
like everything else, fix message/external-body to work again,
|
||||
add some icon caching action, etc, etc.
|
||||
|
||||
2000-09-09 Jeffrey Stedfast <fejj@helixcode.com>
|
||||
|
||||
* mail-ops.c (do_fetch_mail): Use the CamelUIDCache so that we
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <gnome.h>
|
||||
#include "e-util/e-util.h"
|
||||
#include "e-util/e-html-utils.h"
|
||||
#include "e-util/e-popup-menu.h"
|
||||
#include "mail-display.h"
|
||||
#include "mail.h"
|
||||
|
||||
@ -29,7 +30,7 @@
|
||||
|
||||
static GtkObjectClass *mail_display_parent_class;
|
||||
|
||||
static void redisplay (MailDisplay *md);
|
||||
static void redisplay (MailDisplay *md, gboolean unscroll);
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Callbacks
|
||||
@ -116,22 +117,92 @@ make_safe_filename (const char *prefix, CamelMimePart *part)
|
||||
return safe;
|
||||
}
|
||||
|
||||
static CamelMimePart *
|
||||
part_for_url (const char *url, MailDisplay *md)
|
||||
static void
|
||||
save_data_cb (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
GHashTable *urls;
|
||||
GtkFileSelection *file_select = (GtkFileSelection *)
|
||||
gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_SELECTION);
|
||||
|
||||
urls = g_datalist_get_data (md->data, "urls");
|
||||
g_return_val_if_fail (urls != NULL, NULL);
|
||||
return g_hash_table_lookup (urls, url);
|
||||
write_data_to_file (user_data,
|
||||
gtk_file_selection_get_filename (file_select),
|
||||
FALSE);
|
||||
gtk_widget_destroy (GTK_WIDGET (file_select));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_redisplay (gpointer data)
|
||||
{
|
||||
MailDisplay *md = data;
|
||||
|
||||
md->idle_id = 0;
|
||||
redisplay (md, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
launch_external (const char *url, MailDisplay *md)
|
||||
queue_redisplay (MailDisplay *md)
|
||||
{
|
||||
const char *command = url + 21;
|
||||
char *tmpl, *tmpdir, *filename, *argv[2];
|
||||
CamelMimePart *part = part_for_url (url, md);
|
||||
if (!md->idle_id) {
|
||||
md->idle_id = g_idle_add_full (G_PRIORITY_LOW, idle_redisplay,
|
||||
md, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_link_clicked (GtkHTML *html, const char *url, gpointer user_data)
|
||||
{
|
||||
MailDisplay *md = user_data;
|
||||
|
||||
if (!g_strncasecmp (url, "news:", 5) ||
|
||||
!g_strncasecmp (url, "nntp:", 5))
|
||||
g_warning ("Can't handle news URLs yet.");
|
||||
else if (!g_strncasecmp (url, "mailto:", 7))
|
||||
send_to_url (url);
|
||||
else if (!strcmp (url, "x-evolution-decode-pgp:")) {
|
||||
g_datalist_set_data (md->data, "show_pgp",
|
||||
GINT_TO_POINTER (1));
|
||||
queue_redisplay (md);
|
||||
} else
|
||||
gnome_url_show (url);
|
||||
}
|
||||
|
||||
static void
|
||||
save_cb (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
CamelMimePart *part = gtk_object_get_data (user_data, "CamelMimePart");
|
||||
GtkFileSelection *file_select;
|
||||
char *filename;
|
||||
|
||||
filename = make_safe_filename (g_get_home_dir (), part);
|
||||
file_select = GTK_FILE_SELECTION (
|
||||
gtk_file_selection_new ("Save Attachment"));
|
||||
gtk_file_selection_set_filename (file_select, filename);
|
||||
g_free (filename);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (file_select->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC (save_data_cb), part);
|
||||
gtk_signal_connect_object (GTK_OBJECT (file_select->cancel_button),
|
||||
"clicked",
|
||||
GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
GTK_OBJECT (file_select));
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (file_select));
|
||||
}
|
||||
|
||||
static void
|
||||
launch_cb (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
CamelMimePart *part = gtk_object_get_data (user_data, "CamelMimePart");
|
||||
GnomeVFSMimeApplication *app;
|
||||
GMimeContentField *content_type;
|
||||
char *mime_type, *tmpl, *tmpdir, *filename, *argv[2];
|
||||
|
||||
content_type = camel_mime_part_get_content_type (part);
|
||||
mime_type = gmime_content_field_get_mime_type (content_type);
|
||||
app = gnome_vfs_mime_get_default_application (mime_type);
|
||||
g_free (mime_type);
|
||||
|
||||
g_return_if_fail (app != NULL);
|
||||
|
||||
tmpl = g_strdup ("/tmp/evolution.XXXXXX");
|
||||
#ifdef HAVE_MKDTEMP
|
||||
@ -160,7 +231,7 @@ launch_external (const char *url, MailDisplay *md)
|
||||
return;
|
||||
}
|
||||
|
||||
argv[0] = (char *)command;
|
||||
argv[0] = app->command;
|
||||
argv[1] = filename;
|
||||
|
||||
gnome_execute_async (tmpdir, 2, argv);
|
||||
@ -169,82 +240,86 @@ launch_external (const char *url, MailDisplay *md)
|
||||
}
|
||||
|
||||
static void
|
||||
save_data_cb (GtkWidget *widget, gpointer user_data)
|
||||
inline_cb (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
GtkFileSelection *file_select = (GtkFileSelection *)
|
||||
gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_SELECTION);
|
||||
MailDisplay *md = gtk_object_get_data (user_data, "MailDisplay");
|
||||
CamelMimePart *part = gtk_object_get_data (user_data, "CamelMimePart");
|
||||
|
||||
write_data_to_file (user_data,
|
||||
gtk_file_selection_get_filename (file_select),
|
||||
FALSE);
|
||||
gtk_widget_destroy (GTK_WIDGET (file_select));
|
||||
}
|
||||
if (mail_part_is_inline (part))
|
||||
camel_mime_part_set_disposition (part, "attachment");
|
||||
else
|
||||
camel_mime_part_set_disposition (part, "inline");
|
||||
|
||||
static void
|
||||
save_data (const char *cid, MailDisplay *md)
|
||||
{
|
||||
GtkFileSelection *file_select;
|
||||
char *filename;
|
||||
CamelMimePart *part;
|
||||
|
||||
part = part_for_url (cid, md);
|
||||
g_return_if_fail (part != NULL);
|
||||
filename = make_safe_filename (g_get_home_dir (), part);
|
||||
|
||||
file_select = GTK_FILE_SELECTION (gtk_file_selection_new ("Save Attachment"));
|
||||
gtk_file_selection_set_filename (file_select, filename);
|
||||
g_free (filename);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (file_select->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC (save_data_cb), part);
|
||||
gtk_signal_connect_object (GTK_OBJECT (file_select->cancel_button),
|
||||
"clicked",
|
||||
GTK_SIGNAL_FUNC (gtk_widget_destroy),
|
||||
GTK_OBJECT (file_select));
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (file_select));
|
||||
queue_redisplay (md);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_redisplay (gpointer data)
|
||||
pixmap_press (GtkWidget *ebox, GdkEventButton *event, gpointer user_data)
|
||||
{
|
||||
MailDisplay *md = data;
|
||||
EPopupMenu menu[] = {
|
||||
{ N_("Save to Disk..."), NULL,
|
||||
GTK_SIGNAL_FUNC (save_cb), 0 },
|
||||
{ N_("Open in %s..."), NULL,
|
||||
GTK_SIGNAL_FUNC (launch_cb), 1 },
|
||||
{ N_("View Inline"), NULL,
|
||||
GTK_SIGNAL_FUNC (inline_cb), 2 },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
};
|
||||
CamelMimePart *part;
|
||||
MailMimeHandler *handler;
|
||||
int mask;
|
||||
|
||||
md->idle_id = 0;
|
||||
redisplay (md);
|
||||
return FALSE;
|
||||
}
|
||||
if (event->button != 3)
|
||||
return FALSE;
|
||||
|
||||
static void
|
||||
queue_redisplay (MailDisplay *md)
|
||||
{
|
||||
if (!md->idle_id) {
|
||||
md->idle_id = g_idle_add_full (G_PRIORITY_LOW, idle_redisplay,
|
||||
md, NULL);
|
||||
part = gtk_object_get_data (user_data, "CamelMimePart");
|
||||
handler = mail_lookup_handler (gtk_object_get_data (user_data,
|
||||
"mime_type"));
|
||||
|
||||
/* External view item */
|
||||
if (handler && handler->application) {
|
||||
menu[1].name = g_strdup_printf (menu[1].name,
|
||||
handler->application->name);
|
||||
} else {
|
||||
menu[1].name = g_strdup_printf (menu[1].name,
|
||||
N_("External Viewer"));
|
||||
mask |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_link_clicked (GtkHTML *html, const char *url, gpointer user_data)
|
||||
{
|
||||
MailDisplay *md = user_data;
|
||||
/* Inline view item */
|
||||
if (handler && handler->builtin) {
|
||||
if (!mail_part_is_inline (part)) {
|
||||
if (handler->component) {
|
||||
OAF_Property *prop;
|
||||
char *name;
|
||||
|
||||
if (!g_strncasecmp (url, "news:", 5) ||
|
||||
!g_strncasecmp (url, "nntp:", 5))
|
||||
g_warning ("Can't handle news URLs yet.");
|
||||
else if (!g_strncasecmp (url, "mailto:", 7))
|
||||
send_to_url (url);
|
||||
else if (!strncmp (url, "cid:", 4))
|
||||
save_data (url, md);
|
||||
else if (!strncmp (url, "x-evolution-external:", 21))
|
||||
launch_external (url, md);
|
||||
else if (!strcmp (url, "x-evolution-decode-pgp:")) {
|
||||
g_datalist_set_data (md->data, "show_pgp",
|
||||
GINT_TO_POINTER (1));
|
||||
queue_redisplay (md);
|
||||
} else
|
||||
gnome_url_show (url);
|
||||
}
|
||||
prop = oaf_server_info_prop_find (
|
||||
handler->component, "name");
|
||||
if (!prop) {
|
||||
prop = oaf_server_info_prop_find (
|
||||
handler->component,
|
||||
"description");
|
||||
}
|
||||
if (prop && prop->v._d == OAF_P_STRING)
|
||||
name = prop->v._u.value_string;
|
||||
else
|
||||
name = "bonobo";
|
||||
menu[2].name = g_strdup_printf (
|
||||
N_("View Inline (via %s)"), name);
|
||||
} else
|
||||
menu[2].name = g_strdup (menu[2].name);
|
||||
} else
|
||||
menu[2].name = g_strdup (N_("Hide"));
|
||||
} else {
|
||||
menu[2].name = g_strdup (menu[2].name);
|
||||
mask |= 2;
|
||||
}
|
||||
|
||||
e_popup_menu_run (menu, event, mask, 0, user_data);
|
||||
g_free (menu[1].name);
|
||||
g_free (menu[2].name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
|
||||
@ -261,28 +336,77 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
|
||||
GByteArray *ba;
|
||||
CamelStream *cstream;
|
||||
BonoboStream *bstream;
|
||||
char *cid;
|
||||
|
||||
if (strncmp (eb->classid, "cid:", 4) != 0)
|
||||
cid = eb->classid;
|
||||
if (!strncmp (cid, "popup:", 6))
|
||||
cid += 6;
|
||||
if (strncmp (cid, "cid:", 4) != 0)
|
||||
return FALSE;
|
||||
|
||||
urls = g_datalist_get_data (md->data, "urls");
|
||||
g_return_val_if_fail (urls != NULL, FALSE);
|
||||
|
||||
medium = g_hash_table_lookup (urls, eb->classid);
|
||||
medium = g_hash_table_lookup (urls, cid);
|
||||
g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), FALSE);
|
||||
wrapper = camel_medium_get_content_object (medium);
|
||||
|
||||
if (cid != eb->classid) {
|
||||
/* This is a part wrapper */
|
||||
const char *icon;
|
||||
GtkWidget *pixmap, *ebox;
|
||||
|
||||
icon = gnome_vfs_mime_get_value (eb->type, "icon-filename");
|
||||
if (icon) {
|
||||
pixmap = gnome_pixmap_new_from_file_at_size (icon,
|
||||
24, 24);
|
||||
} else {
|
||||
char *filename;
|
||||
|
||||
filename = gnome_pixmap_file ("gnome-unknown.png");
|
||||
pixmap = gnome_pixmap_new_from_file_at_size (filename,
|
||||
24, 24);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
ebox = gtk_event_box_new ();
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (ebox), TRUE);
|
||||
gtk_widget_add_events (GTK_WIDGET (ebox),
|
||||
GDK_BUTTON_PRESS_MASK);
|
||||
gtk_signal_connect (GTK_OBJECT (ebox), "button_press_event",
|
||||
GTK_SIGNAL_FUNC (pixmap_press), ebox);
|
||||
gtk_object_set_data (GTK_OBJECT (ebox), "MailDisplay", md);
|
||||
gtk_object_set_data (GTK_OBJECT (ebox), "CamelMimePart",
|
||||
medium);
|
||||
gtk_object_set_data_full (GTK_OBJECT (ebox), "mime_type",
|
||||
g_strdup (eb->type),
|
||||
(GDestroyNotify)g_free);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (ebox), pixmap);
|
||||
gtk_widget_show_all (ebox);
|
||||
gtk_container_add (GTK_CONTAINER (eb), ebox);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
component = gnome_vfs_mime_get_default_component (eb->type);
|
||||
if (!component)
|
||||
return FALSE;
|
||||
|
||||
embedded = bonobo_widget_new_subdoc (component->iid, NULL);
|
||||
if (!embedded)
|
||||
if (embedded) {
|
||||
/* FIXME: as of bonobo 0.18, there's an extra
|
||||
* client_site dereference in the BonoboWidget
|
||||
* destruction path that we have to balance out to
|
||||
* prevent problems.
|
||||
*/
|
||||
bonobo_object_ref (bonobo_widget_get_client_site (
|
||||
BONOBO_WIDGET (embedded)));
|
||||
} else
|
||||
embedded = bonobo_widget_new_control (component->iid, NULL);
|
||||
CORBA_free (component);
|
||||
if (!embedded)
|
||||
return FALSE;
|
||||
server = bonobo_widget_get_server (BONOBO_WIDGET (embedded));
|
||||
|
||||
server = bonobo_widget_get_server (BONOBO_WIDGET (embedded));
|
||||
persist = (Bonobo_PersistStream) bonobo_object_client_query_interface (
|
||||
server, "IDL:Bonobo/PersistStream:1.0", NULL);
|
||||
if (persist == CORBA_OBJECT_NIL) {
|
||||
@ -293,6 +417,7 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
|
||||
/* Write the data to a CamelStreamMem... */
|
||||
ba = g_byte_array_new ();
|
||||
cstream = camel_stream_mem_new_with_byte_array (ba);
|
||||
wrapper = camel_medium_get_content_object (medium);
|
||||
camel_data_wrapper_write_to_stream (wrapper, cstream);
|
||||
|
||||
/* ...convert the CamelStreamMem to a BonoboStreamMem... */
|
||||
@ -422,9 +547,15 @@ clear_data (CamelObject *object, gpointer event_data, gpointer user_data)
|
||||
}
|
||||
|
||||
static void
|
||||
redisplay (MailDisplay *md)
|
||||
redisplay (MailDisplay *md, gboolean unscroll)
|
||||
{
|
||||
GtkAdjustment *adj;
|
||||
gfloat oldv;
|
||||
|
||||
if (!unscroll) {
|
||||
adj = e_scroll_frame_get_vadjustment (md->scroll);
|
||||
oldv = adj->value;
|
||||
}
|
||||
|
||||
md->stream = gtk_html_begin (md->html);
|
||||
mail_html_write (md->html, md->stream, "%s%s", HTML_HEADER,
|
||||
@ -439,13 +570,17 @@ redisplay (MailDisplay *md)
|
||||
gtk_html_end (md->html, md->stream, GTK_HTML_STREAM_OK);
|
||||
md->stream = NULL;
|
||||
|
||||
adj = e_scroll_frame_get_vadjustment (md->scroll);
|
||||
gtk_adjustment_set_value (adj, 0);
|
||||
e_scroll_frame_set_vadjustment (md->scroll, adj);
|
||||
|
||||
adj = e_scroll_frame_get_hadjustment (md->scroll);
|
||||
gtk_adjustment_set_value (adj, 0);
|
||||
e_scroll_frame_set_hadjustment (md->scroll, adj);
|
||||
if (unscroll) {
|
||||
adj = e_scroll_frame_get_hadjustment (md->scroll);
|
||||
gtk_adjustment_set_value (adj, 0);
|
||||
e_scroll_frame_set_hadjustment (md->scroll, adj);
|
||||
} else {
|
||||
adj = e_scroll_frame_get_vadjustment (md->scroll);
|
||||
if (oldv < adj->upper) {
|
||||
gtk_adjustment_set_value (adj, oldv);
|
||||
e_scroll_frame_set_vadjustment (md->scroll, adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -472,7 +607,7 @@ mail_display_set_message (MailDisplay *md, CamelMedium *medium)
|
||||
md->current_message = (CamelMimeMessage*)medium;
|
||||
|
||||
g_datalist_init (md->data);
|
||||
redisplay (md);
|
||||
redisplay (md, TRUE);
|
||||
if (medium) {
|
||||
camel_object_hook_event (CAMEL_OBJECT (medium), "finalize",
|
||||
clear_data, *(md->data));
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include <libgnome/libgnome.h>
|
||||
#include <libgnomevfs/gnome-vfs-mime-info.h>
|
||||
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
|
||||
#include <liboaf/liboaf.h>
|
||||
|
||||
#include <ctype.h> /* for isprint */
|
||||
#include <string.h> /* for strstr */
|
||||
@ -69,9 +70,6 @@ static gboolean handle_multipart_appledouble (CamelMimePart *part,
|
||||
static gboolean handle_multipart_encrypted (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
static gboolean handle_audio (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
static gboolean handle_message_rfc822 (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
@ -79,15 +77,9 @@ static gboolean handle_message_external_body (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
|
||||
static gboolean handle_unknown_type (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
static gboolean handle_via_bonobo (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
static gboolean handle_via_external (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
|
||||
/* writes the header info for a mime message into an html stream */
|
||||
static void write_headers (CamelMimeMessage *message, MailDisplay *md);
|
||||
@ -95,7 +87,6 @@ static void write_headers (CamelMimeMessage *message, MailDisplay *md);
|
||||
/* dispatch html printing via mimetype */
|
||||
static gboolean call_handler_function (CamelMimePart *part, MailDisplay *md);
|
||||
|
||||
|
||||
static void
|
||||
free_url (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
@ -226,21 +217,13 @@ get_url_for_icon (const char *icon_name, MailDisplay *md)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* We're maintaining a hashtable of mimetypes -> functions;
|
||||
* Those functions have the following signature...
|
||||
*/
|
||||
typedef gboolean (*mime_handler_fn) (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
|
||||
static GHashTable *mime_function_table, *mime_fallback_table;
|
||||
static GHashTable *mime_handler_table, *mime_function_table;
|
||||
|
||||
static void
|
||||
setup_function_table (void)
|
||||
setup_mime_tables (void)
|
||||
{
|
||||
mime_handler_table = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
mime_function_table = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
mime_fallback_table = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
g_hash_table_insert (mime_function_table, "text/plain",
|
||||
handle_text_plain);
|
||||
@ -251,11 +234,34 @@ setup_function_table (void)
|
||||
g_hash_table_insert (mime_function_table, "text/html",
|
||||
handle_text_html);
|
||||
|
||||
g_hash_table_insert (mime_function_table, "image/*",
|
||||
g_hash_table_insert (mime_function_table, "image/gif",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/jpeg",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/png",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-png",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/tiff",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-bmp",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/bmp",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-cmu-raster",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-ico",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-portable-anymap",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-portable-bitmap",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-portable-graymap",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-portable-pixmap",
|
||||
handle_image);
|
||||
g_hash_table_insert (mime_function_table, "image/x-xpixmap",
|
||||
handle_image);
|
||||
|
||||
g_hash_table_insert (mime_function_table, "audio/*",
|
||||
handle_audio);
|
||||
|
||||
g_hash_table_insert (mime_function_table, "message/rfc822",
|
||||
handle_message_rfc822);
|
||||
@ -279,97 +285,221 @@ setup_function_table (void)
|
||||
* as text/plain (as long as you recognize the character set),
|
||||
* and unrecognized multipart subtypes as multipart/mixed.
|
||||
*/
|
||||
g_hash_table_insert (mime_fallback_table, "text/*",
|
||||
g_hash_table_insert (mime_function_table, "text/*",
|
||||
handle_text_plain);
|
||||
g_hash_table_insert (mime_function_table, "multipart/*",
|
||||
handle_multipart_mixed);
|
||||
}
|
||||
|
||||
static mime_handler_fn
|
||||
lookup_handler (const char *mime_type, gboolean *generic)
|
||||
static gboolean
|
||||
component_supports (OAF_ServerInfo *component, const char *mime_type)
|
||||
{
|
||||
mime_handler_fn handler_function;
|
||||
OAF_Property *prop;
|
||||
CORBA_sequence_CORBA_string stringv;
|
||||
int i;
|
||||
|
||||
prop = oaf_server_info_prop_find (component,
|
||||
"bonobo:supported_mime_types");
|
||||
if (!prop || prop->v._d != OAF_P_STRINGV)
|
||||
return FALSE;
|
||||
|
||||
stringv = prop->v._u.value_stringv;
|
||||
for (i = 0; i < stringv._length; i++) {
|
||||
if (!g_strcasecmp (mime_type, stringv._buffer[i]))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* mail_lookup_handler:
|
||||
* @mime_type: a MIME type
|
||||
*
|
||||
* Looks up the MIME type in its own tables and GNOME-VFS's and returns
|
||||
* a MailMimeHandler structure detailing the component, application,
|
||||
* and built-in handlers (if any) for that MIME type. (If the component
|
||||
* is non-%NULL, the built-in handler will always be handle_via_bonobo().)
|
||||
* The MailMimeHandler's @generic field is set if the match was for the
|
||||
* MIME supertype rather than the exact type.
|
||||
*
|
||||
* Return value: a MailMimeHandler (which should not be freed), or %NULL
|
||||
* if no handlers are available.
|
||||
**/
|
||||
MailMimeHandler *
|
||||
mail_lookup_handler (const char *mime_type)
|
||||
{
|
||||
MailMimeHandler *handler;
|
||||
char *mime_type_main;
|
||||
GnomeVFSMimeAction *action;
|
||||
|
||||
if (mime_function_table == NULL)
|
||||
setup_function_table ();
|
||||
if (mime_handler_table == NULL)
|
||||
setup_mime_tables ();
|
||||
|
||||
/* See if we've already found it. */
|
||||
handler = g_hash_table_lookup (mime_handler_table, mime_type);
|
||||
if (handler)
|
||||
return handler;
|
||||
|
||||
/* No. Create a new one and look up application and full type
|
||||
* handler. If we find a builtin, create the handler and
|
||||
* register it.
|
||||
*/
|
||||
handler = g_new0 (MailMimeHandler, 1);
|
||||
handler->application =
|
||||
gnome_vfs_mime_get_default_application (mime_type);
|
||||
handler->builtin =
|
||||
g_hash_table_lookup (mime_function_table, mime_type);
|
||||
|
||||
if (handler->builtin) {
|
||||
handler->generic = FALSE;
|
||||
goto reg;
|
||||
}
|
||||
|
||||
/* Try for a exact component match. */
|
||||
handler->component = gnome_vfs_mime_get_default_component (mime_type);
|
||||
if (handler->component &&
|
||||
component_supports (handler->component, mime_type)) {
|
||||
handler->generic = FALSE;
|
||||
handler->builtin = handle_via_bonobo;
|
||||
goto reg;
|
||||
}
|
||||
|
||||
/* Try for a generic builtin match. */
|
||||
mime_type_main = g_strdup_printf ("%.*s/*",
|
||||
(int)strcspn (mime_type, "/"),
|
||||
mime_type);
|
||||
|
||||
/* OK. There are 6 possibilities, which we try in this order:
|
||||
* 1) full match in the main table
|
||||
* 2) partial match in the main table
|
||||
* 3) full match in gnome_vfs_mime_*
|
||||
* 4) full match in the fallback table
|
||||
* 5) partial match in the fallback table
|
||||
* 6) partial match in gnome_vfs_mime_*
|
||||
*
|
||||
* Of these, 1-4 are considered exact matches, and 5 and 6 are
|
||||
* considered generic.
|
||||
*/
|
||||
|
||||
/* Check for full match in mime_function_table. */
|
||||
handler_function = g_hash_table_lookup (mime_function_table,
|
||||
mime_type);
|
||||
if (!handler_function) {
|
||||
handler_function = g_hash_table_lookup (mime_function_table,
|
||||
mime_type_main);
|
||||
if (handler_function) {
|
||||
/* Optimize this for the next time through. */
|
||||
g_hash_table_insert (mime_function_table,
|
||||
g_strdup (mime_type),
|
||||
handler_function);
|
||||
}
|
||||
}
|
||||
|
||||
if (handler_function) {
|
||||
g_free (mime_type_main);
|
||||
*generic = FALSE;
|
||||
return handler_function;
|
||||
}
|
||||
|
||||
action = gnome_vfs_mime_get_default_action_without_fallback (mime_type);
|
||||
if (action) {
|
||||
if (action->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT)
|
||||
handler_function = handle_via_bonobo;
|
||||
else
|
||||
handler_function = handle_via_external;
|
||||
|
||||
/* Optimize this for the next time through. */
|
||||
g_hash_table_insert (mime_function_table,
|
||||
g_strdup (mime_type), handler_function);
|
||||
g_free (mime_type_main);
|
||||
gnome_vfs_mime_action_free (action);
|
||||
*generic = FALSE;
|
||||
return handler_function;
|
||||
}
|
||||
|
||||
handler_function = g_hash_table_lookup (mime_fallback_table,
|
||||
mime_type);
|
||||
if (handler_function)
|
||||
*generic = FALSE;
|
||||
else {
|
||||
handler_function = g_hash_table_lookup (mime_fallback_table,
|
||||
mime_type_main);
|
||||
if (!handler_function) {
|
||||
action = gnome_vfs_mime_get_default_action (mime_type_main);
|
||||
if (action) {
|
||||
if (action->action_type ==
|
||||
GNOME_VFS_MIME_ACTION_TYPE_COMPONENT)
|
||||
handler_function = handle_via_bonobo;
|
||||
else
|
||||
handler_function = handle_via_external;
|
||||
gnome_vfs_mime_action_free (action);
|
||||
}
|
||||
}
|
||||
*generic = TRUE;
|
||||
}
|
||||
|
||||
handler->builtin = g_hash_table_lookup (mime_function_table,
|
||||
mime_type_main);
|
||||
g_free (mime_type_main);
|
||||
return handler_function;
|
||||
|
||||
if (handler->builtin) {
|
||||
handler->generic = TRUE;
|
||||
if (handler->component) {
|
||||
CORBA_free (handler->component);
|
||||
handler->component = NULL;
|
||||
}
|
||||
goto reg;
|
||||
}
|
||||
|
||||
/* Try for a generic component match. */
|
||||
if (handler->component) {
|
||||
handler->generic = TRUE;
|
||||
handler->builtin = handle_via_bonobo;
|
||||
goto reg;
|
||||
}
|
||||
|
||||
/* If we at least got an application, use that. */
|
||||
if (handler->application) {
|
||||
handler->generic = TRUE;
|
||||
goto reg;
|
||||
}
|
||||
|
||||
/* Nada. */
|
||||
g_free (handler);
|
||||
return NULL;
|
||||
|
||||
reg:
|
||||
g_hash_table_insert (mime_handler_table, g_strdup (mime_type),
|
||||
handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
/* An "anonymous" MIME part is one that we shouldn't call attention
|
||||
* to the existence of, but simply display.
|
||||
*/
|
||||
static gboolean
|
||||
is_anonymous (CamelMimePart *part, const char *mime_type)
|
||||
{
|
||||
if (!g_strncasecmp (mime_type, "multipart/", 10) ||
|
||||
!g_strncasecmp (mime_type, "message/", 8))
|
||||
return TRUE;
|
||||
|
||||
if (!g_strncasecmp (mime_type, "text/", 5) &&
|
||||
!camel_mime_part_get_filename (part))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* mail_part_is_inline:
|
||||
* @part: a CamelMimePart
|
||||
*
|
||||
* Return value: whether or not the part should/will be displayed inline.
|
||||
**/
|
||||
gboolean
|
||||
mail_part_is_inline (CamelMimePart *part)
|
||||
{
|
||||
const char *disposition;
|
||||
GMimeContentField *content_type;
|
||||
const char *mime_type;
|
||||
|
||||
/* If it has an explicit disposition, return that. */
|
||||
disposition = camel_mime_part_get_disposition (part);
|
||||
if (disposition)
|
||||
return g_strcasecmp (disposition, "inline") == 0;
|
||||
|
||||
/* Certain types should default to inline. FIXME: this should
|
||||
* be customizable.
|
||||
*/
|
||||
content_type = camel_mime_part_get_content_type (part);
|
||||
mime_type = gmime_content_field_get_mime_type (content_type);
|
||||
if (!g_strncasecmp (mime_type, "message/", 8))
|
||||
return TRUE;
|
||||
|
||||
/* Otherwise, display it inline if it's "anonymous", and
|
||||
* as an attachment otherwise.
|
||||
*/
|
||||
return is_anonymous (part, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
attachment_header (CamelMimePart *part, const char *mime_type,
|
||||
gboolean is_inline, MailDisplay *md)
|
||||
{
|
||||
const char *info;
|
||||
char *htmlinfo;
|
||||
|
||||
/* No header for anonymous inline parts. */
|
||||
if (is_inline && is_anonymous (part, mime_type))
|
||||
return;
|
||||
|
||||
/* Start the table, create the pop-up object. */
|
||||
mail_html_write (md->html, md->stream, "<table><tr><td>"
|
||||
"<object classid=\"popup:%s\" type=\"%s\">"
|
||||
"</object></td><td><font size=-1>",
|
||||
get_cid (part, md), mime_type);
|
||||
|
||||
/* Write the MIME type */
|
||||
info = gnome_vfs_mime_get_value (mime_type, "description");
|
||||
htmlinfo = e_text_to_html (info ? info : mime_type, 0);
|
||||
mail_html_write (md->html, md->stream, "%s attachment", htmlinfo);
|
||||
g_free (htmlinfo);
|
||||
|
||||
/* Write the name, if we have it. */
|
||||
info = camel_mime_part_get_filename (part);
|
||||
if (info) {
|
||||
htmlinfo = e_text_to_html (info, 0);
|
||||
mail_html_write (md->html, md->stream, " (%s)", htmlinfo);
|
||||
g_free (htmlinfo);
|
||||
}
|
||||
|
||||
/* Write a description, if we have one. */
|
||||
info = camel_mime_part_get_description (part);
|
||||
if (info) {
|
||||
htmlinfo = e_text_to_html (info, E_TEXT_TO_HTML_CONVERT_URLS);
|
||||
mail_html_write (md->html, md->stream, ", \"%s\"", htmlinfo);
|
||||
g_free (htmlinfo);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Describe the click action, if any. */
|
||||
if (action) {
|
||||
mail_html_write (md->html, md->stream,
|
||||
"<br>Click on the icon to %s.", action);
|
||||
}
|
||||
#endif
|
||||
|
||||
mail_html_write (md->html, md->stream, "</font></td></tr></table>");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -377,18 +507,31 @@ call_handler_function (CamelMimePart *part, MailDisplay *md)
|
||||
{
|
||||
CamelDataWrapper *wrapper;
|
||||
char *mime_type;
|
||||
mime_handler_fn handler_function = NULL;
|
||||
gboolean generic, output;
|
||||
MailMimeHandler *handler;
|
||||
gboolean output, is_inline;
|
||||
|
||||
wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
|
||||
mime_type = camel_data_wrapper_get_mime_type (wrapper);
|
||||
g_strdown (mime_type);
|
||||
|
||||
handler_function = lookup_handler (mime_type, &generic);
|
||||
if (handler_function)
|
||||
output = (*handler_function) (part, mime_type, md);
|
||||
handler = mail_lookup_handler (mime_type);
|
||||
if (!handler) {
|
||||
char *id_type;
|
||||
|
||||
id_type = mail_identify_mime_part (part);
|
||||
if (id_type) {
|
||||
g_free (mime_type);
|
||||
mime_type = id_type;
|
||||
handler = mail_lookup_handler (id_type);
|
||||
}
|
||||
}
|
||||
|
||||
is_inline = mail_part_is_inline (part);
|
||||
attachment_header (part, mime_type, is_inline, md);
|
||||
if (handler && handler->builtin && is_inline)
|
||||
output = (*handler->builtin) (part, mime_type, md);
|
||||
else
|
||||
output = handle_unknown_type (part, mime_type, md);
|
||||
output = TRUE;
|
||||
|
||||
g_free (mime_type);
|
||||
return output;
|
||||
@ -528,7 +671,7 @@ handle_text_plain (CamelMimePart *part, const char *mime_type,
|
||||
text = get_data_wrapper_text (wrapper);
|
||||
if (!text)
|
||||
return FALSE;
|
||||
|
||||
|
||||
/* Check for RFC 2646 flowed text. */
|
||||
type = camel_mime_part_get_content_type (part);
|
||||
format = gmime_content_field_get_parameter (type, "format");
|
||||
@ -655,6 +798,7 @@ fake_mime_part_from_data (const char *data, int len, const char *type)
|
||||
part = camel_mime_part_new ();
|
||||
camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
|
||||
camel_object_unref (CAMEL_OBJECT (wrapper));
|
||||
camel_mime_part_set_disposition (part, "inline");
|
||||
return part;
|
||||
}
|
||||
|
||||
@ -1177,7 +1321,7 @@ find_preferred_alternative (CamelMultipart *multipart, gboolean want_plain)
|
||||
{
|
||||
int i, nparts;
|
||||
CamelMimePart *preferred_part = NULL;
|
||||
gboolean generic;
|
||||
MailMimeHandler *handler;
|
||||
|
||||
nparts = camel_multipart_get_number (multipart);
|
||||
for (i = 0; i < nparts; i++) {
|
||||
@ -1188,8 +1332,8 @@ find_preferred_alternative (CamelMultipart *multipart, gboolean want_plain)
|
||||
g_strdown (mime_type);
|
||||
if (want_plain && !strcmp (mime_type, "text/plain"))
|
||||
return part;
|
||||
if (lookup_handler (mime_type, &generic) &&
|
||||
(!preferred_part || !generic))
|
||||
handler = mail_lookup_handler (mime_type);
|
||||
if (handler && (!preferred_part || !handler->generic))
|
||||
preferred_part = part;
|
||||
g_free (mime_type);
|
||||
}
|
||||
@ -1213,7 +1357,7 @@ handle_multipart_alternative (CamelMimePart *part, const char *mime_type,
|
||||
if (mime_part)
|
||||
return call_handler_function (mime_part, md);
|
||||
else
|
||||
return handle_unknown_type (part, mime_type, md);
|
||||
return handle_multipart_mixed (part, mime_type, md);
|
||||
}
|
||||
|
||||
/* RFC 1740 */
|
||||
@ -1236,82 +1380,6 @@ handle_multipart_appledouble (CamelMimePart *part, const char *mime_type,
|
||||
return call_handler_function (part, md);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_mystery (CamelMimePart *part, MailDisplay *md,
|
||||
const char *url, const char *icon_name, const char *id,
|
||||
const char *action)
|
||||
{
|
||||
const char *info;
|
||||
char *htmlinfo;
|
||||
|
||||
mail_html_write (md->html, md->stream, "<table><tr><td>");
|
||||
|
||||
/* Draw the icon, surrounded by an <a href> if we have a URL,
|
||||
* or a plain inactive border if not.
|
||||
*/
|
||||
if (url) {
|
||||
mail_html_write (md->html, md->stream,
|
||||
"<a href=\"%s\">", url);
|
||||
} else {
|
||||
mail_html_write (md->html, md->stream,
|
||||
"<table border=2><tr><td>");
|
||||
}
|
||||
mail_html_write (md->html, md->stream, "<img src=\"%s\">",
|
||||
get_url_for_icon (icon_name, md));
|
||||
|
||||
if (url)
|
||||
mail_html_write (md->html, md->stream, "</a>");
|
||||
else
|
||||
mail_html_write (md->html, md->stream, "</td></tr></table>");
|
||||
mail_html_write (md->html, md->stream, "</td><td>%s<br>", id);
|
||||
|
||||
/* Write a description, if we have one. */
|
||||
info = camel_mime_part_get_description (part);
|
||||
if (info) {
|
||||
htmlinfo = e_text_to_html (info, E_TEXT_TO_HTML_CONVERT_URLS);
|
||||
mail_html_write (md->html, md->stream, "Description: %s<br>",
|
||||
htmlinfo);
|
||||
g_free (htmlinfo);
|
||||
}
|
||||
|
||||
/* Write the name, if we have it. */
|
||||
info = camel_mime_part_get_filename (part);
|
||||
if (info) {
|
||||
htmlinfo = e_text_to_html (info, 0);
|
||||
mail_html_write (md->html, md->stream, "Name: %s<br>",
|
||||
htmlinfo);
|
||||
g_free (htmlinfo);
|
||||
}
|
||||
|
||||
/* Describe the click action, if any. */
|
||||
if (action) {
|
||||
mail_html_write (md->html, md->stream,
|
||||
"<br>Click on the icon to %s.", action);
|
||||
}
|
||||
|
||||
mail_html_write (md->html, md->stream, "</td></tr></table>");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_audio (CamelMimePart *part, const char *mime_type, MailDisplay *md)
|
||||
{
|
||||
char *id;
|
||||
const char *desc;
|
||||
|
||||
desc = gnome_vfs_mime_get_value (mime_type, "description");
|
||||
if (desc)
|
||||
id = g_strdup_printf ("%s data", desc);
|
||||
else {
|
||||
id = g_strdup_printf ("Audio data in \"%s\" format.",
|
||||
mime_type);
|
||||
}
|
||||
handle_mystery (part, md, get_cid (part, md), "gnome-audio2.png",
|
||||
id, "play it");
|
||||
g_free (id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_message_rfc822 (CamelMimePart *part, const char *mime_type,
|
||||
MailDisplay *md)
|
||||
@ -1429,103 +1497,23 @@ handle_message_external_body (CamelMimePart *part, const char *mime_type,
|
||||
desc = g_strdup ("Malformed external-body part.");
|
||||
}
|
||||
|
||||
#if 0 /* FIXME */
|
||||
handle_mystery (part, md, url, "gnome-globe.png", desc,
|
||||
url ? "open it in a browser" : NULL);
|
||||
#endif
|
||||
|
||||
g_free (desc);
|
||||
g_free (url);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_undisplayable (CamelMimePart *part, const char *mime_type,
|
||||
MailDisplay *md)
|
||||
{
|
||||
const char *desc;
|
||||
char *id;
|
||||
|
||||
desc = gnome_vfs_mime_get_value (mime_type, "description");
|
||||
if (desc)
|
||||
id = g_strdup (desc);
|
||||
else
|
||||
id = g_strdup_printf ("Data of type \"%s\".", mime_type);
|
||||
handle_mystery (part, md, get_cid (part, md), "gnome-question.png",
|
||||
id, "save it to disk");
|
||||
g_free (id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_unknown_type (CamelMimePart *part, const char *mime_type,
|
||||
MailDisplay *md)
|
||||
{
|
||||
char *type;
|
||||
|
||||
/* Don't give up quite yet. */
|
||||
type = mail_identify_mime_part (part);
|
||||
if (type) {
|
||||
mime_handler_fn handler_function;
|
||||
gboolean generic, output;
|
||||
|
||||
handler_function = lookup_handler (type, &generic);
|
||||
if (handler_function &&
|
||||
handler_function != handle_unknown_type) {
|
||||
output = (*handler_function) (part, type, md);
|
||||
g_free (type);
|
||||
return output;
|
||||
}
|
||||
} else
|
||||
type = g_strdup (mime_type);
|
||||
|
||||
/* OK. Give up. */
|
||||
handle_undisplayable (part, type, md);
|
||||
g_free (type);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_via_bonobo (CamelMimePart *part, const char *mime_type,
|
||||
MailDisplay *md)
|
||||
{
|
||||
mail_html_write (md->html, md->stream,
|
||||
"<object classid=\"%s\" type=\"%s\">",
|
||||
"<object classid=\"%s\" type=\"%s\"></object>",
|
||||
get_cid (part, md), mime_type);
|
||||
|
||||
/* Call handle_undisplayable to output its HTML inside the
|
||||
* <object> ... </object>. It will only be displayed if the
|
||||
* object loading fails.
|
||||
*/
|
||||
handle_undisplayable (part, mime_type, md);
|
||||
|
||||
mail_html_write (md->html, md->stream, "</object>");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_via_external (CamelMimePart *part, const char *mime_type,
|
||||
MailDisplay *md)
|
||||
{
|
||||
GnomeVFSMimeApplication *app;
|
||||
const char *desc, *icon;
|
||||
char *action, *url;
|
||||
|
||||
app = gnome_vfs_mime_get_default_application (mime_type);
|
||||
g_return_val_if_fail (app != NULL, FALSE);
|
||||
|
||||
desc = gnome_vfs_mime_get_value (mime_type, "description");
|
||||
icon = gnome_vfs_mime_get_value (mime_type, "icon-filename");
|
||||
if (!icon)
|
||||
icon = "gnome-unknown.png";
|
||||
action = g_strdup_printf ("open the file in %s", app->name);
|
||||
url = g_strdup_printf ("x-evolution-external:%s", app->command);
|
||||
handle_mystery (part, md, url, icon, desc, action);
|
||||
add_url (url, part, md);
|
||||
|
||||
g_free (action);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1536,7 +1524,7 @@ mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, gboolean *is
|
||||
CamelMimePart *subpart;
|
||||
int i, nparts;
|
||||
char *subtext, *old;
|
||||
const char *boundary, *disp;
|
||||
const char *boundary;
|
||||
char *text = NULL;
|
||||
GMimeContentField *mime_type;
|
||||
|
||||
@ -1587,8 +1575,7 @@ mail_get_message_body (CamelDataWrapper *data, gboolean want_plain, gboolean *is
|
||||
for (i = 0; i < nparts; i++) {
|
||||
subpart = camel_multipart_get_part (mp, i);
|
||||
|
||||
disp = camel_mime_part_get_disposition (subpart);
|
||||
if (disp && g_strcasecmp (disp, "inline") != 0)
|
||||
if (!mail_part_is_inline (subpart))
|
||||
continue;
|
||||
|
||||
data = camel_medium_get_content_object (
|
||||
|
||||
14
mail/mail.h
14
mail/mail.h
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
|
||||
#include "camel/camel.h"
|
||||
#include "composer/e-msg-composer.h"
|
||||
#include "mail-config.h"
|
||||
@ -43,6 +44,19 @@ char *mail_crypto_openpgp_clearsign (const char *plaintext,
|
||||
void mail_format_mime_message (CamelMimeMessage *mime_message,
|
||||
MailDisplay *md);
|
||||
|
||||
typedef gboolean (*MailMimeHandlerFn) (CamelMimePart *part,
|
||||
const char *mime_type,
|
||||
MailDisplay *md);
|
||||
typedef struct {
|
||||
gboolean generic;
|
||||
OAF_ServerInfo *component;
|
||||
GnomeVFSMimeApplication *application;
|
||||
MailMimeHandlerFn builtin;
|
||||
} MailMimeHandler;
|
||||
MailMimeHandler *mail_lookup_handler (const char *mime_type);
|
||||
|
||||
gboolean mail_part_is_inline (CamelMimePart *part);
|
||||
|
||||
EMsgComposer *mail_generate_reply (CamelMimeMessage *mime_message,
|
||||
gboolean to_all);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user