[evolution/webkit] Make displaying message source work



commit bb04806d155f73128d9f325d0c10536a78c745bf
Author: Dan VrÃtil <dvratil redhat com>
Date:   Fri Sep 23 18:24:41 2011 +0200

    Make displaying message source work
    
    To make this work, new structure EMFormatWriterInfo was added. This
    structure is passed to write_func and holds various writing-related
    flags (collapsable headers, all headers/normal/source...).
    
    The em_format_build_mail_uri now supports various data types as
    query items values.

 em-format/em-format-quote.c |   23 ++-
 em-format/em-format.c       |   58 ++++++--
 em-format/em-format.h       |   19 ++-
 mail/e-mail-browser.c       |   23 ++-
 mail/e-mail-browser.h       |    2 +-
 mail/e-mail-display.c       |  335 ++++++++++++++++++++++++++++++++-----------
 mail/e-mail-display.h       |   22 ++-
 mail/e-mail-reader-utils.c  |    2 +-
 mail/e-mail-reader.c        |   17 ++-
 mail/e-mail-request.c       |   42 ++++--
 mail/em-format-html.c       |  217 ++++++++++------------------
 mail/em-format-html.h       |   23 ---
 12 files changed, 479 insertions(+), 304 deletions(-)
---
diff --git a/em-format/em-format-quote.c b/em-format/em-format-quote.c
index 1aee811..bf1165e 100644
--- a/em-format/em-format-quote.c
+++ b/em-format/em-format-quote.c
@@ -48,13 +48,13 @@ static void emfq_builtin_init (EMFormatQuoteClass *efhc);
 
 static CamelMimePart * decode_inline_parts (CamelMimePart *part, GCancellable *cancellable);
 
-static void emfq_write_text_plain	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void emfq_write_text_enriched	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void emfq_write_text_html	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void emfq_write_message_rfc822	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void emfq_write_message_prefix	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
+static void emfq_write_text_plain	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void emfq_write_text_enriched	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void emfq_write_text_html	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void emfq_write_message_rfc822	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void emfq_write_message_prefix	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
 /* FIXME WEBKIT */
-static void emfq_write_source		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
+static void emfq_write_source		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
 
 static gpointer parent_class;
 
@@ -190,6 +190,7 @@ static void
 emfq_write_source (EMFormat *emf,
 		   EMFormatPURI *puri,
 		   CamelStream *stream,
+		   EMFormatWriterInfo *info,
                    GCancellable *cancellable)
 {
 	CamelStream *filtered_stream;
@@ -218,6 +219,7 @@ static void
 emfq_write_attachment (EMFormat *emf,
 		       EMFormatPURI *puri,
                        CamelStream *stream,
+                       EMFormatWriterInfo *info,
                        GCancellable *cancellable)
 {
 	EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf);
@@ -256,7 +258,7 @@ emfq_write_attachment (EMFormat *emf,
 		stream, "</font></td></tr></table>", cancellable, NULL);
 
 	if (handler && handler->write_func)
-		handler->write_func (emf, puri, stream, cancellable);
+		handler->write_func (emf, puri, stream, info, cancellable);
 }
 
 static void
