aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog22
-rw-r--r--mail/mail-display.c64
-rw-r--r--mail/mail-display.h1
-rw-r--r--mail/mail-format.c117
-rw-r--r--mail/mail-identify.c30
-rw-r--r--mail/mail.h3
6 files changed, 167 insertions, 70 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 81d1a1c542..621935654a 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,25 @@
+2001-01-25 Dan Winship <danw@ximian.com>
+
+ * mail-format.c (mail_content_loaded): Check if a message part's
+ content is available, and if it's not, queue a thread that will
+ load it and then queue an idle-handler redisplay of the message.
+ (call_handler_function): Call mail_content_loaded() on the part
+ and don't try to display it if it's currently offline.
+ (get_data_wrapper_text): Simplify a bit
+
+ * mail-display.c (mail_display_queue_redisplay): rename and make
+ non-static.
+ (mail_display_redisplay): Use a "new and improved" way of
+ preserving the GtkHTML scroll location. ("new and improved" is
+ code for "gross and hackish", but there should be a real interface
+ for this eventually.)
+ (on_url_requested): Use mail_content_loaded() and don't write out
+ offline cid: URLs
+
+ * mail-identify.c (mail_identify_mime_part): Use
+ mail_content_loaded and don't try to identify the data if it's
+ offline.
+
2001-01-25 Christopher James Lahey <clahey@helixcode.com>
* message-list.c: Made the message list pay attention to the
diff --git a/mail/mail-display.c b/mail/mail-display.c
index c585ec0eac..31ec089f46 100644
--- a/mail/mail-display.c
+++ b/mail/mail-display.c
@@ -32,13 +32,12 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixbuf-loader.h>
#include <gtkhtml/gtkhtml-embedded.h>
+#include <gtkhtml/htmlengine.h> /* XXX */
#define PARENT_TYPE (gtk_vbox_get_type ())
static GtkObjectClass *mail_display_parent_class;
-static void redisplay (MailDisplay *md, gboolean unscroll);
-
struct _PixbufLoader {
MailDisplay *md;
CamelDataWrapper *wrapper; /* The data */
@@ -186,12 +185,12 @@ idle_redisplay (gpointer data)
MailDisplay *md = data;
md->idle_id = 0;
- redisplay (md, FALSE);
+ mail_display_redisplay (md, FALSE);
return FALSE;
}
-static void
-queue_redisplay (MailDisplay *md)
+void
+mail_display_queue_redisplay (MailDisplay *md)
{
if (!md->idle_id) {
md->idle_id = g_idle_add_full (G_PRIORITY_LOW, idle_redisplay,
@@ -212,7 +211,7 @@ on_link_clicked (GtkHTML *html, const char *url, gpointer user_data)
else if (!strcmp (url, "x-evolution-decode-pgp:")) {
g_datalist_set_data (md->data, "show_pgp",
GINT_TO_POINTER (1));
- queue_redisplay (md);
+ mail_display_queue_redisplay (md);
} else
gnome_url_show (url);
}
@@ -301,7 +300,7 @@ inline_cb (GtkWidget *widget, gpointer user_data)
else
camel_mime_part_set_disposition (part, "inline");
- queue_redisplay (md);
+ mail_display_queue_redisplay (md);
}
static gboolean
@@ -767,6 +766,8 @@ on_url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle,
g_return_if_fail (CAMEL_IS_MEDIUM (medium));
data = camel_medium_get_content_object (medium);
+ if (!mail_content_loaded (data, md))
+ return;
ba = g_byte_array_new ();
stream_mem = camel_stream_mem_new_with_byte_array (ba);
@@ -844,17 +845,24 @@ clear_data (CamelObject *object, gpointer event_data, gpointer user_data)
g_datalist_clear (&data);
}
-static void
-redisplay (MailDisplay *md, gboolean unscroll)
+/**
+ * mail_display_redisplay:
+ * @mail_display: the mail display object
+ * @unscroll: specifies whether or not to lose current scroll
+ *
+ * Force a redraw of the message display.
+ **/
+void
+mail_display_redisplay (MailDisplay *md, gboolean unscroll)
{
- GtkAdjustment *adj;
- gfloat oldv = 0;
+ printf("redisplaying\n");
+ md->stream = gtk_html_begin (GTK_HTML (md->html));
if (!unscroll) {
- adj = e_scroll_frame_get_vadjustment (md->scroll);
- oldv = adj->value;
+ /* This is a hack until there's a clean way to do this. */
+ GTK_HTML (md->html)->engine->newPage = FALSE;
}
- md->stream = gtk_html_begin (GTK_HTML (md->html));
+
mail_html_write (md->html, md->stream, "%s%s", HTML_HEADER, "<BODY>\n");
if (md->current_message) {
@@ -868,32 +876,6 @@ redisplay (MailDisplay *md, gboolean unscroll)
mail_html_write (md->html, md->stream, "</BODY></HTML>\n");
gtk_html_end (md->html, md->stream, GTK_HTML_STREAM_OK);
md->stream = NULL;
-
- 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);
- }
- }
-}
-
-
-/**
- * mail_display_redisplay:
- * @mail_display: the mail display object
- * @unscroll: specifies whether or not to lose current scroll
- *
- * Force a redraw of the message display.
- **/
-void
-mail_display_redisplay (MailDisplay *mail_display, gboolean unscroll)
-{
- redisplay (mail_display, unscroll);
}
/**
@@ -920,7 +902,7 @@ mail_display_set_message (MailDisplay *md, CamelMedium *medium)
md->current_message = (CamelMimeMessage*)medium;
g_datalist_init (md->data);
- redisplay (md, TRUE);
+ mail_display_redisplay (md, TRUE);
if (medium) {
camel_object_hook_event (CAMEL_OBJECT (medium), "finalize",
clear_data, *(md->data));
diff --git a/mail/mail-display.h b/mail/mail-display.h
index c7c45c9bdf..4334d7dfad 100644
--- a/mail/mail-display.h
+++ b/mail/mail-display.h
@@ -40,6 +40,7 @@ typedef struct {
GtkType mail_display_get_type (void);
GtkWidget * mail_display_new (void);
+void mail_display_queue_redisplay (MailDisplay *mail_display);
void mail_display_redisplay (MailDisplay *mail_display, gboolean unscroll);
void mail_display_set_message (MailDisplay *mail_display,
diff --git a/mail/mail-format.c b/mail/mail-format.c
index 610bf27b68..faea36f633 100644
--- a/mail/mail-format.c
+++ b/mail/mail-format.c
@@ -28,6 +28,7 @@
#include "mail-tools.h"
#include "mail-display.h"
#include "mail-crypto.h"
+#include "mail-mt.h"
#include "shell/e-setup.h"
#include "e-util/e-html-utils.h"
#include <gal/widgets/e-unicode.h>
@@ -547,7 +548,7 @@ call_handler_function (CamelMimePart *part, MailDisplay *md)
if (!handler) {
char *id_type;
- id_type = mail_identify_mime_part (part);
+ id_type = mail_identify_mime_part (part, md);
if (id_type) {
g_free (mime_type);
mime_type = id_type;
@@ -557,7 +558,8 @@ call_handler_function (CamelMimePart *part, MailDisplay *md)
is_inline = mail_part_is_inline (part);
attachment_header (part, mime_type, is_inline, md);
- if (handler && handler->builtin && is_inline)
+ if (handler && handler->builtin && is_inline &&
+ mail_content_loaded (wrapper, md))
output = (*handler->builtin) (part, mime_type, md);
else
output = TRUE;
@@ -637,35 +639,118 @@ write_headers (CamelMimeMessage *message, MailDisplay *md)
"</table></td></tr></table></td></tr></table></font>");
}
+struct _load_content_msg {
+ struct _mail_msg msg;
-/* Return the contents of a text-based data wrapper, or NULL if it
- * contains only whitespace.
+ MailDisplay *display;
+ CamelMimeMessage *message;
+ CamelDataWrapper *wrapper;
+};
+
+static char *
+load_content_desc (struct _mail_msg *mm, int done)
+{
+ return g_strdup (_("Loading message content"));
+}
+
+static void
+load_content_load (struct _mail_msg *mm)
+{
+ struct _load_content_msg *m = (struct _load_content_msg *)mm;
+ CamelStream *memstream;
+
+ memstream = camel_stream_mem_new ();
+ camel_data_wrapper_write_to_stream (m->wrapper, memstream);
+ camel_object_unref (CAMEL_OBJECT (memstream));
+}
+
+static void
+load_content_loaded (struct _mail_msg *mm)
+{
+ struct _load_content_msg *m = (struct _load_content_msg *)mm;
+
+ if (m->display->current_message == m->message)
+ mail_display_queue_redisplay (m->display);
+}
+
+static void
+load_content_free (struct _mail_msg *mm)
+{
+ struct _load_content_msg *m = (struct _load_content_msg *)mm;
+
+ gtk_object_unref (GTK_OBJECT (m->display));
+ camel_object_unref (CAMEL_OBJECT (m->wrapper));
+ camel_object_unref (CAMEL_OBJECT (m->message));
+}
+
+static struct _mail_msg_op load_content_op = {
+ load_content_desc,
+ load_content_load,
+ load_content_loaded,
+ load_content_free,
+};
+
+gboolean
+mail_content_loaded (CamelDataWrapper *wrapper, MailDisplay *md)
+{
+ struct _load_content_msg *m;
+ GHashTable *loading;
+
+ if (!camel_data_wrapper_is_offline (wrapper))
+ return TRUE;
+
+ loading = g_datalist_get_data (md->data, "loading");
+ if (loading) {
+ if (g_hash_table_lookup (loading, wrapper))
+ return FALSE;
+ } else {
+ loading = g_hash_table_new (NULL, NULL);
+ g_datalist_set_data_full (md->data, "loading", loading,
+ (GDestroyNotify)g_hash_table_destroy);
+ }
+ g_hash_table_insert (loading, wrapper, GINT_TO_POINTER (1));
+
+ m = mail_msg_new (&load_content_op, NULL, sizeof (*m));
+ m->display = md;
+ gtk_object_ref (GTK_OBJECT (m->display));
+ m->message = md->current_message;
+ camel_object_ref (CAMEL_OBJECT (m->message));
+ m->wrapper = wrapper;
+ camel_object_ref (CAMEL_OBJECT (m->wrapper));
+
+ e_thread_put (mail_thread_queued, (EMsg *)m);
+ return FALSE;
+}
+
+/* Return the contents of a data wrapper, or %NULL if it contains only
+ * whitespace.
*/
static char *
-get_data_wrapper_text (CamelDataWrapper *data)
+get_data_wrapper_text (CamelDataWrapper *wrapper)
{
CamelStream *memstream;
GByteArray *ba;
char *text, *end;
+ memstream = camel_stream_mem_new ();
ba = g_byte_array_new ();
- memstream = camel_stream_mem_new_with_byte_array (ba);
-
- camel_data_wrapper_write_to_stream (data, memstream);
+ camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (memstream), ba);
+ camel_data_wrapper_write_to_stream (wrapper, memstream);
+ camel_object_unref (CAMEL_OBJECT (memstream));
- for (text = ba->data, end = ba->data + ba->len; text < end; text++) {
+ for (text = ba->data, end = text + ba->len; text < end; text++) {
if (!isspace ((unsigned char)*text))
break;
}
- if (text < end) {
- text = g_malloc (ba->len + 1);
- memcpy (text, ba->data, ba->len);
- text[ba->len] = '\0';
- } else
- text = NULL;
+ if (text >= end) {
+ g_byte_array_free (ba, TRUE);
+ return NULL;
+ }
- camel_object_unref (CAMEL_OBJECT (memstream));
+ g_byte_array_append (ba, "", 1);
+ text = ba->data;
+ g_byte_array_free (ba, FALSE);
return text;
}
diff --git a/mail/mail-identify.c b/mail/mail-identify.c
index 3f86ea361c..61b2d1fe10 100644
--- a/mail/mail-identify.c
+++ b/mail/mail-identify.c
@@ -35,12 +35,13 @@
/**
* mail_identify_mime_part:
* @part: a CamelMimePart
+ * @md: the MailDisplay @part is being shown in
*
* Try to identify the MIME type of the data in @part (which presumably
* doesn't have a useful Content-Type).
**/
char *
-mail_identify_mime_part (CamelMimePart *part)
+mail_identify_mime_part (CamelMimePart *part, MailDisplay *md)
{
const char *filename, *type;
GnomeVFSMimeSniffBuffer *sniffer;
@@ -62,17 +63,22 @@ mail_identify_mime_part (CamelMimePart *part)
/* Try file magic. */
data = camel_medium_get_content_object (CAMEL_MEDIUM (part));
- ba = g_byte_array_new ();
- memstream = camel_stream_mem_new_with_byte_array (ba);
- camel_data_wrapper_write_to_stream (data, memstream);
- if (ba->len) {
- sniffer = gnome_vfs_mime_sniff_buffer_new_from_memory (
- ba->data, ba->len);
- type = gnome_vfs_get_mime_type_for_buffer (sniffer);
- gnome_vfs_mime_sniff_buffer_free (sniffer);
- } else
- type = NULL;
- camel_object_unref (CAMEL_OBJECT (memstream));
+ /* FIXME: In a perfect world, we would not load the content just
+ * to identify the MIME type.
+ */
+ if (mail_content_loaded (data, md)) {
+ ba = g_byte_array_new ();
+ memstream = camel_stream_mem_new_with_byte_array (ba);
+ camel_data_wrapper_write_to_stream (data, memstream);
+ if (ba->len) {
+ sniffer = gnome_vfs_mime_sniff_buffer_new_from_memory (
+ ba->data, ba->len);
+ type = gnome_vfs_get_mime_type_for_buffer (sniffer);
+ gnome_vfs_mime_sniff_buffer_free (sniffer);
+ } else
+ type = NULL;
+ camel_object_unref (CAMEL_OBJECT (memstream));
+ }
if (type)
return g_strdup (type);
diff --git a/mail/mail.h b/mail/mail.h
index c80cabfa52..4015fd613a 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -40,6 +40,7 @@ void mail_format_mime_message (CamelMimeMessage *mime_message,
MailDisplay *md);
void mail_format_raw_message (CamelMimeMessage *mime_message,
MailDisplay *md);
+gboolean mail_content_loaded (CamelDataWrapper *wrapper, MailDisplay *display);
typedef gboolean (*MailMimeHandlerFn) (CamelMimePart *part,
const char *mime_type,
@@ -61,7 +62,7 @@ char *mail_get_message_body (CamelDataWrapper *data, gboolean want_plain,
gboolean *is_html);
/* mail-identify */
-char *mail_identify_mime_part (CamelMimePart *part);
+char *mail_identify_mime_part (CamelMimePart *part, MailDisplay *md);
/* mail view */
GtkWidget *mail_view_create (CamelFolder *source, const char *uid, CamelMimeMessage *msg);