@@ -595,6 +597,7 @@ static void
 emfq_write_message_prefix (EMFormat *emf,
 			   EMFormatPURI *puri,
 			   CamelStream *stream,
+			   EMFormatWriterInfo *info,
 			   GCancellable *cancellable)
 {
 	EMFormatQuote *emfq = (EMFormatQuote *) emf;
@@ -611,6 +614,7 @@ static void
 emfq_write_message_rfc822 (EMFormat *emf,
                      	   EMFormatPURI *puri,
                      	   CamelStream *stream,
+                     	   EMFormatWriterInfo *info,
                      	   GCancellable *cancellable)
 {
 	EMFormatQuote *emfq = (EMFormatQuote *) emf;
@@ -637,7 +641,7 @@ emfq_write_message_rfc822 (EMFormat *emf,
 	camel_stream_write (
 		stream, buffer->str, buffer->len, cancellable, NULL);
 
-	puri->write_func (emf, puri, stream, cancellable);
+	puri->write_func (emf, puri, stream, info, cancellable);
 
 	if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE)
 		camel_stream_write_string (
@@ -653,6 +657,7 @@ static void
 emfq_write_text_plain (EMFormat *emf,
 		       EMFormatPURI *puri,
 		       CamelStream *stream,
+		       EMFormatWriterInfo *info,
 		       GCancellable *cancellable)
 {
 	EMFormatQuote *emfq = EM_FORMAT_QUOTE (emf);
@@ -716,6 +721,7 @@ static void
 emfq_write_text_enriched (EMFormat *emf,
 			  EMFormatPURI *puri,
                     	  CamelStream *stream,
+                    	  EMFormatWriterInfo *info,
                     	  GCancellable *cancellable)
 {
 	CamelStream *filtered_stream;
@@ -758,6 +764,7 @@ static void
 emfq_write_text_html (EMFormat *emf,
 		      EMFormatPURI *puri,
 	              CamelStream *stream,
+	              EMFormatWriterInfo *info,
 	              GCancellable *cancellable)
 {
 	EMFormatQuotePrivate *priv;
diff --git a/em-format/em-format.c b/em-format/em-format.c
index 6e34bfe..093720e 100644
--- a/em-format/em-format.c
+++ b/em-format/em-format.c
@@ -79,8 +79,8 @@ static void emf_parse_post_headers		(EMFormat *emf, CamelMimePart *part, GString
 static void emf_parse_source			(EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 
 /* WRITERS */
-static void emf_write_text			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable) {};
-static void emf_write_source			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable) {}
+static void emf_write_text			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable) {};
+static void emf_write_source			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable) {};
 
 static void emf_error				(EMFormat *emf, const gchar *message) {};
 static void emf_source				(EMFormat *emf, CamelStream *stream, GCancellable *cancellable);
@@ -1054,7 +1054,7 @@ emf_parse_source (EMFormat *emf,
 	g_string_append (part_id, ".source");
 
 	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
-	puri->write_func = emf_write_source;
+	puri->write_func = info->handler->write_func;
 	puri->mime_type = g_strdup ("text/html");
 	g_string_truncate (part_id, len);
 
@@ -1067,6 +1067,7 @@ void
 em_format_empty_writer (EMFormat *emf,
 			EMFormatPURI *puri,
 			CamelStream *stream,
+			EMFormatWriterInfo *info,
 			GCancellable *cancellable)
 {
 	/* DO NOTHING */
@@ -1100,6 +1101,7 @@ emf_parse (EMFormat *emf,
 	   GCancellable *cancellable)
 {
 	GString *part_id;
+	EMFormatPURI *puri;
 	EMFormatParserInfo info = { 0 };
 
 	g_return_if_fail (EM_IS_FORMAT (emf));
@@ -1128,6 +1130,12 @@ emf_parse (EMFormat *emf,
 
 	part_id = g_string_new ("");
 
+	/* Create a special PURI with entire message */
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI),
+		(CamelMimePart *) message, ".message");
+	puri->mime_type = g_strdup ("text/html");
+	em_format_add_puri (emf, puri);
+
 	em_format_parse_part_as (emf, CAMEL_MIME_PART (message), part_id, &info,
 			"x-evolution/message", cancellable);
 
@@ -1192,7 +1200,7 @@ static EMFormatHandler type_handlers[] = {
 		{ (gchar *) "x-evolution/message", emf_parse_message, },
 		{ (gchar *) "x-evolution/message/headers", emf_parse_headers, },
 		{ (gchar *) "x-evolution/message/post-headers", emf_parse_post_headers, },
-		{ (gchar *) "x-evolution/message/source", emf_parse_source, },
+		{ (gchar *) "x-evolution/message/source", emf_parse_source, emf_write_source },
 };
 
 /* note: also copied in em-mailer-prefs.c */
@@ -2177,13 +2185,33 @@ em_format_build_mail_uri (CamelFolder *folder,
 	separator = '?';
 	while (name) {
 		gchar *tmp2;
-		gchar *val = va_arg (ap, char *);
-		if (val) {
-			tmp2 = g_strdup_printf ("%s%c%s=%s", tmp, separator, name, val);
-			g_free (tmp);
-			tmp = tmp2;
+		gint type = va_arg (ap, int);
+		switch (type) {
+			case G_TYPE_INT:
+			case G_TYPE_BOOLEAN: {
+				gint val = va_arg (ap, int);
+				tmp2 = g_strdup_printf ("%s%c%s=%d", tmp, separator, name, val);
+				break;
+			}
+			case G_TYPE_FLOAT:
+			case G_TYPE_DOUBLE: {
+				gdouble val = va_arg (ap, double);
+				tmp2 = g_strdup_printf ("%s%c%s=%f", tmp, separator, name, val);
+				break;
+			}
+			case G_TYPE_STRING: {
+				gchar *val = va_arg (ap, char *);
+				tmp2 = g_strdup_printf ("%s%c%s=%s", tmp, separator, name, val);
+				break;
+			}
+			default:
+				g_warning ("Invalid param type %s", g_type_name (type));
+				return NULL;
 		}
 
+		g_free (tmp);
+		tmp = tmp2;
+
 		if (separator == '?')
 			separator = '&';
 
@@ -2264,13 +2292,21 @@ em_format_puri_free (EMFormatPURI *puri)
 void
 em_format_puri_write (EMFormatPURI *puri,
 		      CamelStream *stream,
+		      EMFormatWriterInfo *info,
 		      GCancellable *cancellable)
 {
 	g_return_if_fail (puri);
 	g_return_if_fail (CAMEL_IS_STREAM (stream));
 
+	if (info->mode == EM_FORMAT_WRITE_MODE_SOURCE) {
+		const EMFormatHandler *handler;
+		handler = em_format_find_handler (puri->emf, "x-evolution/message/source");
+		handler->write_func (puri->emf, puri, stream, info, cancellable);
+		return;
+	}
+
 	if (puri->write_func) {
-		puri->write_func (puri->emf, puri, stream, cancellable);
+		puri->write_func (puri->emf, puri, stream, info, cancellable);
 	} else {
 		const EMFormatHandler *handler;
 		const gchar *mime_type;
@@ -2284,7 +2320,7 @@ em_format_puri_write (EMFormatPURI *puri,
 		handler = em_format_find_handler (puri->emf, mime_type);
 		if (handler && handler->write_func) {
 			handler->write_func (puri->emf,
-					puri, stream, cancellable);
+					puri, stream, info, cancellable);
 		}
 	}
 }
diff --git a/em-format/em-format.h b/em-format/em-format.h
index 60c7581..713a9b9 100644
--- a/em-format/em-format.h
+++ b/em-format/em-format.h
@@ -64,6 +64,7 @@ typedef struct _EMFormatPURI EMFormatPURI;
 typedef struct _EMFormatHeader EMFormatHeader;
 typedef struct _EMFormatHandler EMFormatHandler;
 typedef struct _EMFormatParserInfo EMFormatParserInfo;
+typedef struct _EMFormatWriterInfo EMFormatWriterInfo;
 
 typedef void		(*EMFormatParseFunc)	(EMFormat *emf,
 					 	 CamelMimePart *part,
@@ -73,20 +74,24 @@ typedef void		(*EMFormatParseFunc)	(EMFormat *emf,
 typedef void		(*EMFormatWriteFunc)	(EMFormat *emf,
 					 	 EMFormatPURI *puri,
 					 	 CamelStream *stream,
+					 	 EMFormatWriterInfo *info,
 					 	 GCancellable *cancellable);
 typedef GtkWidget*	(*EMFormatWidgetFunc)	(EMFormat *emf,
 					 	 EMFormatPURI *puri,
 					 	 GCancellable *cancellable);
 
 
-
-typedef struct _EMFormatHandler EMFormatHandler;
-
 typedef enum {
 	EM_FORMAT_HANDLER_INLINE = 1 << 0,
 	EM_FORMAT_HANDLER_INLINE_DISPOSITION = 1 << 1
 } EMFormatHandlerFlags;
 
+typedef enum {
+	EM_FORMAT_WRITE_MODE_NORMAL= 0,
+	EM_FORMAT_WRITE_MODE_ALL_HEADERS,
+	EM_FORMAT_WRITE_MODE_SOURCE
+} EMFormatWriteMode;
+
 struct _EMFormatHandler {
 	gchar *mime_type;
 	EMFormatParseFunc parse_func;
@@ -109,6 +114,12 @@ struct _EMFormatParserInfo {
 	CamelCipherValidity *validity;
 };
 
+struct _EMFormatWriterInfo {
+	EMFormatWriteMode mode;
+	gboolean headers_collapsable;
+	gboolean headers_collapsed;
+};
+
 struct _EMFormatHeader {
 	guint32 flags;		/* E_FORMAT_HEADER_ * */
 	gchar name[1];
@@ -284,6 +295,7 @@ void			em_format_empty_parser 		(EMFormat *emf,
 void			em_format_empty_writer 		(EMFormat *emf,
 							 EMFormatPURI *puri,
 							 CamelStream *stream,
+							 EMFormatWriterInfo *info,
 							 GCancellable *cancellable);
 
 
@@ -295,6 +307,7 @@ void			em_format_puri_free 		(EMFormatPURI *puri);
 
 void			em_format_puri_write 		(EMFormatPURI *puri,
 							 CamelStream *stream,
+							 EMFormatWriterInfo *info,
 							 GCancellable *cancellable);
 
 #endif /* EM_FORMAT_H */
diff --git a/mail/e-mail-browser.c b/mail/e-mail-browser.c
index d8c0f41..f6f2649 100644
--- a/mail/e-mail-browser.c
+++ b/mail/e-mail-browser.c
@@ -56,6 +56,8 @@ struct _EMailBrowserPrivate {
 	EFocusTracker *focus_tracker;
 	EMailDisplay *display;
 
+	EMFormatWriteMode mode;
+
 	GtkWidget *main_menu;
 	GtkWidget *main_toolbar;
 	GtkWidget *message_list;
@@ -74,7 +76,7 @@ enum {
 	PROP_GROUP_BY_THREADS,
 	PROP_SHOW_DELETED,
 	PROP_REPLY_STYLE,
-	PROP_UI_MANAGER
+	PROP_UI_MANAGER,
 };
 
 static gpointer parent_class;
@@ -573,7 +575,8 @@ mail_browser_constructed (GObject *object)
 
 	e_shell_watch_window (shell, GTK_WINDOW (object));
 
-	priv->display = e_mail_reader_get_mail_display (reader);
+	//priv->display = e_mail_reader_get_mail_display (reader);
+	e_mail_display_set_mode (priv->display, E_MAIL_BROWSER (object)->priv->mode);
 
 	/* The message list is a widget, but it is not shown in the browser.
 	 * Unfortunately, the widget is inseparable from its model, and the
@@ -686,8 +689,6 @@ mail_browser_constructed (GObject *object)
 	priv->alert_bar = g_object_ref (widget);
 	/* EAlertBar controls its own visibility. */
 
-	gtk_widget_show (GTK_WIDGET (priv->display));
-
 	widget = GTK_WIDGET (priv->display);
 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
 	gtk_widget_show (widget);
@@ -948,6 +949,7 @@ e_mail_browser_class_init (EMailBrowserClass *class)
 			"Show deleted messages",
 			FALSE,
 			G_PARAM_READWRITE));
+
 }
 
 static void
@@ -993,13 +995,20 @@ GtkWidget *
 e_mail_browser_new (EMailBackend *backend,
 		    CamelFolder *folder,
 		    const gchar *msg_uid,
-		    EMailDisplayMode mode)
+		    EMFormatWriteMode mode)
 {
+	GtkWidget *widget;
+
 	g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
 
-	return g_object_new (
+	widget= g_object_new (
 		E_TYPE_MAIL_BROWSER,
-		"backend", backend, NULL);
+		"backend", backend,
+		NULL);
+
+	E_MAIL_BROWSER (widget)->priv->mode = mode;
+
+	return widget;
 }
 
 void
diff --git a/mail/e-mail-browser.h b/mail/e-mail-browser.h
index 90ea53a..88f8174 100644
--- a/mail/e-mail-browser.h
+++ b/mail/e-mail-browser.h
@@ -64,7 +64,7 @@ GType		e_mail_browser_get_type		(void);
 GtkWidget *	e_mail_browser_new		(EMailBackend *backend,
 						 CamelFolder *folder,
 						 const gchar *message_uid,
-						 EMailDisplayMode mode);
+						 EMFormatWriteMode mode);
 void		e_mail_browser_close		(EMailBrowser *browser);
 gboolean	e_mail_browser_get_show_deleted	(EMailBrowser *browser);
 void		e_mail_browser_set_show_deleted (EMailBrowser *browser,
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index de2e23f..c8c1374 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -47,7 +47,9 @@ struct _EMailDisplayPrivate {
 	ESearchBar *searchbar;
 	EMFormatHTML *formatter;
 
-	EMailDisplayMode display_mode;
+	EMFormatWriteMode mode;
+	gboolean headers_collapsable;
+	gboolean headers_collapsed;
 
 	GList *webviews;
 };
@@ -55,7 +57,9 @@ struct _EMailDisplayPrivate {
 enum {
 	PROP_0,
 	PROP_FORMATTER,
-	PROP_DISPLAY_MODE
+	PROP_MODE,
+	PROP_HEADERS_COLLAPSABLE,
+	PROP_HEADERS_COLLAPSED
 };
 
 static gpointer parent_class;
@@ -175,11 +179,21 @@ mail_display_set_property (GObject *object,
 				E_MAIL_DISPLAY (object),
 				g_value_get_object (value));
 			return;
-		case PROP_DISPLAY_MODE:
+		case PROP_MODE:
 			e_mail_display_set_mode (
 				E_MAIL_DISPLAY (object),
 				g_value_get_int (value));
 			return;
+		case PROP_HEADERS_COLLAPSABLE:
+			e_mail_display_set_headers_collapsable (
+				E_MAIL_DISPLAY (object),
+				g_value_get_boolean (value));
+			return;
+		case PROP_HEADERS_COLLAPSED:
+			e_mail_display_set_headers_collapsed (
+				E_MAIL_DISPLAY (object),
+				g_value_get_boolean (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -197,11 +211,21 @@ mail_display_get_property (GObject *object,
 				value, e_mail_display_get_formatter (
 				E_MAIL_DISPLAY (object)));
 			return;
-		case PROP_DISPLAY_MODE:
+		case PROP_MODE:
 			g_value_set_int (
 				value, e_mail_display_get_mode (
 				E_MAIL_DISPLAY (object)));
 			return;
+		case PROP_HEADERS_COLLAPSABLE:
+			g_value_set_boolean (
+				value, e_mail_display_get_headers_collapsable (
+				E_MAIL_DISPLAY (object)));
+			return;
+		case PROP_HEADERS_COLLAPSED:
+			g_value_set_boolean (
+				value, e_mail_display_get_headers_collapsed (
+				E_MAIL_DISPLAY (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -341,7 +365,8 @@ mail_display_resource_requested (WebKitWebView *web_view,
         /* Redirect cid:part_id to mail://mail_id/cid:part_id */
         if (g_str_has_prefix (uri, "cid:")) {
 		gchar *new_uri = em_format_build_mail_uri (EM_FORMAT (formatter)->folder, 
-			EM_FORMAT (formatter)->message_uid, "part_id", uri, NULL);
+			EM_FORMAT (formatter)->message_uid,
+			"part_id", G_TYPE_STRING, uri, NULL);
 
                 webkit_network_request_set_uri (request, new_uri);
 
@@ -386,16 +411,9 @@ mail_display_headers_collapsed_state_changed (EWebView *web_view,
 					      gpointer user_data)
 {
 	EMailDisplay *display = user_data;
-	EMFormatHTML *formatter = display->priv->formatter;
 	JSGlobalContextRef ctx = e_web_view_get_global_context (web_view);
 
-	gboolean collapsed = JSValueToBoolean (ctx, args[0]);
-
-	if (collapsed) {
-		em_format_html_set_headers_state (formatter, EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED);
-	} else {
-		em_format_html_set_headers_state (formatter, EM_FORMAT_HTML_HEADERS_STATE_EXPANDED);
-	}
+	display->priv->headers_collapsed = JSValueToBoolean (ctx, args[0]);
 }
 
 static void
@@ -480,6 +498,105 @@ mail_display_insert_web_view (EMailDisplay *display,
 }
 
 static void
+mail_display_load_as_source (EMailDisplay *display,
+			     const gchar *msg_uid)
+{
+	EWebView *web_view;
+	EMFormat *emf = (EMFormat *) display->priv->formatter;
+	gchar *uri;
+
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	e_mail_display_clear (display);
+
+	web_view = mail_display_setup_webview (display);
+	mail_display_insert_web_view (display, web_view, TRUE);
+
+	uri = em_format_build_mail_uri (emf->folder, emf->message_uid,
+		"part_id", G_TYPE_STRING, ".message",
+		"mode", G_TYPE_INT, display->priv->mode,
+		NULL);
+	e_web_view_load_uri (web_view, uri);
+
+	gtk_widget_show_all (display->priv->vbox);
+}
+
+static void
+mail_display_load_normal (EMailDisplay *display,
+			  const gchar *msg_uid)
+{
+	EWebView *web_view;
+	EMFormatPURI *puri;
+	EMFormat *emf = (EMFormat *) display->priv->formatter;
+	gchar *uri;
+	GList *iter;
+	GtkBox *box;
+
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	/* Don't use gtk_widget_show_all() to display all widgets at once,
+	   it makes all parts of EMailAttachmentBar visible and that's not
+	   what we want.
+	   FIXME: Maybe using gtk_widget_set_no_show_all() in EAttachmentView
+	          could help...
+	*/
+
+	/* First remove all widgets left after previous message */
+	e_mail_display_clear (display);
+
+	box = GTK_BOX (display->priv->vbox);
+	gtk_widget_show (display->priv->vbox);
+
+	for (iter = emf->mail_part_list; iter; iter = iter->next) {
+		GtkWidget *widget = NULL;
+
+		puri = iter->data;
+		uri = em_format_build_mail_uri (emf->folder, emf->message_uid,
+			"part_id", G_TYPE_STRING, puri->uri,
+			"mode", G_TYPE_INT, display->priv->mode,
+			"headers_collapsable", G_TYPE_BOOLEAN, display->priv->headers_collapsable,
+			"headers_collapsed", G_TYPE_BOOLEAN, display->priv->headers_collapsed,
+			NULL);
+
+		if (puri->widget_func) {
+
+			widget = puri->widget_func (emf, puri, NULL);
+			if (!GTK_IS_WIDGET (widget)) {
+				g_message ("Part %s didn't provide a valid widget, skipping!", puri->uri);
+				continue;
+			}
+
+			gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
+			if (E_IS_ATTACHMENT_VIEW (widget)) {
+				EAttachmentStore *store = e_attachment_view_get_store (E_ATTACHMENT_VIEW (widget));
+				if (e_attachment_store_get_num_attachments (store) > 0)
+					gtk_widget_show (widget);
+				else
+					gtk_widget_hide (widget);
+
+				g_object_ref (widget);
+			} else
+				gtk_widget_show (widget);
+
+		}
+
+		if ((!puri->is_attachment && puri->write_func) || (puri->is_attachment && puri->write_func && puri->widget_func)) {
+			web_view = mail_display_setup_webview (display);
+			mail_display_insert_web_view (display, web_view, TRUE);
+			e_web_view_load_uri (web_view, uri);
+
+			if (widget) {
+				g_object_bind_property (widget, "expanded",
+					web_view, "visible", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+			}
+
+		}
+
+		g_free (uri);
+	}
+}
+
+static void
 mail_display_class_init (EMailDisplayClass *class)
 {
 	GObjectClass *object_class;
@@ -509,14 +626,34 @@ mail_display_class_init (EMailDisplayClass *class)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_DISPLAY_MODE,
+		PROP_MODE,
 		g_param_spec_int (
-			"display-mode",
+			"mode",
 			"Display Mode",
 			NULL,
-			E_MAIL_DISPLAY_MODE_NORMAL,
-			E_MAIL_DISPLAY_MODE_SOURCE,
-			E_MAIL_DISPLAY_MODE_NORMAL,
+			EM_FORMAT_WRITE_MODE_NORMAL,
+			EM_FORMAT_WRITE_MODE_SOURCE,
+			EM_FORMAT_WRITE_MODE_NORMAL,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_HEADERS_COLLAPSABLE,
+		g_param_spec_boolean (
+			"headers-collapsable",
+			"Headers Collapsable",
+			NULL,
+			FALSE,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_HEADERS_COLLAPSED,
+		g_param_spec_boolean (
+			"header-collapsed",
+			"Headers Collapsed",
+			NULL,
+			FALSE,
 			G_PARAM_READWRITE));
 }
 
@@ -600,100 +737,90 @@ e_mail_display_set_formatter (EMailDisplay *display,
 	g_object_notify (G_OBJECT (display), "formatter");
 }
 
-EMailDisplayMode
+EMFormatWriteMode
 e_mail_display_get_mode (EMailDisplay *display)
 {
 	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display),
-			E_MAIL_DISPLAY_MODE_NORMAL);
+			EM_FORMAT_WRITE_MODE_NORMAL);
 
-	return display->priv->display_mode;
+	return display->priv->mode;
 }
 
 void
 e_mail_display_set_mode (EMailDisplay *display,
-			 EMailDisplayMode mode)
+			 EMFormatWriteMode mode)
 {
 	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
-	if (display->priv->display_mode == mode)
+	if (display->priv->mode == mode)
 		return;
 
-	display->priv->display_mode = mode;
-	e_mail_display_reload (display);
+	display->priv->mode = mode;
+	if (mode == EM_FORMAT_WRITE_MODE_SOURCE)
+		mail_display_load_as_source (display, NULL);
+	else
+		e_mail_display_reload (display);
 
-	g_object_notify (G_OBJECT (display), "display-mode");
+	g_object_notify (G_OBJECT (display), "mode");
 }
 
-void
-e_mail_display_load (EMailDisplay *display,
-		     const gchar *msg_uri)
+gboolean
+e_mail_display_get_headers_collapsable (EMailDisplay *display)
 {
-	EWebView *web_view;
-	EMFormatPURI *puri;
-	EMFormat *emf = (EMFormat *) display->priv->formatter;
-	gchar *uri;
-	GList *iter;
-	GtkBox *box;
-
-	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
-
-	/* Don't use gtk_widget_show_all() to display all widgets at once,
-	   it makes all parts of EMailAttachmentBar visible and that's not
-	   what we want.
-	   FIXME: Maybe using gtk_widget_set_no_show_all() in EAttachmentView
-	          could help...
-	*/
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
 
-	/* First remove all widgets left after previous message */
-	e_mail_display_clear (display);
+	return display->priv->headers_collapsable;
+}
 
-	box = GTK_BOX (display->priv->vbox);
-	gtk_widget_show (display->priv->vbox);
+void
+e_mail_display_set_headers_collapsable (EMailDisplay *display,
+					gboolean collapsable)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
-	for (iter = emf->mail_part_list; iter; iter = iter->next) {
-		GtkWidget *widget = NULL;
+	if (display->priv->headers_collapsable == collapsable)
+		return;
 
-		puri = iter->data;
-		uri = em_format_build_mail_uri (emf->folder, emf->message_uid,
-			"part_id", puri->uri, NULL);
-		g_message ("%s", uri);
+	display->priv->headers_collapsable = collapsable;
+	e_mail_display_reload (display);
 
-		if (puri->widget_func) {
+	g_object_notify (G_OBJECT (display), "header-collapsable");
+}
 
-			widget = puri->widget_func (emf, puri, NULL);
-			if (!GTK_IS_WIDGET (widget)) {
-				g_message ("Part %s didn't provide a valid widget, skipping!", puri->uri);
-				continue;
-			}
+gboolean
+e_mail_display_get_headers_collapsed (EMailDisplay *display)
+{
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
 
-			gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
-			if (E_IS_ATTACHMENT_VIEW (widget)) {
-				EAttachmentStore *store = e_attachment_view_get_store (E_ATTACHMENT_VIEW (widget));
-				if (e_attachment_store_get_num_attachments (store) > 0)
-					gtk_widget_show (widget);
-				else
-					gtk_widget_hide (widget);
+	if (display->priv->headers_collapsable)
+		return display->priv->headers_collapsed;
 
-				g_object_ref (widget);
-			} else
-				gtk_widget_show (widget);
+	return FALSE;
+}
 
-		}
+void
+e_mail_display_set_headers_collapsed (EMailDisplay *display,
+				      gboolean collapsed)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
-		if ((!puri->is_attachment && puri->write_func) || (puri->is_attachment && puri->write_func && puri->widget_func)) {
-			web_view = mail_display_setup_webview (display);
-			mail_display_insert_web_view (display, web_view, TRUE);
-			e_web_view_load_uri (web_view, uri);
+	if (display->priv->headers_collapsed == collapsed)
+		return;
 
-			if (widget) {
-				g_object_bind_property (widget, "expanded",
-					web_view, "visible", G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
-			}
+	display->priv->headers_collapsed = collapsed;
+	e_mail_display_reload (display);
 
-		}
+	g_object_notify (G_OBJECT (display), "headers-collapsed");
+}
 
-		g_free (uri);
-	}
+void
+e_mail_display_load (EMailDisplay *display,
+		     const gchar *msg_uri)
+{
+	if (display->priv->mode == EM_FORMAT_WRITE_MODE_SOURCE)
+		mail_display_load_as_source  (display, msg_uri);
+	else
+		mail_display_load_normal (display, msg_uri);
 }
 
 void
@@ -703,8 +830,50 @@ e_mail_display_reload (EMailDisplay *display)
 
 	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
 
+	/* We can't just call e_web_view_reload() here, we need the URI queries
+	   to reflect possible changes in write mode and headers properties.
+	   Unfortunatelly, nothing provides API good enough to do this more
+	   simple way... */
+
 	for (iter = display->priv->webviews; iter; iter = iter->next) {
-		e_web_view_reload ((EWebView *) (iter->data));
+		EWebView *web_view;
+		const gchar *uri;
+		gchar *base;
+		GString *new_uri;
+		GHashTable *table;
+		GHashTableIter table_iter;
+		gpointer key, val;
+		char separator;
+
+		web_view = (EWebView *) iter->data;
+		uri = e_web_view_get_uri (web_view);
+
+		if (!uri)
+			continue;
+
+		base = g_strndup (uri, strstr (uri, "?") - uri);
+		new_uri = g_string_new (base);
+		g_free (base);
+
+		table = soup_form_decode (strstr (uri, "?") + 1);
+		g_hash_table_insert (table, g_strdup ("mode"), g_strdup_printf ("%d", display->priv->mode));
+		g_hash_table_insert (table, g_strdup ("headers_collapsable"), g_strdup_printf ("%d", display->priv->headers_collapsable));
+		g_hash_table_insert (table, g_strdup ("headers_collapsed"), g_strdup_printf ("%d", display->priv->headers_collapsed));
+
+		g_hash_table_iter_init (&table_iter, table);
+		separator = '?';
+		while (g_hash_table_iter_next (&table_iter, &key, &val)) {
+			g_string_append_printf (new_uri, "%c%s=%s", separator,
+				(gchar *) key, (gchar *) val);
+
+			if (separator == '?')
+				separator = '&';
+		}
+
+		e_web_view_load_uri (web_view, new_uri->str);
+
+		g_string_free (new_uri, TRUE);
+		g_hash_table_destroy (table);
 	}
 }
 
diff --git a/mail/e-mail-display.h b/mail/e-mail-display.h
index 5efb975..bb4fa8a 100644
--- a/mail/e-mail-display.h
+++ b/mail/e-mail-display.h
@@ -51,12 +51,6 @@ typedef struct _EMailDisplay EMailDisplay;
 typedef struct _EMailDisplayClass EMailDisplayClass;
 typedef struct _EMailDisplayPrivate EMailDisplayPrivate;
 
-typedef enum {
-	E_MAIL_DISPLAY_MODE_NORMAL,
-	E_MAIL_DISPLAY_MODE_ALL_HEADERS,
-	E_MAIL_DISPLAY_MODE_SOURCE
-} EMailDisplayMode;
-
 struct _EMailDisplay {
 	GtkViewport parent;
 	EMailDisplayPrivate *priv;
@@ -73,9 +67,21 @@ GType			e_mail_display_get_type			(void);
 EMFormatHTML *		e_mail_display_get_formatter	(EMailDisplay *display);
 void			e_mail_display_set_formatter	(EMailDisplay *display,
 						 	 EMFormatHTML *formatter);
+
 void			e_mail_display_set_mode		(EMailDisplay *display,
-							 EMailDisplayMode mode);
-EMailDisplayMode	e_mail_display_get_mode		(EMailDisplay *display);
+							 EMFormatWriteMode mode);
+EMFormatWriteMode	e_mail_display_get_mode		(EMailDisplay *display);
+void			e_mail_display_set_headers_collapsable
+							(EMailDisplay *display,
+							 gboolean collapsable);
+gboolean		e_mail_display_get_headers_collapsable
+							(EMailDisplay *display);
+void			e_mail_display_set_headers_collapsed
+							(EMailDisplay *display,
+							 gboolean collapsed);
+gboolean		e_mail_display_get_headers_collapsed
+							(EMailDisplay *display);
+
 void			e_mail_display_load		(EMailDisplay *display,
 						 	 const gchar *msg_uri);
 void			e_mail_display_reload		(EMailDisplay *display);
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index f203dd7..695cc58 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -444,7 +444,7 @@ e_mail_reader_open_selected (EMailReader *reader)
 		GtkWidget *browser;
 
 		browser = e_mail_browser_new (backend, folder, uid,
-				E_MAIL_DISPLAY_MODE_NORMAL);
+				EM_FORMAT_WRITE_MODE_NORMAL);
 		e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
 		e_mail_reader_set_message (E_MAIL_READER (browser), uid);
 		copy_tree_state (reader, E_MAIL_READER (browser));
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index d97fe87..1b705a3 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -1568,9 +1568,9 @@ action_mail_show_all_headers_cb (GtkToggleAction *action,
 	display = e_mail_reader_get_mail_display (reader);
 
 	if (gtk_toggle_action_get_active (action))
-		e_mail_display_set_mode (display, E_MAIL_DISPLAY_MODE_ALL_HEADERS);
+		e_mail_display_set_mode (display, EM_FORMAT_WRITE_MODE_ALL_HEADERS);
 	else
-		e_mail_display_set_mode (display, E_MAIL_DISPLAY_MODE_NORMAL);
+		e_mail_display_set_mode (display, EM_FORMAT_WRITE_MODE_NORMAL);
 }
 
 static void
@@ -1579,22 +1579,29 @@ action_mail_show_source_cb (GtkAction *action,
 {
 	EMailBackend *backend;
 	EMailDisplay *display;
+	EMFormatHTML *formatter;
 	CamelFolder *folder;
 	GtkWidget *browser;
 	GPtrArray *uids;
+	EMFormatWriteMode mode;
 	const gchar *message_uid;
 
 	backend = e_mail_reader_get_backend (reader);
 	folder = e_mail_reader_get_folder (reader);
 	display = e_mail_reader_get_mail_display (reader);
+	formatter = e_mail_display_get_formatter (display);
 
 	uids = e_mail_reader_get_selected_uids (reader);
 	g_return_if_fail (uids != NULL && uids->len == 1);
 	message_uid = g_ptr_array_index (uids, 0);
 
-	browser = e_mail_browser_new (backend, folder, message_uid,
-			E_MAIL_DISPLAY_MODE_SOURCE);
+	browser = e_mail_browser_new (backend, NULL, NULL, EM_FORMAT_WRITE_MODE_SOURCE);
+	e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
+	e_mail_reader_set_message (E_MAIL_READER (browser), message_uid);
 
+	display = e_mail_reader_get_mail_display (E_MAIL_READER (browser));
+	e_mail_display_set_formatter (display, formatter);
+	e_mail_display_set_mode (display, EM_FORMAT_WRITE_MODE_SOURCE);
 	gtk_widget_show (browser);
 
 	em_utils_uids_free (uids);
@@ -2549,7 +2556,7 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
 		(EEvent *) event, "message.reading",
 		(EEventTarget *) target);
 
-	mail_uri = em_format_build_mail_uri (folder, message_uid, NULL);
+	mail_uri = em_format_build_mail_uri (folder, message_uid, NULL, NULL);
 
 	session = webkit_get_default_session ();
 	if ((formatter = g_object_get_data (G_OBJECT (session), mail_uri)) == NULL) {
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 1f5151e..052d43b 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -48,7 +48,22 @@ start_mail_formatting (GSimpleAsyncResult *res,
 	if (part_id) {
 		request->priv->puri = em_format_find_puri (emf, part_id);
 		if (request->priv->puri) {
-			em_format_puri_write (request->priv->puri, request->priv->output_stream, NULL);
+			EMFormatWriterInfo info = {0};
+			gchar *val;
+
+			val = g_hash_table_lookup (request->priv->uri_query, "headers_collapsed");
+			if (val)
+				info.headers_collapsed = atoi (val);
+
+			val = g_hash_table_lookup (request->priv->uri_query, "headers_collapsable");
+			if (val)
+				info.headers_collapsable = atoi (val);
+
+			val = g_hash_table_lookup (request->priv->uri_query, "mode");
+			if (val)
+				info.mode = atoi (val);
+
+			em_format_puri_write (request->priv->puri, request->priv->output_stream, &info, NULL);
 		} else {
 			g_warning ("Failed to lookup requested part '%s' - this should not happen!", part_id);
 		}
@@ -84,14 +99,16 @@ get_file_content (GSimpleAsyncResult *res,
 	uri = soup_request_get_uri (SOUP_REQUEST (request));
 
 	if (g_file_get_contents (uri->path, &contents, &length, NULL)) {
-		request->priv->mime_type = g_content_type_guess (uri->path, NULL, 0, NULL);
 
+		request->priv->mime_type = g_content_type_guess (uri->path, NULL, 0, NULL);
 		request->priv->content_length = length;
 
 		stream = g_memory_input_stream_new_from_data (contents, length, NULL);
 		g_simple_async_result_set_op_res_gpointer (res, stream, NULL);
 
-		g_free (contents);
+		/* FIXME - Freeing the data empties the result stream, but without it
+		   the #contents leaks memory */
+		//g_free (contents);
 	}
 }
 
@@ -165,7 +182,6 @@ mail_request_send_async (SoupRequest *request,
 			g_return_if_fail (uri->query);
 		}
 
-		/* SoupURI has no API to get URI without queries */
 		uri_str = g_strdup_printf ("%s://%s%s", uri->scheme, uri->host, uri->path);
 
 		emr->priv->efh = g_object_get_data (G_OBJECT (session), uri_str);
@@ -220,20 +236,20 @@ static const gchar*
 mail_request_get_content_type (SoupRequest *request)
 {
 	EMailRequest *emr = E_MAIL_REQUEST (request);
+	const gchar *mime_type;
 
 	if (emr->priv->mime_type)
-		return emr->priv->mime_type;
-
-	if (!emr->priv->puri)
-		return "text/html";
-
-	if (!emr->priv->puri->mime_type) {
+		mime_type = emr->priv->mime_type;
+	else if (!emr->priv->puri)
+		mime_type = "text/html";
+	else if (!emr->priv->puri->mime_type) {
 		CamelContentType *ct = camel_mime_part_get_content_type (emr->priv->puri->part);
-		return camel_content_type_format (ct);
+		mime_type = camel_content_type_format (ct);
 	} else
-		return emr->priv->puri->mime_type;
+		mime_type = emr->priv->puri->mime_type;
 
-	return "text/html";
+	d(printf("Content-Type: %s\n", mime_type));
+	return mime_type;
 }
 
 static const char *data_schemes[] = { "mail", "evo-file", NULL };
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 7c530b9..fc2a39b 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -67,9 +67,6 @@ struct _EMFormatHTMLPrivate {
 	GdkColor colors[EM_FORMAT_HTML_NUM_COLOR_TYPES];
 	EMailImageLoadingPolicy image_loading_policy;
 
-	EMFormatHTMLHeadersState headers_state;
-	gboolean headers_collapsable;
-
 	guint load_images_now	: 1;
 	guint only_local_photos	: 1;
 	guint show_sender_photo	: 1;
@@ -91,8 +88,6 @@ enum {
 	PROP_SHOW_SENDER_PHOTO,
 	PROP_SHOW_REAL_DATE,
 	PROP_TEXT_COLOR,
-	PROP_HEADERS_STATE,
-	PROP_HEADERS_COLLAPSABLE
 };
 
 #define EFM_MESSAGE_START_ANAME "evolution_message_start"
@@ -135,13 +130,17 @@ static void efh_parse_message_external		(EMFormat *emf, CamelMimePart *part, GSt
 static void efh_parse_message_deliverystatus	(EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 static void efh_parse_message_rfc822		(EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 
-static void efh_write_image			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void efh_write_text_enriched		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void efh_write_text_plain		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void efh_write_text_html			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void efh_write_source			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void efh_write_message_rfc822		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
-static void efh_write_headers			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, GCancellable *cancellable);
+static void efh_write_image			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_text_enriched		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_text_plain		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_text_html			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_source			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_message_rfc822		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_headers			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+
+static void efh_format_full_headers 		(EMFormatHTML *efh, GString *buffer, CamelMedium *part, gboolean all_headers, gboolean visible, GCancellable *cancellable);
+static void efh_format_short_headers 		(EMFormatHTML *efh, GString *buffer, CamelMedium *part, gboolean visible, GCancellable *cancellable);
+
 /*****************************************************************************/
 static void
 efh_parse_image (EMFormat *emf,
@@ -564,6 +563,7 @@ static void
 efh_write_image (EMFormat *emf,
 		 EMFormatPURI *puri,
 		 CamelStream *stream,
+ 		 EMFormatWriterInfo *info,
 		 GCancellable *cancellable)
 {
 	GByteArray *ba;
@@ -597,6 +597,7 @@ static void
 efh_write_text_enriched (EMFormat *emf,
 			 EMFormatPURI *puri,
 			 CamelStream *stream,
+			 EMFormatWriterInfo *info,
 			 GCancellable *cancellable)
 {
 	EMFormatHTML *efh = EM_FORMAT_HTML (emf);
@@ -664,6 +665,7 @@ static void
 efh_write_text_plain (EMFormat *emf,
 		      EMFormatPURI *puri,
 		      CamelStream *stream,
+ 		      EMFormatWriterInfo *info,
 		      GCancellable *cancellable)
 {
 	CamelDataWrapper *dw;
@@ -716,6 +718,7 @@ static void
 efh_write_text_html (EMFormat *emf,
 		     EMFormatPURI *puri,
 		     CamelStream *stream,
+		     EMFormatWriterInfo *info,
 		     GCancellable *cancellable)
 {
 	if (g_cancellable_is_cancelled (cancellable))
@@ -729,8 +732,11 @@ static void
 efh_write_source (EMFormat *emf,
 		  EMFormatPURI *puri,
 		  CamelStream *stream,
+		  EMFormatWriterInfo *info,
 		  GCancellable *cancellable)
 {
+	EMFormatHTML *efh = (EMFormatHTML *) emf;
+	GString *buffer;
 	CamelStream *filtered_stream;
 	CamelMimeFilter *filter;
 	CamelDataWrapper *dw = (CamelDataWrapper *) puri->part;
@@ -745,23 +751,75 @@ efh_write_source (EMFormat *emf,
 		CAMEL_STREAM_FILTER (filtered_stream), filter);
 	g_object_unref (filter);
 
+	buffer = g_string_new ("");
+	g_string_append_printf (
+		buffer, EFH_HTML_HEADER,
+		e_color_to_value (
+			&efh->priv->colors[
+			EM_FORMAT_HTML_COLOR_BODY]),
+		e_color_to_value (
+			&efh->priv->colors[
+			EM_FORMAT_HTML_COLOR_HEADER]));
+	camel_stream_write_string (
+		stream, buffer->str, cancellable, NULL);
 	camel_stream_write_string (
 		stream, "<code class=\"pre\">", cancellable, NULL);
-	em_format_format_text (emf, filtered_stream, dw, cancellable);
+	camel_data_wrapper_write_to_stream_sync (dw, filtered_stream,
+		cancellable, NULL);
 	camel_stream_write_string (
 		stream, "</code>", cancellable, NULL);
 
 	g_object_unref (filtered_stream);
+	g_string_free (buffer, TRUE);
 }
 
 static void
 efh_write_headers (EMFormat *emf,
 		   EMFormatPURI *puri,
 		   CamelStream *stream,
+		   EMFormatWriterInfo *info,
 		   GCancellable *cancellable)
 {
-	/* FIXME: We could handle this more nicely */
-	em_format_html_format_headers ((EMFormatHTML *) emf, stream, (CamelMedium *)  puri->part, FALSE, cancellable);
+	GString *buffer;
+	EMFormatHTML *efh = (EMFormatHTML *) emf;
+
+	if (!puri->part)
+		return;
+
+	buffer = g_string_new ("");
+
+	g_string_append_printf (
+		buffer, EFH_HTML_HEADER,
+		e_color_to_value (
+			&efh->priv->colors[
+			EM_FORMAT_HTML_COLOR_BODY]),
+		e_color_to_value (
+			&efh->priv->colors[
+			EM_FORMAT_HTML_COLOR_HEADER]));
+
+	g_string_append (buffer, "<table border=\"0\" width=\"100%\"><tr><td valign=\"top\" width=\"16\">");
+
+	if (info->headers_collapsable) {
+		g_string_append_printf (buffer,
+			"<img src=\"evo-file://%s/%s\" onClick=\"collapse_headers();\" class=\"navigable\" id=\"collapse-headers-img\" /></td><td>",
+			EVOLUTION_IMAGESDIR,
+			(info->headers_collapsed) ? "plus.png" : "minus.png");
+
+		efh_format_short_headers (efh, buffer, (CamelMedium *) puri->part,
+			info->headers_collapsed,
+			cancellable);
+	}
+
+	efh_format_full_headers (efh, buffer, (CamelMedium *) puri->part,
+		(info->mode == EM_FORMAT_WRITE_MODE_ALL_HEADERS),
+		!info->headers_collapsed,
+		cancellable);
+
+	g_string_append (buffer, "</td></tr></table>" EFH_HTML_FOOTER);
+
+	camel_stream_write_string (stream, buffer->str, cancellable, NULL);
+
+	g_string_free (buffer, true);
 }
 
 /*****************************************************************************/
@@ -811,6 +869,7 @@ static EMFormatHandler type_builtin_table[] = {
 	/* special internal types */
 	{ (gchar *) "x-evolution/message/rfc822", 0, efh_write_text_plain, },
 	{ (gchar *) "x-evolution/message/headers", 0, efh_write_headers, },
+	{ (gchar *) "x-evolution/message/source", 0, efh_write_source, },
 };
 
 static void
@@ -904,15 +963,6 @@ efh_set_property (GObject *object,
 				EM_FORMAT_HTML_COLOR_TEXT,
 				g_value_get_boxed (value));
 			return;
-		case PROP_HEADERS_STATE:
-			em_format_html_set_headers_state (
-				EM_FORMAT_HTML (object),
-				g_value_get_int (value));
-			return;
-		case PROP_HEADERS_COLLAPSABLE:
-			em_format_html_set_headers_collapsable (
-				EM_FORMAT_HTML (object),
-				g_value_get_boolean (value));
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1005,16 +1055,6 @@ efh_get_property (GObject *object,
 				&color);
 			g_value_set_boxed (value, &color);
 			return;
-
-		case PROP_HEADERS_STATE:
-			g_value_set_int (
-				value, em_format_html_get_headers_state (
-				EM_FORMAT_HTML (object)));
-			return;
-		case PROP_HEADERS_COLLAPSABLE:
-			g_value_set_boolean (
-				value, em_format_html_get_headers_collapsable (
-				EM_FORMAT_HTML (object)));
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1083,10 +1123,10 @@ efh_format_source (EMFormat *emf,
 	g_object_unref (filter);
 
 	camel_stream_write_string (
-		stream, "<code class=\"pre\">", cancellable, NULL);
+		stream, EFH_HTML_HEADER "<code class=\"pre\">", cancellable, NULL);
 	em_format_format_text (emf, filtered_stream, dw, cancellable);
 	camel_stream_write_string (
-		stream, "</code>", cancellable, NULL);
+		stream, "</code>" EFH_HTML_FOOTER, cancellable, NULL);
 
 	g_object_unref (filtered_stream);
 }
@@ -1275,28 +1315,6 @@ efh_class_init (EMFormatHTMLClass *class)
 			GDK_TYPE_COLOR,
 			G_PARAM_READWRITE));
 
-	g_object_class_install_property (
-		object_class,
-		PROP_HEADERS_STATE,
-		g_param_spec_int (
-			"headers-state",
-			"Headers state",
-			NULL,
-			EM_FORMAT_HTML_HEADERS_STATE_EXPANDED,
-			EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED,
-			EM_FORMAT_HTML_HEADERS_STATE_EXPANDED,
-			G_PARAM_READWRITE));
-
-	g_object_class_install_property (
-		object_class,
-		PROP_HEADERS_COLLAPSABLE,
-		g_param_spec_boolean (
-			"headers-collapsable",
-			NULL,
-			NULL,
-			FALSE,
-			G_PARAM_READWRITE));
-
 	/* cache expiry - 2 hour access, 1 day max */
 
 	/* FIXME WEBKIT - this emfh_http_cache is not used anywhere - remove?
@@ -1347,7 +1365,6 @@ efh_init (EMFormatHTML *efh,
 		CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
 		CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
 	efh->show_icon = TRUE;
-	efh->state = EM_FORMAT_HTML_STATE_NONE;
 
 	/* FIXME WEBKIT: emit signal? */
 	/*
@@ -1583,44 +1600,6 @@ em_format_html_set_show_real_date (EMFormatHTML *efh,
 	g_object_notify (G_OBJECT (efh), "show-real-date");
 }
 
-EMFormatHTMLHeadersState
-em_format_html_get_headers_state (EMFormatHTML *efh)
-{
-	g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), EM_FORMAT_HTML_HEADERS_STATE_EXPANDED);
-
-	return efh->priv->headers_state;
-}
-
-void
-em_format_html_set_headers_state (EMFormatHTML *efh,
-				  EMFormatHTMLHeadersState state)
-{
-	g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
-	efh->priv->headers_state = state;
-
-	g_object_notify (G_OBJECT (efh), "headers-state");
-}
-
-gboolean
-em_format_html_get_headers_collapsable (EMFormatHTML *efh)
-{
-	g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), FALSE);
-
-	return efh->priv->headers_collapsable;
-}
-
-void
-em_format_html_set_headers_collapsable (EMFormatHTML *efh,
-					gboolean collapsable)
-{
-	g_return_if_fail (EM_IS_FORMAT_HTML (efh));
-
-	efh->priv->headers_collapsable = collapsable;
-
-	g_object_notify (G_OBJECT (efh), "headers-collapsable");
-}
-
 CamelMimePart *
 em_format_html_file_part (EMFormatHTML *efh,
                           const gchar *mime_type,
@@ -2404,50 +2383,6 @@ efh_format_full_headers (EMFormatHTML *efh,
 	g_string_append (buffer, "</tr></table>");
 }
 
-void
-em_format_html_format_headers (EMFormatHTML *efh,
-			       CamelStream *stream,
-			       CamelMedium *part,
-			       gboolean all_headers,
-			       GCancellable *cancellable)
-{
-	GString *buffer;
-
-	if (!part)
-		return;
-
-	buffer = g_string_new ("");
-
-	g_string_append_printf (
-		buffer, EFH_HTML_HEADER,
-		e_color_to_value (
-			&efh->priv->colors[
-			EM_FORMAT_HTML_COLOR_BODY]),
-		e_color_to_value (
-			&efh->priv->colors[
-			EM_FORMAT_HTML_COLOR_HEADER]));
-
-	if (efh->priv->headers_collapsable) {
-		g_string_append_printf (buffer,
-			"<img src=\"evo-file://%s/%s\" onClick=\"collapse_headers();\" class=\"navigable\" id=\"collapse-headers-img\" /></td><td>",
-			EVOLUTION_IMAGESDIR,
-			(efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED) ? "plus.png" : "minus.png");
-
-		efh_format_short_headers (efh, buffer, part,
-			(efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED),
-			cancellable);
-	}
-
-	efh_format_full_headers (efh, buffer, part, all_headers,
-		(efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_EXPANDED),
-		cancellable);
-
-	g_string_append (buffer, "</td></tr></table>" EFH_HTML_FOOTER);
-
-	camel_stream_write_string (stream, buffer->str, cancellable, NULL);
-
-	g_string_free (buffer, true);
-}
 
 /* unref returned pointer with g_object_unref(), if not NULL */
 CamelStream *
diff --git a/mail/em-format-html.h b/mail/em-format-html.h
index 00de997..020acd2 100644
--- a/mail/em-format-html.h
+++ b/mail/em-format-html.h
@@ -65,16 +65,6 @@ enum _em_format_html_header_flags {
 };
 
 typedef enum {
-	EM_FORMAT_HTML_STATE_NONE = 0,
-	EM_FORMAT_HTML_STATE_RENDERING
-} EMFormatHTMLState;
-
-typedef enum {
-	EM_FORMAT_HTML_HEADERS_STATE_EXPANDED = 0, /* Default value */
-	EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED
-} EMFormatHTMLHeadersState;
-
-typedef enum {
 	EM_FORMAT_HTML_COLOR_BODY,	/* header area background */
 	EM_FORMAT_HTML_COLOR_CITATION,	/* citation font color */
 	EM_FORMAT_HTML_COLOR_CONTENT,	/* message area background */
@@ -135,8 +125,6 @@ struct _EMFormatHTML {
 	guint hide_headers:1; /* no headers at all */
 	guint show_icon:1; /* show an icon when the sender used Evo */
 	guint32 header_wrap_flags;
-
-	EMFormatHTMLState state; /* actual state of the object */
 };
 
 struct _EMFormatHTMLClass {
@@ -179,17 +167,6 @@ gboolean	em_format_html_get_show_real_date
 void		em_format_html_set_show_real_date
 						(EMFormatHTML *efh,
 						 gboolean show_real_date);
-EMFormatHTMLHeadersState
-		em_format_html_get_headers_state
-						(EMFormatHTML *efh);
-void		em_format_html_set_headers_state
-						(EMFormatHTML *efh,
-						 EMFormatHTMLHeadersState state);
-gboolean	em_format_html_get_headers_collapsable
-						(EMFormatHTML *efh);
-void		em_format_html_set_headers_collapsable
-						(EMFormatHTML *efh,
-						 gboolean collapsable);
 
 /* retrieves a pseudo-part icon wrapper for a file */
 CamelMimePart *	em_format_html_file_part	(EMFormatHTML *efh,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]