[evolution/webkit] Convert EMailDisplay to GtkScrolledWindow and change the way EMFormat is used.



commit 33dc8a60df86c2004a7f55f3c9c3dd25736998eb
Author: Dan VrÃtil <dvratil redhat com>
Date:   Fri Aug 26 16:29:38 2011 +0200

    Convert EMailDisplay to GtkScrolledWindow and change the way EMFormat is used.
    
    Because embedding widgets directly into WebKit is broken, I decided to
    split the email into multiple webview, thus allowing me to embbed
    GtkWidgets between the webviews directly to a parent container.
    
    The idea is to have EMailDisplay to implement most of the API of EWebView, thus
    making it to look like a single EWebView from the outside. The EMailDisplay
    would then work as a "proxy" resending the commands/signals/etc to all the
    EWebViews and widgets it would manage.
    
    This also requires completely another way of using EMFormat. Till now, it was
    EMFormat-per-EMailDisplay. Since now, it's EMFormat-per-mail. This way, displaying
    the same email in multiple views (the preview pane and EMailBrowser for example)
    requires the email to be parsed only once and then the write_func of the required
    mail parts are called. This can have positive impact on performance and user experience.
    
    FIXME: For now, all created EMFormat objects remain stored in SoupSession and are not
    removed even after the mail is not being displayed in any view. This is a big memleak
    that needs to be fixed definitely.

 mail/e-mail-browser.c                    |   53 ++---
 mail/e-mail-browser.h                    |    6 +-
 mail/e-mail-display.c                    |  404 ++++++++++++++++++++++++++----
 mail/e-mail-display.h                    |   51 ++++-
 mail/e-mail-notebook-view.c              |    8 +-
 mail/e-mail-paned-view.c                 |   52 ++--
 mail/e-mail-reader-utils.c               |   32 ++-
 mail/e-mail-reader.c                     |  205 +++++++---------
 mail/e-mail-reader.h                     |    6 +-
 mail/e-mail-request.c                    |  112 ++++++---
 mail/em-utils.c                          |   17 +-
 modules/mail/e-mail-shell-backend.c      |    5 +-
 modules/mail/e-mail-shell-content.c      |   10 +-
 modules/mail/e-mail-shell-view-actions.c |   22 +-
 modules/mail/e-mail-shell-view-private.c |   41 ++--
 15 files changed, 698 insertions(+), 326 deletions(-)
---
diff --git a/mail/e-mail-browser.c b/mail/e-mail-browser.c
index e4799bf..9a186b1 100644
--- a/mail/e-mail-browser.c
+++ b/mail/e-mail-browser.c
@@ -54,7 +54,7 @@ struct _EMailBrowserPrivate {
 	EMailBackend *backend;
 	GtkUIManager *ui_manager;
 	EFocusTracker *focus_tracker;
-	EMFormatHTMLDisplay *formatter;
+	EMailDisplay *display;
 
 	GtkWidget *main_menu;
 	GtkWidget *main_toolbar;
@@ -264,11 +264,10 @@ static void
 mail_browser_message_selected_cb (EMailBrowser *browser,
                                   const gchar *uid)
 {
-	EMFormatHTML *formatter;
 	CamelMessageInfo *info;
 	CamelFolder *folder;
 	EMailReader *reader;
-	EWebView *web_view;
+	EMailDisplay *display;
 	const gchar *title;
 
 	reader = E_MAIL_READER (browser);
@@ -278,8 +277,7 @@ mail_browser_message_selected_cb (EMailBrowser *browser,
 		return;
 
 	folder = e_mail_reader_get_folder (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 
 	info = camel_folder_get_message_info (folder, uid);
 
@@ -291,7 +289,7 @@ mail_browser_message_selected_cb (EMailBrowser *browser,
 		title = _("(No Subject)");
 
 	gtk_window_set_title (GTK_WINDOW (browser), title);
-	gtk_widget_grab_focus (GTK_WIDGET (web_view));
+	gtk_widget_grab_focus (GTK_WIDGET (display));
 
 	camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
 	camel_folder_free_message_info (folder, info);
@@ -320,7 +318,7 @@ mail_browser_popup_event_cb (EMailBrowser *browser,
                              GdkEventButton *event,
                              const gchar *uri)
 {
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	EMailReader *reader;
 	EWebView *web_view;
 	GtkMenu *menu;
@@ -330,8 +328,8 @@ mail_browser_popup_event_cb (EMailBrowser *browser,
 		return FALSE;
 
 	reader = E_MAIL_READER (browser);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
+	web_view = e_mail_display_get_current_web_view (display);
 
 	if (e_web_view_get_cursor_image (web_view) != NULL)
 		return FALSE;
@@ -496,11 +494,6 @@ mail_browser_dispose (GObject *object)
 		priv->focus_tracker = NULL;
 	}
 
-	if (priv->formatter != NULL) {
-		g_object_unref (priv->formatter);
-		priv->formatter = NULL;
-	}
-
 	if (priv->main_menu != NULL) {
 		g_object_unref (priv->main_menu);
 		priv->main_menu = NULL;
@@ -540,7 +533,6 @@ static void
 mail_browser_constructed (GObject *object)
 {
 	EMailBrowserPrivate *priv;
-	EMFormatHTML *formatter;
 	EMailReader *reader;
 	EMailBackend *backend;
 	EShellBackend *shell_backend;
@@ -554,7 +546,6 @@ mail_browser_constructed (GObject *object)
 	GtkUIManager *ui_manager;
 	GtkWidget *container;
 	GtkWidget *widget;
-	EWebView *web_view;
 	const gchar *domain;
 	const gchar *key;
 	const gchar *id;
@@ -577,10 +568,9 @@ mail_browser_constructed (GObject *object)
 	priv->ui_manager = ui_manager;
 	domain = GETTEXT_PACKAGE;
 
-	formatter = e_mail_reader_get_formatter (reader);
 	e_shell_watch_window (shell, GTK_WINDOW (object));
 
-	web_view = em_format_html_get_web_view (formatter);
+	priv->display = e_mail_reader_get_mail_display (reader);
 
 	/* The message list is a widget, but it is not shown in the browser.
 	 * Unfortunately, the widget is inseparable from its model, and the
@@ -597,11 +587,11 @@ mail_browser_constructed (GObject *object)
 		G_CALLBACK (mail_browser_message_list_built_cb), object);
 
 	g_signal_connect_swapped (
-		web_view, "popup-event",
+		priv->display, "popup-event",
 		G_CALLBACK (mail_browser_popup_event_cb), object);
 
 	g_signal_connect_swapped (
-		web_view, "status-message",
+		priv->display, "status-message",
 		G_CALLBACK (mail_browser_status_message_cb), object);
 
 	/* Add action groups before initializing the reader interface. */
@@ -693,18 +683,18 @@ mail_browser_constructed (GObject *object)
 	priv->alert_bar = g_object_ref (widget);
 	/* EAlertBar controls its own visibility. */
 
-	gtk_widget_show (GTK_WIDGET (web_view));
+	gtk_widget_show (GTK_WIDGET (priv->display));
 
-	widget = e_preview_pane_new (web_view);
+	widget = GTK_WIDGET (priv->display);
 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
 	gtk_widget_show (widget);
 
-	search_bar = e_preview_pane_get_search_bar (E_PREVIEW_PANE (widget));
+	search_bar = e_mail_display_get_search_bar (priv->display);
 	priv->search_bar = g_object_ref (search_bar);
 
 	g_signal_connect_swapped (
 		search_bar, "changed",
-		G_CALLBACK (e_web_view_reload), web_view);
+		G_CALLBACK (e_mail_display_reload), priv->display);
 
 	/* Bind GObject properties to GConf keys. */
 
@@ -811,14 +801,14 @@ mail_browser_get_hide_deleted (EMailReader *reader)
 	return !e_mail_browser_get_show_deleted (browser);
 }
 
-static EMFormatHTML *
-mail_browser_get_formatter (EMailReader *reader)
+static EMailDisplay *
+mail_browser_get_mail_display (EMailReader *reader)
 {
 	EMailBrowserPrivate *priv;
 
 	priv = E_MAIL_BROWSER (reader)->priv;
 
-	return EM_FORMAT_HTML (priv->formatter);
+	return priv->display;
 }
 
 static GtkWidget *
@@ -969,7 +959,7 @@ e_mail_browser_reader_init (EMailReaderInterface *interface)
 	interface->get_action_group = mail_browser_get_action_group;
 	interface->get_alert_sink = mail_browser_get_alert_sink;
 	interface->get_backend = mail_browser_get_backend;
-	interface->get_formatter = mail_browser_get_formatter;
+	interface->get_mail_display = mail_browser_get_mail_display;
 	interface->get_hide_deleted = mail_browser_get_hide_deleted;
 	interface->get_message_list = mail_browser_get_message_list;
 	interface->get_popup_menu = mail_browser_get_popup_menu;
@@ -987,7 +977,7 @@ e_mail_browser_init (EMailBrowser *browser)
 	browser->priv = G_TYPE_INSTANCE_GET_PRIVATE (
 		browser, E_TYPE_MAIL_BROWSER, EMailBrowserPrivate);
 
-	browser->priv->formatter = em_format_html_display_new ();
+	browser->priv->display = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
 
 	bridge = gconf_bridge_get ();
 	prefix = "/apps/evolution/mail/mail_browser";
@@ -997,7 +987,10 @@ e_mail_browser_init (EMailBrowser *browser)
 }
 
 GtkWidget *
-e_mail_browser_new (EMailBackend *backend)
+e_mail_browser_new (EMailBackend *backend,
+		    CamelFolder *folder,
+		    const gchar *msg_uid,
+		    EMailDisplayMode mode)
 {
 	g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL);
 
diff --git a/mail/e-mail-browser.h b/mail/e-mail-browser.h
index c09c85b..90ea53a 100644
--- a/mail/e-mail-browser.h
+++ b/mail/e-mail-browser.h
@@ -24,6 +24,7 @@
 
 #include <mail/e-mail-backend.h>
 #include <misc/e-focus-tracker.h>
+#include <mail/e-mail-display.h>
 
 /* Standard GObject macros */
 #define E_TYPE_MAIL_BROWSER \
@@ -60,7 +61,10 @@ struct _EMailBrowserClass {
 };
 
 GType		e_mail_browser_get_type		(void);
-GtkWidget *	e_mail_browser_new		(EMailBackend *backend);
+GtkWidget *	e_mail_browser_new		(EMailBackend *backend,
+						 CamelFolder *folder,
+						 const gchar *message_uid,
+						 EMailDisplayMode 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 f0b3980..a907daa 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -34,21 +34,31 @@
 #include "mail/em-composer-utils.h"
 #include "mail/em-utils.h"
 #include "mail/e-mail-request.h"
+#include "mail/em-format-html-display.h"
+#include "mail/e-mail-attachment-bar.h"
 
 #include <libsoup/soup.h>
 #include <libsoup/soup-requester.h>
 
 struct _EMailDisplayPrivate {
+	GtkWidget *vbox;
+
+	ESearchBar *searchbar;
 	EMFormatHTML *formatter;
+
+	EMailDisplayMode display_mode;
 };
 
 enum {
 	PROP_0,
-	PROP_FORMATTER
+	PROP_FORMATTER,
+	PROP_DISPLAY_MODE
 };
 
 static gpointer parent_class;
 
+typedef void (*WebViewActionFunc) (EWebView *web_view);
+
 static const gchar *ui =
 "<ui>"
 "  <popup name='context'>"
@@ -62,6 +72,7 @@ static const gchar *ui =
 "        <menuitem action='search-folder-sender'/>"
 "      </menu>"
 "    </placeholder>"
+"    <placeholder name='inspect' />"
 "  </popup>"
 "</ui>";
 
@@ -117,6 +128,9 @@ mail_display_update_formatter_colors (EMailDisplay *display)
 	state = gtk_widget_get_state (GTK_WIDGET (display));
 	formatter = display->priv->formatter;
 
+	if (!display->priv->formatter)
+		return;
+
 	style = gtk_widget_get_style (GTK_WIDGET (display));
 	if (style == NULL)
 		return;
@@ -158,6 +172,11 @@ mail_display_set_property (GObject *object,
 				E_MAIL_DISPLAY (object),
 				g_value_get_object (value));
 			return;
+		case PROP_DISPLAY_MODE:
+			e_mail_display_set_mode (
+				E_MAIL_DISPLAY (object),
+				g_value_get_int (value));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -175,6 +194,11 @@ mail_display_get_property (GObject *object,
 				value, e_mail_display_get_formatter (
 				E_MAIL_DISPLAY (object)));
 			return;
+		case PROP_DISPLAY_MODE:
+			g_value_set_int (
+				value, e_mail_display_get_mode (
+				E_MAIL_DISPLAY (object)));
+			return;
 	}
 
 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -192,6 +216,11 @@ mail_display_dispose (GObject *object)
 		priv->formatter = NULL;
 	}
 
+	if (priv->searchbar) {
+		g_object_unref (priv->searchbar);
+		priv->searchbar = NULL;
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -209,21 +238,26 @@ static void
 mail_display_style_set (GtkWidget *widget,
                         GtkStyle *previous_style)
 {
+	EMailDisplay *display = E_MAIL_DISPLAY (widget);
+
 	/* Chain up to parent's style_set() method. */
 	GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
 
-	mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget));
+	mail_display_update_formatter_colors (display);
 
-	e_web_view_reload (E_WEB_VIEW (widget));
+	e_mail_display_reload (display);
 }
 
 static gboolean
 mail_display_process_mailto (EWebView *web_view,
-                             const gchar *mailto_uri)
+                             const gchar *mailto_uri,
+                             gpointer user_data)
 {
+	EMailDisplay *display = user_data;
+
 	g_return_val_if_fail (web_view != NULL, FALSE);
 	g_return_val_if_fail (mailto_uri != NULL, FALSE);
-	g_return_val_if_fail (E_IS_MAIL_DISPLAY (web_view), FALSE);
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
 
 	if (g_ascii_strncasecmp (mailto_uri, "mailto:";, 7) == 0) {
 		EMailDisplayPrivate *priv;
@@ -231,7 +265,7 @@ mail_display_process_mailto (EWebView *web_view,
 		CamelFolder *folder = NULL;
 		EShell *shell;
 
-		priv = E_MAIL_DISPLAY (web_view)->priv;
+		priv = display->priv;
 		g_return_val_if_fail (priv->formatter != NULL, FALSE);
 
 		format = EM_FORMAT (priv->formatter);
@@ -261,10 +295,10 @@ mail_display_link_clicked (WebKitWebView *web_view,
 	EMailDisplayPrivate *priv;
 	const gchar *uri = webkit_network_request_get_uri (request);
 
-	priv = E_MAIL_DISPLAY (display)->priv;
+	priv = display->priv;
 	g_return_val_if_fail (priv->formatter != NULL, FALSE);
 
-	if (mail_display_process_mailto (E_WEB_VIEW (display), uri)) {
+	if (mail_display_process_mailto (E_WEB_VIEW (web_view), uri, display)) {
 		/* do nothing, function handled the "mailto:"; uri already */
 		webkit_web_policy_decision_ignore (policy_decision);
 		return TRUE;
@@ -288,17 +322,17 @@ static void
 mail_display_resource_requested (WebKitWebView *web_view,
 				 WebKitWebFrame *frame,
 				 WebKitWebResource *resource,
-                        	 WebKitNetworkRequest *request,
-                        	 WebKitNetworkResponse *response,
-                        	 gpointer user_data)
+				 WebKitNetworkRequest *request,
+				 WebKitNetworkResponse *response,
+				 gpointer user_data)
 {
-	EMFormatHTML *formatter = E_MAIL_DISPLAY (web_view)->priv->formatter;
+	EMailDisplay *display = user_data;
+	EMFormatHTML *formatter = display->priv->formatter;
 	const gchar *uri = webkit_network_request_get_uri (request);
 
         /* 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)->uid, uri, EM_FORMAT (formatter));
+		gchar *new_uri = em_format_build_mail_uri (EM_FORMAT (formatter)->folder, EM_FORMAT (formatter)->message_uid, uri);
 
                 webkit_network_request_set_uri (request, new_uri);
 
@@ -335,7 +369,7 @@ mail_display_resource_requested (WebKitWebView *web_view,
                 g_free (path);
         }
 
-       	g_signal_stop_emission_by_name (web_view, "resource-request-starting");
+       	//g_signal_stop_emission_by_name (web_view, "resource-request-starting");
 }
 
 static void
@@ -344,7 +378,8 @@ mail_display_headers_collapsed_state_changed (EWebView *web_view,
 					      const JSValueRef args[],
 					      gpointer user_data)
 {
-	EMFormatHTML *formatter = E_MAIL_DISPLAY (web_view)->priv->formatter;
+	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]);
@@ -370,13 +405,52 @@ mail_display_install_js_callbacks (WebKitWebView *web_view,
 		(EWebViewJSFunctionCallback) mail_display_headers_collapsed_state_changed, user_data);
 }
 
+static EWebView*
+mail_display_setup_webview (EMailDisplay *display)
+{
+	EWebView *web_view;
+	GtkUIManager *ui_manager;
+	GtkActionGroup *action_group;
+	GError *error = NULL;
+
+	web_view = E_WEB_VIEW (e_web_view_new ());
+
+	g_signal_connect (web_view, "navigation-policy-decision-requested",
+		G_CALLBACK (mail_display_link_clicked), display);
+	g_signal_connect (web_view, "window-object-cleared",
+		G_CALLBACK (mail_display_install_js_callbacks), display);
+	g_signal_connect (web_view, "resource-request-starting",
+		G_CALLBACK (mail_display_resource_requested), display);
+	g_signal_connect (web_view, "process-mailto",
+		G_CALLBACK (mail_display_process_mailto), display);
+
+	/* EWebView's action groups are added during its instance
+	 * initialization function (like what we're in now), so it
+	 * is safe to fetch them this early in construction. */
+	action_group = e_web_view_get_action_group (web_view, "mailto");
+
+	/* We don't actually handle the actions we're adding.
+	 * EMailReader handles them.  How devious is that? */
+	gtk_action_group_add_actions (
+		action_group, mailto_entries,
+		G_N_ELEMENTS (mailto_entries), display);
+
+	/* Because we are loading from a hard-coded string, there is
+	 * no chance of I/O errors.  Failure here implies a malformed
+	 * UI definition.  Full stop. */
+	ui_manager = e_web_view_get_ui_manager (web_view);
+	gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
+	if (error != NULL)
+		g_error ("%s", error->message);
+
+	return web_view;
+}
 
 static void
 mail_display_class_init (EMailDisplayClass *class)
 {
 	GObjectClass *object_class;
 	GtkWidgetClass *widget_class;
-	EWebViewClass *web_view_class;
 
 	parent_class = g_type_class_peek_parent (class);
 	g_type_class_add_private (class, sizeof (EMailDisplayPrivate));
@@ -390,9 +464,6 @@ mail_display_class_init (EMailDisplayClass *class)
 	widget_class->realize = mail_display_realize;
 	widget_class->style_set = mail_display_style_set;
 
-	web_view_class = E_WEB_VIEW_CLASS (class);
-	web_view_class->process_mailto = mail_display_process_mailto;
-
 	g_object_class_install_property (
 		object_class,
 		PROP_FORMATTER,
@@ -402,51 +473,46 @@ mail_display_class_init (EMailDisplayClass *class)
 			NULL,
 			EM_TYPE_FORMAT_HTML,
 			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_DISPLAY_MODE,
+		g_param_spec_int (
+			"display-mode",
+			"Display Mode",
+			NULL,
+			E_MAIL_DISPLAY_MODE_NORMAL,
+			E_MAIL_DISPLAY_MODE_SOURCE,
+			E_MAIL_DISPLAY_MODE_NORMAL,
+			G_PARAM_READWRITE));
 }
 
 static void
 mail_display_init (EMailDisplay *display)
 {
-	GtkUIManager *ui_manager;
-	GtkActionGroup *action_group;
-	GError *error = NULL;
-	EWebView *web_view;
+	GtkScrolledWindow *scrolled_window;
 	SoupSession *session;
 	SoupSessionFeature *feature;
-
-	web_view = E_WEB_VIEW (display);
+	GValue margin = {0};
 
 	display->priv = G_TYPE_INSTANCE_GET_PRIVATE (
 		display, E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate);
 
-	g_signal_connect (web_view, "navigation-policy-decision-requested",
-		G_CALLBACK (mail_display_link_clicked), display);
-	g_signal_connect (web_view, "resource-request-starting",
-		G_CALLBACK (mail_display_resource_requested), display);
-	g_signal_connect (web_view, "window-object-cleared",
-		G_CALLBACK (mail_display_install_js_callbacks), display);
+	scrolled_window = GTK_SCROLLED_WINDOW (display);
+	gtk_scrolled_window_set_policy (scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (scrolled_window, GTK_SHADOW_NONE);
 
-	/* EWebView's action groups are added during its instance
-	 * initialization function (like what we're in now), so it
-	 * is safe to fetch them this early in construction. */
-	action_group = e_web_view_get_action_group (web_view, "mailto");
+	display->priv->vbox = gtk_vbox_new (FALSE, 0);
+	gtk_scrolled_window_add_with_viewport (scrolled_window, display->priv->vbox);
+	g_value_init (&margin, G_TYPE_INT);
+	g_value_set_int (&margin, 10);
+	g_object_set_property (G_OBJECT (display->priv->vbox), "margin", &margin);
 
-	/* We don't actually handle the actions we're adding.
-	 * EMailReader handles them.  How devious is that? */
-	gtk_action_group_add_actions (
-		action_group, mailto_entries,
-		G_N_ELEMENTS (mailto_entries), display);
 
-	/* Because we are loading from a hard-coded string, there is
-	 * no chance of I/O errors.  Failure here implies a malformed
-	 * UI definition.  Full stop. */
-	ui_manager = e_web_view_get_ui_manager (web_view);
-	gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
-	if (error != NULL)
-		g_error ("%s", error->message);
+	/* WEBKIT TODO: ESearchBar */
 
 
-	/* Register our own handler for mail:// protocol */
+	/* Register our own handler for our own mail:// protocol */
 	session = webkit_get_default_session ();
 	feature = SOUP_SESSION_FEATURE (soup_requester_new ());
 	soup_session_feature_add_feature (feature, E_TYPE_MAIL_REQUEST);
@@ -474,7 +540,7 @@ e_mail_display_get_type (void)
 		};
 
 		type = g_type_register_static (
-			E_TYPE_WEB_VIEW, "EMailDisplay", &type_info, 0);
+			GTK_TYPE_SCROLLED_WINDOW, "EMailDisplay", &type_info, 0);
 	}
 
 	return type;
@@ -504,3 +570,241 @@ e_mail_display_set_formatter (EMailDisplay *display,
 
 	g_object_notify (G_OBJECT (display), "formatter");
 }
+
+EMailDisplayMode
+e_mail_display_get_mode (EMailDisplay *display)
+{
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display),
+			E_MAIL_DISPLAY_MODE_NORMAL);
+
+	return display->priv->display_mode;
+}
+
+void
+e_mail_display_set_mode (EMailDisplay *display,
+			 EMailDisplayMode mode)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	if (display->priv->display_mode == mode)
+		return;
+
+	display->priv->display_mode = mode;
+	e_mail_display_reload (display);
+
+	g_object_notify (G_OBJECT (display), "display-mode");
+}
+
+void
+e_mail_display_load (EMailDisplay *display,
+		     const gchar *msg_uri)
+{
+	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));
+
+	/* First remove all widgets left after previous message */
+	e_mail_display_clear (display);
+
+	box = GTK_BOX (display->priv->vbox);
+
+	/* Headers webview */
+	web_view = mail_display_setup_webview (display);
+	display->widgets = g_list_append (display->widgets, GTK_WIDGET (web_view));
+	gtk_box_pack_start (box, GTK_WIDGET (web_view),
+			TRUE, TRUE, 0);
+	uri = em_format_build_mail_uri (emf->folder, emf->message_uid, "headers");
+	e_web_view_load_uri (web_view, uri);
+	g_free (uri);
+
+	/* Attachment bar */
+	puri = g_hash_table_lookup (emf->mail_part_table, "attachment-bar:");
+	if (puri && puri->widget_func) {
+		GtkWidget *widget = puri->widget_func (emf, puri, NULL);
+		display->widgets = g_list_append (display->widgets, widget);
+		gtk_box_pack_start (box, widget, TRUE, TRUE, 0);
+	}
+
+	for (iter = emf->mail_part_list; iter; iter = iter->next) {
+		puri = iter->data;
+		uri = em_format_build_mail_uri (emf->folder, emf->message_uid, puri->uri);
+
+		if (puri->widget_func && strcmp (puri->uri, "attachment-bar:") != 0) {
+			GtkWidget *widget;
+
+			widget = puri->widget_func (emf, puri, NULL);
+			if (!widget) {
+				g_message ("Part %s didn't provide a valid widget, skipping!", puri->uri);
+				continue;
+			}
+			display->widgets = g_list_append (display->widgets, widget);
+			gtk_box_pack_start (box, widget,
+					TRUE, TRUE, 0);
+
+		} else if (puri->write_func) {
+			web_view = mail_display_setup_webview (display);
+			display->widgets = g_list_append (display->widgets, GTK_WIDGET (web_view));
+			gtk_box_pack_start (box, GTK_WIDGET (web_view),
+					TRUE, TRUE, 0);
+			e_web_view_load_uri (web_view, uri);
+		}
+
+		g_free (uri);
+	}
+
+	gtk_widget_show_all (display->priv->vbox);
+}
+
+void
+e_mail_display_reload (EMailDisplay *display)
+{
+	GList *iter;
+
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	for (iter = display->widgets; iter; iter = iter->next) {
+		if (E_IS_WEB_VIEW (iter->data))
+			e_web_view_reload (E_WEB_VIEW (iter->data));
+	}
+}
+
+EWebView*
+e_mail_display_get_current_web_view (EMailDisplay *display)
+{
+	GtkWidget *widget;
+
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
+
+	widget = gtk_container_get_focus_child (GTK_CONTAINER (display));
+
+	if (E_IS_WEB_VIEW (widget))
+		return E_WEB_VIEW (widget);
+	else
+		return NULL;
+}
+
+void
+e_mail_display_set_status (EMailDisplay *display,
+			   const gchar *status)
+{
+	GtkWidget *label;
+
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	e_mail_display_clear (display);
+
+	label = gtk_label_new (status);
+	gtk_box_pack_start (GTK_BOX (display->priv->vbox), label, TRUE, TRUE, 0);
+	gtk_widget_show_all (display->priv->vbox);
+
+	display->widgets = g_list_append (display->widgets, label);
+}
+
+void
+e_mail_display_clear (EMailDisplay *display)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	gtk_widget_hide (display->priv->vbox);
+
+	g_list_free_full (display->widgets,
+			(GDestroyNotify) gtk_widget_destroy);
+	display->widgets = NULL;
+}
+
+ESearchBar*
+e_mail_display_get_search_bar (EMailDisplay *display)
+{
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
+
+	return display->priv->searchbar;
+}
+
+gboolean
+e_mail_display_is_selection_active (EMailDisplay *display)
+{
+	EWebView *web_view;
+
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
+
+	web_view = e_mail_display_get_current_web_view (display);
+	if (!web_view)
+		return FALSE;
+	else
+		return e_web_view_is_selection_active (web_view);
+}
+
+gchar*
+e_mail_display_get_selection_plain_text (EMailDisplay *display,
+					 gint *len)
+{
+	EWebView *web_view;
+	WebKitWebFrame *frame;
+	const gchar *frame_name;
+	GValue value = {0};
+	GType type;
+	const gchar *str;
+
+	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
+
+	web_view = e_mail_display_get_current_web_view (display);
+	if (!web_view)
+		return NULL;
+
+	frame = webkit_web_view_get_focused_frame (WEBKIT_WEB_VIEW (web_view));
+	frame_name = webkit_web_frame_get_name (frame);
+
+	type = e_web_view_frame_exec_script (web_view, frame_name, "window.getSelection().toString()", &value);
+	g_return_val_if_fail (type == G_TYPE_STRING, NULL);
+
+	str = g_value_get_string (&value);
+
+	if (len)
+		*len = strlen (str);
+
+	return g_strdup (str);
+}
+
+static void
+webview_action (GtkWidget *widget, WebViewActionFunc func)
+{
+	/*
+	 * It's not a critical error to pass other then EWebView
+	 * widgets.
+	 */
+	if (E_IS_WEB_VIEW (widget)) {
+		func (E_WEB_VIEW (widget));
+	}
+}
+
+void
+e_mail_display_zoom_100 (EMailDisplay *display)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	gtk_container_foreach (GTK_CONTAINER (display),
+			(GtkCallback) webview_action, e_web_view_zoom_100);
+}
+
+void
+e_mail_display_zoom_in (EMailDisplay *display)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	gtk_container_foreach (GTK_CONTAINER (display),
+			(GtkCallback) webview_action, e_web_view_zoom_in);
+}
+
+void
+e_mail_display_zoom_out (EMailDisplay *display)
+{
+	g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+	gtk_container_foreach (GTK_CONTAINER (display),
+			(GtkCallback) webview_action, e_web_view_zoom_out);
+}
diff --git a/mail/e-mail-display.h b/mail/e-mail-display.h
index fb3f29d..d81dd1b 100644
--- a/mail/e-mail-display.h
+++ b/mail/e-mail-display.h
@@ -23,6 +23,7 @@
 #define E_MAIL_DISPLAY_H
 
 #include <widgets/misc/e-web-view.h>
+#include <widgets/misc/e-search-bar.h>
 #include "em-format-html.h"
 
 /* Standard GObject macros */
@@ -50,19 +51,57 @@ 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 {
-	EWebView parent;
+	GtkScrolledWindow parent;
 	EMailDisplayPrivate *priv;
+
+	GtkWidget *headers;	/* EWebView */
+	GList *widgets;
 };
 
 struct _EMailDisplayClass {
-	EWebViewClass parent_class;
+	GtkScrolledWindowClass parent_class;
+
+	/* TODO WEBKIT: popup-event signal */
+	/* TODO WEBKIT: status-message signal */
 };
 
-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);
+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);
+void			e_mail_display_load		(EMailDisplay *display,
+						 	 const gchar *msg_uri);
+void			e_mail_display_reload		(EMailDisplay *display);
+
+EWebView *		e_mail_display_get_current_web_view
+							(EMailDisplay *display);
+
+void			e_mail_display_set_status	(EMailDisplay *display,
+							 const gchar *status);
+void			e_mail_display_clear		(EMailDisplay *display);
+
+ESearchBar*		e_mail_display_get_search_bar	(EMailDisplay *display);
+
+gboolean		e_mail_display_is_selection_active
+							(EMailDisplay *display);
+
+gchar*			e_mail_display_get_selection_plain_text
+							(EMailDisplay *display, gint *len);
+
+
+void			e_mail_display_zoom_100		(EMailDisplay *display);
+void			e_mail_display_zoom_in		(EMailDisplay *display);
+void			e_mail_display_zoom_out		(EMailDisplay *display);
 
 G_END_DECLS
 
diff --git a/mail/e-mail-notebook-view.c b/mail/e-mail-notebook-view.c
index c4e0ed3..1c90434 100644
--- a/mail/e-mail-notebook-view.c
+++ b/mail/e-mail-notebook-view.c
@@ -868,8 +868,8 @@ mail_notebook_view_get_backend (EMailReader *reader)
 	return E_MAIL_BACKEND (shell_backend);
 }
 
-static EMFormatHTML *
-mail_notebook_view_get_formatter (EMailReader *reader)
+static EMailDisplay *
+mail_notebook_view_get_mail_display (EMailReader *reader)
 {
 	EMailNotebookViewPrivate *priv;
 
@@ -878,7 +878,7 @@ mail_notebook_view_get_formatter (EMailReader *reader)
 	if (priv->current_view == NULL)
 		return NULL;
 
-	return e_mail_reader_get_formatter (E_MAIL_READER (priv->current_view));
+	return e_mail_reader_get_mail_display (E_MAIL_READER (priv->current_view));
 }
 
 static gboolean
@@ -1397,7 +1397,7 @@ e_mail_notebook_view_reader_init (EMailReaderInterface *interface)
 	interface->get_action_group = mail_notebook_view_get_action_group;
 	interface->get_alert_sink = mail_notebook_view_get_alert_sink;
 	interface->get_backend = mail_notebook_view_get_backend;
-	interface->get_formatter = mail_notebook_view_get_formatter;
+	interface->get_mail_display = mail_notebook_view_get_mail_display;
 	interface->get_hide_deleted = mail_notebook_view_get_hide_deleted;
 	interface->get_message_list = mail_notebook_view_get_message_list;
 	interface->get_popup_menu = mail_notebook_view_get_popup_menu;
diff --git a/mail/e-mail-paned-view.c b/mail/e-mail-paned-view.c
index 32c7996..b802a19 100644
--- a/mail/e-mail-paned-view.c
+++ b/mail/e-mail-paned-view.c
@@ -54,9 +54,8 @@ struct _EMailPanedViewPrivate {
 	GtkWidget *scrolled_window;
 	GtkWidget *message_list;
 	GtkWidget *search_bar;
-	GtkWidget *preview;
 
-	EMFormatHTMLDisplay *formatter;
+	EMailDisplay *display;
 	GalViewInstance *view_instance;
 
 	/* ETable scrolling hack */
@@ -350,9 +349,9 @@ mail_paned_view_dispose (GObject *object)
 		priv->search_bar = NULL;
 	}
 
-	if (priv->formatter != NULL) {
-		g_object_unref (priv->formatter);
-		priv->formatter = NULL;
+	if (priv->display != NULL) {
+		g_object_unref (priv->display);
+		priv->display = NULL;
 	}
 
 	if (priv->view_instance != NULL) {
@@ -419,14 +418,14 @@ mail_paned_view_get_backend (EMailReader *reader)
 	return E_MAIL_BACKEND (shell_backend);
 }
 
-static EMFormatHTML *
-mail_paned_view_get_formatter (EMailReader *reader)
+static EMailDisplay *
+mail_paned_view_get_mail_display (EMailReader *reader)
 {
 	EMailPanedViewPrivate *priv;
 
 	priv = E_MAIL_PANED_VIEW (reader)->priv;
 
-	return EM_FORMAT_HTML (priv->formatter);
+	return priv->display;
 }
 
 static gboolean
@@ -605,35 +604,30 @@ mail_paned_view_constructed (GObject *object)
 	EShellBackend *shell_backend;
 	EShellWindow *shell_window;
 	EShellView *shell_view;
-	EShell *shell;
-	EShellSettings *shell_settings;
 	ESearchBar *search_bar;
 	EMailReader *reader;
 	EMailView *view;
 	GtkWidget *message_list;
 	GtkWidget *container;
 	GtkWidget *widget;
-	EWebView *web_view;
 
 	priv = E_MAIL_PANED_VIEW (object)->priv;
-	priv->formatter = em_format_html_display_new ();
+
+	priv->display = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
 
 	view = E_MAIL_VIEW (object);
 	shell_view = e_mail_view_get_shell_view (view);
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	shell_backend = e_shell_view_get_shell_backend (shell_view);
-	shell = e_shell_window_get_shell (shell_window);
-	shell_settings = e_shell_get_shell_settings (shell);
 
 	/* Make headers collapsable and store state of headers in config file */
-	em_format_html_set_headers_collapsable (EM_FORMAT_HTML (priv->formatter), TRUE);
+	/* FIXME WEBKIT */
+	/*em_format_html_set_headers_collapsable (EM_FORMAT_HTML (priv->formatter), TRUE);
 	g_object_bind_property (shell_settings, "paned-view-headers-state",
 				EM_FORMAT_HTML (priv->formatter), "headers-state",
 				G_BINDING_BIDIRECTIONAL |
 				G_BINDING_SYNC_CREATE);
-
-	web_view = em_format_html_get_web_view (
-		EM_FORMAT_HTML (priv->formatter));
+	*/
 
 	/* Build content widgets. */
 
@@ -670,10 +664,9 @@ mail_paned_view_constructed (GObject *object)
 
 	container = priv->paned;
 
-	gtk_widget_show (GTK_WIDGET (web_view));
+	gtk_widget_show (GTK_WIDGET (priv->display));
 
-	widget = e_preview_pane_new (web_view);
-	priv->preview = widget;
+	widget = GTK_WIDGET (priv->display);
 	gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, FALSE);
 	gtk_widget_show (widget);
 
@@ -682,12 +675,15 @@ mail_paned_view_constructed (GObject *object)
 		widget, "visible",
 		G_BINDING_SYNC_CREATE);
 
-	search_bar = e_preview_pane_get_search_bar (E_PREVIEW_PANE (widget));
-	priv->search_bar = g_object_ref (search_bar);
+	/* FIXME WEBKIT: Searchbar!!! */
+	search_bar = e_mail_display_get_search_bar (priv->display);
+	if (search_bar) {
+		priv->search_bar = g_object_ref (search_bar);
 
-	g_signal_connect_swapped (
-		search_bar, "changed",
-		G_CALLBACK (e_web_view_reload), web_view);
+		g_signal_connect_swapped (
+				search_bar, "changed",
+				G_CALLBACK (e_mail_display_reload), priv->display);
+	}
 
 	/* Load the view instance. */
 
@@ -999,7 +995,7 @@ e_mail_paned_view_reader_init (EMailReaderInterface *interface)
 	interface->get_action_group = mail_paned_view_get_action_group;
 	interface->get_alert_sink = mail_paned_view_get_alert_sink;
 	interface->get_backend = mail_paned_view_get_backend;
-	interface->get_formatter = mail_paned_view_get_formatter;
+	interface->get_mail_display = mail_paned_view_get_mail_display;
 	interface->get_hide_deleted = mail_paned_view_get_hide_deleted;
 	interface->get_message_list = mail_paned_view_get_message_list;
 	interface->get_popup_menu = mail_paned_view_get_popup_menu;
@@ -1050,7 +1046,7 @@ e_mail_paned_view_get_preview (EMailPanedView *view)
 {
 	g_return_val_if_fail (E_IS_MAIL_PANED_VIEW (view), NULL);
 
-	return view->priv->preview;
+	return GTK_WIDGET (mail_paned_view_get_mail_display (E_MAIL_READER (view)));
 }
 
 void
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 0e14e64..ab34e2d 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -283,6 +283,7 @@ e_mail_reader_mark_as_read (EMailReader *reader,
 	EMailBackend *backend;
 	EMailSession *session;
 	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	CamelFolder *folder;
 	guint32 mask, set;
 	guint32 flags;
@@ -292,7 +293,8 @@ e_mail_reader_mark_as_read (EMailReader *reader,
 
 	folder = e_mail_reader_get_folder (reader);
 	backend = e_mail_reader_get_backend (reader);
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
+	formatter = e_mail_display_get_formatter (display);
 
 	session = e_mail_backend_get_session (backend);
 
@@ -434,7 +436,8 @@ e_mail_reader_open_selected (EMailReader *reader)
 		const gchar *uid = views->pdata[ii];
 		GtkWidget *browser;
 
-		browser = e_mail_browser_new (backend);
+		browser = e_mail_browser_new (backend, folder, uid,
+				E_MAIL_DISPLAY_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));
@@ -460,6 +463,7 @@ mail_reader_print_cb (CamelFolder *folder,
 {
 	EAlertSink *alert_sink;
 	CamelMimeMessage *message;
+	EMailDisplay *display;
 	EMFormatHTML *formatter;
 	EMFormatHTMLPrint *html_print;
 	GError *error = NULL;
@@ -486,12 +490,15 @@ mail_reader_print_cb (CamelFolder *folder,
 
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
-	formatter = e_mail_reader_get_formatter (context->reader);
+	display = e_mail_reader_get_mail_display (context->reader);
+	formatter = e_mail_display_get_formatter (display);
 
 	html_print = em_format_html_print_new (
 		formatter, context->print_action);
+	/* FIXME WEBKIT
 	em_format_merge_handler (
 		EM_FORMAT (html_print), EM_FORMAT (formatter));
+	*/
 	em_format_html_print_message (
 		html_print, message, folder, context->message_uid);
 	g_object_unref (html_print);
@@ -784,6 +791,7 @@ e_mail_reader_reply_to_message (EMailReader *reader,
 	EShell *shell;
 	EMailBackend *backend;
 	EShellBackend *shell_backend;
+	EMailDisplay *display;
 	EMFormatHTML *formatter;
 	GtkWidget *message_list;
 	CamelMimeMessage *new_message;
@@ -804,14 +812,15 @@ e_mail_reader_reply_to_message (EMailReader *reader,
 
 	backend = e_mail_reader_get_backend (reader);
 	folder = e_mail_reader_get_folder (reader);
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
+	formatter = e_mail_display_get_formatter (display);
 	message_list = e_mail_reader_get_message_list (reader);
 	reply_style = e_mail_reader_get_reply_style (reader);
 
 	shell_backend = E_SHELL_BACKEND (backend);
 	shell = e_shell_backend_get_shell (shell_backend);
 
-	web_view = em_format_html_get_web_view (formatter);
+	web_view = e_mail_display_get_current_web_view (display);
 
 	if (reply_type == E_MAIL_REPLY_TO_RECIPIENT) {
 		const gchar *uri;
@@ -1337,18 +1346,23 @@ headers_changed_cb (GConfClient *client,
                     GConfEntry *entry,
                     EMailReader *reader)
 {
+	EMailDisplay *display;
 	EMFormatHTML *formatter;
-	EWebView *web_view;
 	GSList *header_config_list, *p;
 
 	g_return_if_fail (client != NULL);
 	g_return_if_fail (reader != NULL);
 
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
+	formatter = e_mail_display_get_formatter (display);
+
+	if (!formatter)
+		return;
 
 	header_config_list = gconf_client_get_list (
 		client, "/apps/evolution/mail/display/headers",
 		GCONF_VALUE_STRING, NULL);
+	/* FIXME WEBKIT
 	em_format_clear_headers (EM_FORMAT (formatter));
 	for (p = header_config_list; p; p = g_slist_next (p)) {
 		EMailReaderHeader *h;
@@ -1368,11 +1382,11 @@ headers_changed_cb (GConfClient *client,
 
 	g_slist_foreach (header_config_list, (GFunc) g_free, NULL);
 	g_slist_free (header_config_list);
+	*/
 
 	/* force a redraw */
 	if (EM_FORMAT (formatter)->message) {
-		web_view = em_format_html_get_web_view (formatter);
-		e_web_view_reload (web_view);
+		e_mail_display_reload (display);
 	}
 }
 
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index d185e1f..538dc7f 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -43,13 +43,13 @@
 
 #include "mail/e-mail-backend.h"
 #include "mail/e-mail-browser.h"
-#include "mail/e-mail-display.h"
 #include "mail/e-mail-enumtypes.h"
 #include "mail/e-mail-reader-utils.h"
 #include "mail/em-composer-utils.h"
 #include "mail/em-event.h"
 #include "mail/em-folder-selector.h"
 #include "mail/em-folder-tree.h"
+#include "mail/em-format-html-display.h"
 #include "mail/em-utils.h"
 #include "mail/mail-autofilter.h"
 #include "mail/mail-ops.h"
@@ -195,9 +195,9 @@ action_add_to_address_book_cb (GtkAction *action,
 	EShell *shell;
 	EMailBackend *backend;
 	EShellBackend *shell_backend;
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	CamelInternetAddress *cia;
-	EWebView *web_view;
+	GtkWidget *web_view;
 	CamelURL *curl;
 	const gchar *uri;
 	gchar *email;
@@ -205,11 +205,13 @@ action_add_to_address_book_cb (GtkAction *action,
 	/* This action is defined in EMailDisplay. */
 
 	backend = e_mail_reader_get_backend (reader);
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
 
-	web_view = em_format_html_get_web_view (formatter);
+	web_view = gtk_container_get_focus_child (GTK_CONTAINER  (display));
+	if (!E_IS_WEB_VIEW (web_view))
+		return;
 
-	uri = e_web_view_get_selected_uri (web_view);
+	uri = e_web_view_get_selected_uri (E_WEB_VIEW (web_view));
 	g_return_if_fail (uri != NULL);
 
 	curl = camel_url_new (uri, NULL);
@@ -245,17 +247,20 @@ action_mail_charset_cb (GtkRadioAction *action,
                         GtkRadioAction *current,
                         EMailReader *reader)
 {
+	EMailDisplay *display;
 	EMFormatHTML *formatter;
 	const gchar *charset;
 
 	if (action != current)
 		return;
 
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
+	formatter = e_mail_display_get_formatter (display);
 	charset = g_object_get_data (G_OBJECT (action), "charset");
 
 	/* Charset for "Default" action will be NULL. */
-	em_format_set_charset (EM_FORMAT (formatter), charset);
+	if (formatter)
+		em_format_set_charset (EM_FORMAT (formatter), charset);
 }
 
 static void
@@ -428,42 +433,38 @@ static void
 action_mail_flag_clear_cb (GtkAction *action,
                            EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 	CamelFolder *folder;
 	GtkWindow *window;
 	GPtrArray *uids;
 
 	folder = e_mail_reader_get_folder (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 	uids = e_mail_reader_get_selected_uids (reader);
 	window = e_mail_reader_get_window (reader);
 
 	em_utils_flag_for_followup_clear (window, folder, uids);
 
-	e_web_view_reload (web_view);
+	e_mail_display_reload (display);
 }
 
 static void
 action_mail_flag_completed_cb (GtkAction *action,
                                EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 	CamelFolder *folder;
 	GtkWindow *window;
 	GPtrArray *uids;
 
 	folder = e_mail_reader_get_folder (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 	uids = e_mail_reader_get_selected_uids (reader);
 	window = e_mail_reader_get_window (reader);
 
 	em_utils_flag_for_followup_completed (window, folder, uids);
 
-	e_web_view_reload (web_view);
+	e_mail_display_reload (display);
 }
 
 static void
@@ -648,9 +649,11 @@ static void
 action_mail_load_images_cb (GtkAction *action,
                             EMailReader *reader)
 {
+	EMailDisplay *display;
 	EMFormatHTML *formatter;
 
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
+	formatter = e_mail_display_get_formatter (display);
 
 	em_format_html_load_images (formatter);
 }
@@ -1552,20 +1555,14 @@ static void
 action_mail_show_all_headers_cb (GtkToggleAction *action,
                                  EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EMFormatMode mode;
+	EMailDisplay *display;
 
-	formatter = e_mail_reader_get_formatter (reader);
-
-	if (!formatter)
-		return;
+	display = e_mail_reader_get_mail_display (reader);
 
 	if (gtk_toggle_action_get_active (action))
-		mode = EM_FORMAT_MODE_ALLHEADERS;
+		e_mail_display_set_mode (display, E_MAIL_DISPLAY_MODE_ALL_HEADERS);
 	else
-		mode = EM_FORMAT_MODE_NORMAL;
-
-	em_format_set_mode (EM_FORMAT (formatter), mode);
+		e_mail_display_set_mode (display, E_MAIL_DISPLAY_MODE_NORMAL);
 }
 
 static void
@@ -1573,7 +1570,7 @@ action_mail_show_source_cb (GtkAction *action,
                             EMailReader *reader)
 {
 	EMailBackend *backend;
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	CamelFolder *folder;
 	GtkWidget *browser;
 	GPtrArray *uids;
@@ -1581,21 +1578,15 @@ action_mail_show_source_cb (GtkAction *action,
 
 	backend = e_mail_reader_get_backend (reader);
 	folder = e_mail_reader_get_folder (reader);
+	display = e_mail_reader_get_mail_display (reader);
 
 	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);
-	reader = E_MAIL_READER (browser);
-	formatter = e_mail_reader_get_formatter (reader);
-
-	if (formatter != NULL)
-		em_format_set_mode (
-			EM_FORMAT (formatter), EM_FORMAT_MODE_SOURCE);
+	browser = e_mail_browser_new (backend, folder, message_uid,
+			E_MAIL_DISPLAY_MODE_SOURCE);
 
-	e_mail_reader_set_folder (reader, folder);
-	e_mail_reader_set_message (reader, message_uid);
 	gtk_widget_show (browser);
 
 	em_utils_uids_free (uids);
@@ -1647,39 +1638,33 @@ static void
 action_mail_zoom_100_cb (GtkAction *action,
                          EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 
-	e_web_view_zoom_100 (web_view);
+	e_mail_display_zoom_100 (display);
 }
 
 static void
 action_mail_zoom_in_cb (GtkAction *action,
                         EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 
-	e_web_view_zoom_in (web_view);
+	e_mail_display_zoom_in (display);
 }
 
 static void
 action_mail_zoom_out_cb (GtkAction *action,
                          EMailReader *reader)
 {
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 
-	e_web_view_zoom_out (web_view);
+	e_mail_display_zoom_out (display);
 }
 
 static void
@@ -1688,7 +1673,7 @@ action_search_folder_recipient_cb (GtkAction *action,
 {
 	EMailBackend *backend;
 	EMailSession *session;
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	EWebView *web_view;
 	CamelFolder *folder;
 	CamelURL *curl;
@@ -1697,9 +1682,8 @@ action_search_folder_recipient_cb (GtkAction *action,
 	/* This action is defined in EMailDisplay. */
 
 	folder = e_mail_reader_get_folder (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
+	web_view = e_mail_display_get_current_web_view (display);
 
 	uri = e_web_view_get_selected_uri (web_view);
 	g_return_if_fail (uri != NULL);
@@ -1729,7 +1713,7 @@ action_search_folder_sender_cb (GtkAction *action,
 {
 	EMailBackend *backend;
 	EMailSession *session;
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	EWebView *web_view;
 	CamelFolder *folder;
 	CamelURL *curl;
@@ -1738,9 +1722,8 @@ action_search_folder_sender_cb (GtkAction *action,
 	/* This action is defined in EMailDisplay. */
 
 	folder = e_mail_reader_get_folder (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
+	web_view = e_mail_display_get_current_web_view (display);
 
 	uri = e_web_view_get_selected_uri (web_view);
 	g_return_if_fail (uri != NULL);
@@ -2490,15 +2473,16 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
                                EMailReaderClosure *closure)
 {
 	EMailReader *reader;
+	EMailDisplay *display;
 	EMailReaderPrivate *priv;
 	CamelMimeMessage *message = NULL;
-	EMFormatHTML *formatter;
 	GtkWidget *message_list;
 	EMailBackend *backend;
 	EShellBackend *shell_backend;
 	EShellSettings *shell_settings;
 	EShell *shell;
 	EWebView *web_view;
+	EMFormatHTMLDisplay *formatter;
 	EMEvent *event;
 	EMEventTargetMessage *target;
 	const gchar *message_uid;
@@ -2506,6 +2490,7 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
 	gboolean schedule_timeout;
 	gint timeout_interval;
 	GError *error = NULL;
+	SoupSession *session;
 
 	reader = closure->reader;
 	message_uid = closure->message_uid;
@@ -2530,9 +2515,8 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
 	}
 
 	backend = e_mail_reader_get_backend (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
 	message_list = e_mail_reader_get_message_list (reader);
+	display = e_mail_reader_get_mail_display (reader);
 
 	if (!message_list) {
 		/* for cases where message fetching took so long that
@@ -2544,8 +2528,6 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
 	shell = e_shell_backend_get_shell (shell_backend);
 	shell_settings = e_shell_get_shell_settings (shell);
 
-	web_view = em_format_html_get_web_view (formatter);
-
 	/** @Event: message.reading
 	 * @Title: Viewing a message
 	 * @Target: EMEventTargetMessage
@@ -2559,13 +2541,18 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
 		(EEvent *) event, "message.reading",
 		(EEventTarget *) target);
 
+	mail_uri = em_format_build_mail_uri (folder, message_uid, NULL);
 
-	/* Initialize formatter */
-	em_format_format_clone (EM_FORMAT (formatter), folder, message_uid, message, NULL, NULL);
+	session = webkit_get_default_session ();
+	if ((formatter = g_object_get_data (G_OBJECT (session), mail_uri)) == NULL) {
+		formatter = em_format_html_display_new ();
+		EM_FORMAT (formatter)->message_uid = g_strdup (message_uid);
+		em_format_parse (EM_FORMAT (formatter), message, folder, NULL);
+		g_object_set_data (G_OBJECT (session), mail_uri, formatter);
+	}
 
-	/* Start formatting */
-	mail_uri = em_format_build_mail_uri (folder, message_uid, NULL, EM_FORMAT (formatter));
-	e_web_view_load_uri (web_view, mail_uri);
+	e_mail_display_set_formatter (display, EM_FORMAT_HTML (formatter));
+	e_mail_display_load (display, mail_uri);
 	g_free (mail_uri);
 
 	/* Reset the shell view icon. */
@@ -2600,10 +2587,12 @@ mail_reader_message_loaded_cb (CamelFolder *folder,
 			mail_reader_closure_free);
 
 	} else if (error != NULL) {
+		/* FIXME WEBKIT
 		e_alert_submit (
 			E_ALERT_SINK (web_view),
 			"mail:no-retrieve-message",
 			error->message, NULL);
+		*/
 		g_error_free (error);
 	}
 
@@ -2620,9 +2609,8 @@ static gboolean
 mail_reader_message_selected_timeout_cb (EMailReader *reader)
 {
 	EMailReaderPrivate *priv;
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	GtkWidget *message_list;
-	EWebView *web_view;
 	CamelFolder *folder;
 	const gchar *cursor_uid;
 	const gchar *format_uid;
@@ -2631,49 +2619,35 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
 
 	folder = e_mail_reader_get_folder (reader);
 
-	formatter = e_mail_reader_get_formatter (reader);
 	message_list = e_mail_reader_get_message_list (reader);
+	display = e_mail_reader_get_mail_display (reader);
 
 	cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
-	format_uid = EM_FORMAT (formatter)->uid;
-
-	web_view = em_format_html_get_web_view (formatter);
+	//format_uid = EM_FORMAT (formatter)->message_uid;
 
 	if (MESSAGE_LIST (message_list)->last_sel_single) {
 		GtkWidget *widget;
-		gboolean web_view_visible;
+		gboolean display_visible;
 		gboolean selected_uid_changed;
 
 		/* Decide whether to download the full message now. */
+		widget = GTK_WIDGET (display);
 
-		widget = GTK_WIDGET (web_view);
+		display_visible = gtk_widget_get_mapped (widget);
 
-		web_view_visible = gtk_widget_get_mapped (widget);
-		selected_uid_changed = g_strcmp0 (cursor_uid, format_uid);
+		/* FIXME WEBKIT */
+		//selected_uid_changed = g_strcmp0 (cursor_uid, format_uid);
 
-		if (web_view_visible && selected_uid_changed) {
+		//if (display_visible && selected_uid_changed) {
+		if (display_visible) {
 			EMailReaderClosure *closure;
 			GCancellable *cancellable;
 			EActivity *activity;
-			gchar *string, *html;
+			gchar *string;
 
-			string = g_strdup_printf (
-				_("Retrieving message '%s'"), cursor_uid);
-
-			html = g_strdup_printf ("<html><head></head><body>"
-						"<table width=\"100%%\" height=\"100%%\"><tr>"
-						"<td valign=\"middle\" align=\"center\"><h5>%s</h5></td>"
-						"</tr></table>"
-						"</body></html>",
-						string);
-#if HAVE_CLUTTER
-			if (!e_shell_get_express_mode (e_shell_get_default ()))
-				e_web_view_load_string (web_view, html);
-#else
-			e_web_view_load_string (web_view, html);
-#endif
+			string = g_strdup_printf (_("Retrieving message '%s'"), cursor_uid);
+			e_mail_display_set_status (display, string);
 			g_free (string);
-			g_free (html);
 
 			activity = e_mail_reader_new_activity (reader);
 			cancellable = e_activity_get_cancellable (activity);
@@ -2693,8 +2667,6 @@ mail_reader_message_selected_timeout_cb (EMailReader *reader)
 			priv->retrieving_message = g_object_ref (cancellable);
 		}
 	} else {
-		e_web_view_load_string (web_view, "");
-
 		priv->restoring_message_selection = FALSE;
 	}
 
@@ -2784,8 +2756,7 @@ mail_reader_set_folder (EMailReader *reader,
                         CamelFolder *folder)
 {
 	EMailReaderPrivate *priv;
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 	CamelFolder *previous_folder;
 	GtkWidget *message_list;
 	EMailBackend *backend;
@@ -2795,8 +2766,7 @@ mail_reader_set_folder (EMailReader *reader,
 	priv = E_MAIL_READER_GET_PRIVATE (reader);
 
 	backend = e_mail_reader_get_backend (reader);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
 	message_list = e_mail_reader_get_message_list (reader);
 
 	previous_folder = e_mail_reader_get_folder (reader);
@@ -2816,7 +2786,7 @@ mail_reader_set_folder (EMailReader *reader,
 		em_utils_folder_is_outbox (folder) ||
 		em_utils_folder_is_sent (folder));
 
-	e_web_view_load_string (web_view, "");
+	e_mail_display_clear (display);
 
 	priv->folder_was_just_selected = (folder != NULL);
 
@@ -3377,9 +3347,7 @@ e_mail_reader_init (EMailReader *reader,
                     gboolean init_actions,
                     gboolean connect_signals)
 {
-	EMFormatHTML *formatter;
 	EMenuToolAction *menu_tool_action;
-	EWebView *web_view;
 	GtkActionGroup *action_group;
 	GtkWidget *message_list;
 	GConfBridge *bridge;
@@ -3394,11 +3362,8 @@ e_mail_reader_init (EMailReader *reader,
 
 	g_return_if_fail (E_IS_MAIL_READER (reader));
 
-	formatter = e_mail_reader_get_formatter (reader);
 	message_list = e_mail_reader_get_message_list (reader);
 
-	web_view = em_format_html_get_web_view (formatter);
-
 	if (!init_actions)
 		goto connect_signals;
 
@@ -3533,6 +3498,7 @@ e_mail_reader_init (EMailReader *reader,
 	gtk_action_set_is_important (action, TRUE);
 	gtk_action_set_short_label (action, _("Reply"));
 
+	/* FIXME WEBKIT
 	action_name = "add-to-address-book";
 	action = e_web_view_get_action (web_view, action_name);
 	g_signal_connect (
@@ -3556,7 +3522,7 @@ e_mail_reader_init (EMailReader *reader,
 	g_signal_connect (
 		action, "activate",
 		G_CALLBACK (action_search_folder_sender_cb), reader);
-
+	*/
 #ifndef G_OS_WIN32
 	/* Lockdown integration. */
 
@@ -3597,21 +3563,24 @@ e_mail_reader_init (EMailReader *reader,
 	action_name = "mail-caret-mode";
 	action = e_mail_reader_get_action (reader, action_name);
 
+	/* FIXME WEBKIT
 	g_object_bind_property (
 		action, "active",
 		web_view, "caret-mode",
 		G_BINDING_BIDIRECTIONAL |
 		G_BINDING_SYNC_CREATE);
-
+	*/
 connect_signals:
 
 	if (!connect_signals)
 		goto init_private;
 
 	/* Connect signals. */
+	/* WEBKIT FIXME
 	g_signal_connect_swapped (
 		web_view, "key-press-event",
 		G_CALLBACK (mail_reader_key_press_event_cb), reader);
+	 */
 
 	g_signal_connect_swapped (
 		message_list, "message-selected",
@@ -3917,17 +3886,17 @@ e_mail_reader_get_backend (EMailReader *reader)
 	return interface->get_backend (reader);
 }
 
-EMFormatHTML *
-e_mail_reader_get_formatter (EMailReader *reader)
+EMailDisplay *
+e_mail_reader_get_mail_display (EMailReader *reader)
 {
 	EMailReaderInterface *interface;
 
 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
 
 	interface = E_MAIL_READER_GET_INTERFACE (reader);
-	g_return_val_if_fail (interface->get_formatter != NULL, NULL);
+	g_return_val_if_fail (interface->get_mail_display != NULL, NULL);
 
-	return interface->get_formatter (reader);
+	return interface->get_mail_display (reader);
 }
 
 gboolean
diff --git a/mail/e-mail-reader.h b/mail/e-mail-reader.h
index f4df175..95a3b21 100644
--- a/mail/e-mail-reader.h
+++ b/mail/e-mail-reader.h
@@ -31,7 +31,7 @@
 #include <camel/camel.h>
 #include <e-util/e-alert-sink.h>
 #include <mail/e-mail-backend.h>
-#include <mail/em-format-html.h>
+#include <mail/e-mail-display.h>
 
 /* Standard GObject macros */
 #define E_TYPE_MAIL_READER \
@@ -95,7 +95,7 @@ struct _EMailReaderInterface {
 						 EMailReaderActionGroup group);
 	EAlertSink *	(*get_alert_sink)	(EMailReader *reader);
 	EMailBackend *	(*get_backend)		(EMailReader *reader);
-	EMFormatHTML *	(*get_formatter)	(EMailReader *reader);
+	EMailDisplay *	(*get_mail_display)	(EMailReader *reader);
 	gboolean	(*get_hide_deleted)	(EMailReader *reader);
 	GtkWidget *	(*get_message_list)	(EMailReader *reader);
 	GtkMenu *	(*get_popup_menu)	(EMailReader *reader);
@@ -132,7 +132,7 @@ GtkActionGroup *
 						 EMailReaderActionGroup group);
 EAlertSink *	e_mail_reader_get_alert_sink	(EMailReader *reader);
 EMailBackend *	e_mail_reader_get_backend	(EMailReader *reader);
-EMFormatHTML *	e_mail_reader_get_formatter	(EMailReader *reader);
+EMailDisplay *	e_mail_reader_get_mail_display	(EMailReader *reader);
 gboolean	e_mail_reader_get_hide_deleted	(EMailReader *reader);
 GtkWidget *	e_mail_reader_get_message_list	(EMailReader *reader);
 guint		e_mail_reader_open_selected_mail
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index eb7c694..b4f7576 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -7,6 +7,7 @@
 
 #include "em-format-html.h"
 
+#define d(x)
 
 G_DEFINE_TYPE (EMailRequest, e_mail_request, SOUP_TYPE_REQUEST)
 
@@ -16,11 +17,22 @@ struct _EMailRequestPrivate {
 
 	CamelStream *output_stream;
 
-	gchar *content_type;
+	CamelContentType *content_type;
+	gchar *mime_type;
 
 	GHashTable *uri_query;
 };
 
+static void
+mail_request_set_content_type (EMailRequest *emr,
+			       CamelContentType *ct)
+{
+	if (emr->priv->content_type)
+		camel_content_type_unref (emr->priv->content_type);
+
+	emr->priv->content_type = ct;
+	camel_content_type_ref (emr->priv->content_type);
+}
 
 static void
 start_mail_formatting (GSimpleAsyncResult *res,
@@ -45,25 +57,23 @@ start_mail_formatting (GSimpleAsyncResult *res,
 	part_id = g_hash_table_lookup (request->priv->uri_query, "part_id");
 
 	if (part_id) {
-		CamelContentType *ct;
-		EMFormatPURI *puri;
-
-		puri = em_format_find_puri (emf, part_id);
-		if (puri) {
-			request->priv->part = puri->part;
-			ct = camel_mime_part_get_content_type (request->priv->part);
-			if (ct) {
-				request->priv->content_type = camel_content_type_format (ct);
-			camel_content_type_unref (ct);
+		gboolean all_headers = GPOINTER_TO_INT (g_hash_table_lookup (
+				request->priv->uri_query, "all-headers"));
+
+		if (strcmp (part_id, "headers") == 0) {
+			em_format_html_format_headers (efh, request->priv->output_stream,
+				CAMEL_MEDIUM (emf->message), all_headers, cancellable);
+		} else {
+			EMFormatPURI *puri = g_hash_table_lookup (emf->mail_part_table, part_id);
+			if (puri) {
+				em_format_puri_write (puri, request->priv->output_stream, NULL);
 			} else {
-				request->priv->content_type = g_strdup ("text/html");
+				g_warning ("Failed to lookup requested part '%s' - this should not happen!", part_id);
 			}
-			em_format_html_format_message_part (efh, part_id, request->priv->output_stream, cancellable);
+
+			mail_request_set_content_type (request,
+					camel_mime_part_get_content_type (puri->part));
 		}
-	} else {
-		request->priv->content_type = g_strdup ("text/html");
-		request->priv->part = g_object_ref (CAMEL_MIME_PART (emf->message));
-		em_format_html_format_message (efh, request->priv->output_stream, cancellable);
 	}
 
 	/* Convert the GString to GInputStream and send it back to WebKit */
@@ -96,7 +106,12 @@ get_image_content (GSimpleAsyncResult *res,
 	uri = soup_request_get_uri (SOUP_REQUEST (request));
 
 	if (g_file_get_contents (uri->path, &contents, &length, NULL)) {
-		request->priv->content_type = g_content_type_guess (uri->path, NULL, 0, NULL);
+		CamelContentType *ct;
+		gchar *mime_type = g_content_type_guess (uri->path, NULL, 0, NULL);
+		ct = camel_content_type_decode (mime_type);
+		mail_request_set_content_type (request, ct);
+		camel_content_type_unref (ct);
+
 		stream = g_memory_input_stream_new_from_data (contents, length, NULL);
 		g_simple_async_result_set_op_res_gpointer (res, stream, NULL);
 	}
@@ -125,10 +140,15 @@ mail_request_finalize (GObject *object)
 	}
 
 	if (request->priv->content_type) {
-		g_free (request->priv->content_type);
+		camel_content_type_unref (request->priv->content_type);
 		request->priv->content_type = NULL;
 	}
 
+	if (request->priv->mime_type) {
+		g_free (request->priv->mime_type);
+		request->priv->mime_type = NULL;
+	}
+
 	if (request->priv->uri_query) {
 		g_hash_table_destroy (request->priv->uri_query);
 		request->priv->uri_query = NULL;
@@ -152,26 +172,34 @@ mail_request_send_async (SoupRequest *request,
 			 GAsyncReadyCallback callback,
 			 gpointer	user_data)
 {
+	SoupSession *session;
 	EMailRequest *emr = E_MAIL_REQUEST (request);
 	GSimpleAsyncResult *result;
 	SoupURI *uri;
 
+	session = soup_request_get_session (request);
 	uri = soup_request_get_uri (request);
-
 	if (g_strcmp0 (uri->scheme, "mail") == 0) {
-		gchar *formatter;
-		emr->priv->uri_query = soup_form_decode (uri->query);
+		gchar *uri_str;
+
+		if (!uri->query) {
+			g_warning ("No query in URI %s", soup_uri_to_string (uri, FALSE));
+			g_return_if_fail (uri->query);
+		}
 
-		formatter = g_hash_table_lookup (emr->priv->uri_query, "formatter");
+		/* 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 = GINT_TO_POINTER (atoi (formatter));
-		g_return_if_fail (EM_IS_FORMAT (emr->priv->efh));
+		emr->priv->efh = g_object_get_data (G_OBJECT (session), uri_str);
+		g_free (uri_str);
+		g_return_if_fail (emr->priv->efh);
 
+		emr->priv->uri_query = soup_form_decode (uri->query);
 		result = g_simple_async_result_new (G_OBJECT (request), callback, user_data, mail_request_send_async);
 		g_simple_async_result_run_in_thread (result, start_mail_formatting, G_PRIORITY_DEFAULT, cancellable);
 	} else if (g_strcmp0 (uri->scheme, "evo-file") == 0) {
 		/* WebKit won't allow us to load data through local file:// protocol, when using "remote" mail://
-		   protocol. evo-file:// behaves as file:// */
+		   protocol, so we have evo-file:// which WebKit thinks it's remote, but in fact it behaves like file:// */
 		result = g_simple_async_result_new (G_OBJECT (request), callback, user_data, mail_request_send_async);
 		g_simple_async_result_run_in_thread (result, get_image_content, G_PRIORITY_DEFAULT, cancellable);
 	}
@@ -195,15 +223,17 @@ mail_request_get_content_length (SoupRequest *request)
 {
 	EMailRequest *emr = E_MAIL_REQUEST (request);
 	GByteArray *ba;
+	gint content_length = 0;
 
 	if (emr->priv->output_stream) {
 		ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (emr->priv->output_stream));
 		if (ba) {
-			return ba->len;
+			content_length = ba->len;
 		}
 	}
 
-	return 0;
+	d(printf("Content-Length: %d bytes", content_length));
+	return content_length;
 }
 
 static const gchar*
@@ -211,7 +241,31 @@ mail_request_get_content_type (SoupRequest *request)
 {
 	EMailRequest *emr = E_MAIL_REQUEST (request);
 
-	return emr->priv->content_type;
+	if (emr->priv->mime_type)
+		g_free (emr->priv->mime_type);
+
+	if (emr->priv->content_type == NULL) {
+		emr->priv->mime_type = g_strdup ("text/html");
+
+	/* For text/html return native content type, since it can contain
+	 * informations about charset
+	 */
+	} else if (camel_content_type_is (emr->priv->content_type, "text", "html")) {
+		emr->priv->mime_type = camel_content_type_format (emr->priv->content_type);
+
+	/* For any other text/* content type, return text/html, because we
+	 * have converted it from whatever type it was to HTML */
+	} else if (camel_content_type_is (emr->priv->content_type, "text", "*")) {
+		emr->priv->mime_type = g_strdup ("text/html");
+
+	/* For any other format return it's native format, because then it is
+	 * most probably image or something similar	 */
+	} else {
+		emr->priv->mime_type = camel_content_type_format (emr->priv->content_type);
+	}
+
+	d(printf("Content-Type: %s\n", emr->priv->mime_type));
+	return emr->priv->mime_type;
 }
 
 static const char *data_schemes[] = { "mail", "evo-file", NULL };
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 98ceea6..0be0c06 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -393,8 +393,7 @@ em_utils_flag_for_followup (EMailReader *reader,
 	EMailBackend *backend;
 	EShellSettings *shell_settings;
 	EShellBackend *shell_backend;
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 	GtkWidget *editor;
 	GtkWindow *window;
 	CamelTag *tags;
@@ -484,9 +483,8 @@ em_utils_flag_for_followup (EMailReader *reader,
 	camel_folder_thaw (folder);
 	camel_tag_list_free (&tags);
 
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
-	e_web_view_reload (web_view);
+	display = e_mail_reader_get_mail_display (reader);
+	e_mail_display_reload (display);
 
 exit:
 	/* XXX We shouldn't be freeing this. */
@@ -1326,7 +1324,7 @@ em_utils_message_to_html (CamelMimeMessage *message,
 	camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (mem), buf);
 
 	emfq = em_format_quote_new (credits, mem, flags);
-	((EMFormat *) emfq)->composer = TRUE;
+	em_format_set_composer ((EMFormat *) emfq, TRUE);
 
 	if (!source) {
 		GConfClient *gconf;
@@ -1343,11 +1341,12 @@ em_utils_message_to_html (CamelMimeMessage *message,
 	}
 
 	/* FIXME Not passing a GCancellable here. */
-	em_format_format_clone (
-		EM_FORMAT (emfq), NULL, NULL, message, source, NULL);
+	em_format_parse (EM_FORMAT (emfq), message, NULL, NULL);
+	/* FIXME WEBKIT The validity is now per-part, not global :(
 	if (validity_found)
-		*validity_found = ((EMFormat *)emfq)->validity_found;
+		*validity_found = ((EMFormat *)emfq)->validity_type;
 	g_object_unref (emfq);
+	*/
 
 	if (append && *append)
 		camel_stream_write_string (mem, append, NULL, NULL);
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index cc75844..f19eb3c 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -713,11 +713,12 @@ mbox_create_preview_cb (GObject *preview, GtkWidget **preview_widget)
 	g_return_if_fail (preview != NULL);
 	g_return_if_fail (preview_widget != NULL);
 
+	/* FIXME WEBKIT
 	format = em_format_html_display_new ();
 	g_object_set_data_full (
 		preview, "mbox-imp-formatter", format, g_object_unref);
 	web_view = em_format_html_get_web_view (EM_FORMAT_HTML (format));
-
+*/
 	*preview_widget = GTK_WIDGET (web_view);
 }
 
@@ -733,5 +734,7 @@ mbox_fill_preview_cb (GObject *preview, CamelMimeMessage *msg)
 	g_return_if_fail (format != NULL);
 
 	/* FIXME Not passing a GCancellable here. */
+	/* FIXME WEBKIT
 	em_format_format (EM_FORMAT (format), NULL, NULL, msg, NULL);
+	*/
 }
diff --git a/modules/mail/e-mail-shell-content.c b/modules/mail/e-mail-shell-content.c
index 9fd7d3b..519bf60 100644
--- a/modules/mail/e-mail-shell-content.c
+++ b/modules/mail/e-mail-shell-content.c
@@ -306,18 +306,18 @@ mail_shell_content_get_backend (EMailReader *reader)
 	return e_mail_reader_get_backend (reader);
 }
 
-static EMFormatHTML *
-mail_shell_content_get_formatter (EMailReader *reader)
+static EMailDisplay *
+mail_shell_content_get_mail_display(EMailReader *reader)
 {
 	EMailShellContentPrivate *priv;
+	EMailDisplay *display;
 
 	priv = E_MAIL_SHELL_CONTENT (reader)->priv;
 
 	/* Forward this to our internal EMailView, which
 	 * also implements the EMailReader interface. */
 	reader = E_MAIL_READER (priv->mail_view);
-
-	return e_mail_reader_get_formatter (reader);
+	return e_mail_reader_get_mail_display (reader);
 }
 
 static gboolean
@@ -476,7 +476,7 @@ mail_shell_content_reader_init (EMailReaderInterface *interface)
 	interface->get_action_group = mail_shell_content_get_action_group;
 	interface->get_alert_sink = mail_shell_content_get_alert_sink;
 	interface->get_backend = mail_shell_content_get_backend;
-	interface->get_formatter = mail_shell_content_get_formatter;
+	interface->get_mail_display = mail_shell_content_get_mail_display;
 	interface->get_hide_deleted = mail_shell_content_get_hide_deleted;
 	interface->get_message_list = mail_shell_content_get_message_list;
 	interface->get_popup_menu = mail_shell_content_get_popup_menu;
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 53cd908..021acc2 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -830,12 +830,11 @@ action_mail_smart_backward_cb (GtkAction *action,
 	EMailShellContent *mail_shell_content;
 	EMailShellSidebar *mail_shell_sidebar;
 	EMFolderTree *folder_tree;
-	EMFormatHTML *formatter;
 	EMailReader *reader;
 	EMailView *mail_view;
 	GtkWidget *message_list;
 	GtkToggleAction *toggle_action;
-	EWebView *web_view;
+	EMailDisplay *display;
 	gboolean caret_mode;
 	gboolean magic_spacebar;
 
@@ -853,7 +852,7 @@ action_mail_smart_backward_cb (GtkAction *action,
 	folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
 
 	reader = E_MAIL_READER (mail_view);
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
 	message_list = e_mail_reader_get_message_list (reader);
 
 	magic_spacebar = e_shell_settings_get_boolean (
@@ -862,10 +861,9 @@ action_mail_smart_backward_cb (GtkAction *action,
 	toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE));
 	caret_mode = gtk_toggle_action_get_active (toggle_action);
 
-	web_view = em_format_html_get_web_view (formatter);
-
-	if (e_web_view_scroll_backward (web_view))
-		return;
+	/* FIXME WEBKIT FUCKING IMPLEMENT
+	gtk_scrolled_window_scroll (display, GTK_MOVEMENT_PAGES, -1);
+	*/
 
 	if (caret_mode || !magic_spacebar)
 		return;
@@ -906,7 +904,7 @@ action_mail_smart_forward_cb (GtkAction *action,
 	EMailView *mail_view;
 	GtkWidget *message_list;
 	GtkToggleAction *toggle_action;
-	EWebView *web_view;
+	EMailDisplay *display;
 	gboolean caret_mode;
 	gboolean magic_spacebar;
 
@@ -924,7 +922,7 @@ action_mail_smart_forward_cb (GtkAction *action,
 	folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
 
 	reader = E_MAIL_READER (mail_view);
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
 	message_list = e_mail_reader_get_message_list (reader);
 
 	magic_spacebar = e_shell_settings_get_boolean (
@@ -933,10 +931,10 @@ action_mail_smart_forward_cb (GtkAction *action,
 	toggle_action = GTK_TOGGLE_ACTION (ACTION (MAIL_CARET_MODE));
 	caret_mode = gtk_toggle_action_get_active (toggle_action);
 
-	web_view = em_format_html_get_web_view (formatter);
+	/* FIXME WEBKIT: Fucking implement
+	gtk_scolled_window_scroll (display, GTK_MOVEMENT_PAGES, 1);
+	*/
 
-	if (e_web_view_scroll_forward (web_view))
-		return;
 
 	if (caret_mode || !magic_spacebar)
 		return;
diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c
index ee1c55e..72f3291 100644
--- a/modules/mail/e-mail-shell-view-private.c
+++ b/modules/mail/e-mail-shell-view-private.c
@@ -330,7 +330,7 @@ mail_shell_view_popup_event_cb (EMailShellView *mail_shell_view,
                                 const gchar *uri)
 {
 	EMailShellContent *mail_shell_content;
-	EMFormatHTML *formatter;
+	EMailDisplay *display;
 	EShellView *shell_view;
 	EMailReader *reader;
 	EMailView *mail_view;
@@ -343,9 +343,10 @@ mail_shell_view_popup_event_cb (EMailShellView *mail_shell_view,
 	mail_shell_content = mail_shell_view->priv->mail_shell_content;
 	mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
 
+	/* FIXME WEBKIT: Probably does not do what we want it to */
 	reader = E_MAIL_READER (mail_view);
-	formatter = e_mail_reader_get_formatter (reader);
-	web_view = em_format_html_get_web_view (formatter);
+	display = e_mail_reader_get_mail_display (reader);
+	web_view = e_mail_display_get_current_web_view (display);
 
 	if (e_web_view_get_cursor_image (web_view) != NULL)
 		return FALSE;
@@ -426,17 +427,15 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view,
                                    EMailReader *reader)
 {
 	GtkWidget *message_list;
-	EMFormatHTML *formatter;
-	EWebView *web_view;
+	EMailDisplay *display;
 	EShellView *shell_view;
 	EShellTaskbar *shell_taskbar;
 
 	shell_view = E_SHELL_VIEW (mail_shell_view);
 	shell_taskbar = e_shell_view_get_shell_taskbar (shell_view);
 
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
 	message_list = e_mail_reader_get_message_list (reader);
-	web_view = em_format_html_get_web_view (formatter);
 
 	e_shell_view_update_actions (E_SHELL_VIEW (mail_shell_view));
 	e_mail_shell_view_update_sidebar (mail_shell_view);
@@ -462,26 +461,28 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view,
 		G_CALLBACK (mail_shell_view_message_list_right_click_cb),
 		mail_shell_view, G_CONNECT_SWAPPED);
 
+	/* FIXME WEBKIT EMailDisplay does not have these signals (yet)
 	g_signal_connect_object (
-		web_view, "key-press-event",
+		display, "key-press-event",
 		G_CALLBACK (mail_shell_view_key_press_event_cb),
 		mail_shell_view, G_CONNECT_SWAPPED);
 
 	g_signal_connect_object (
-		web_view, "popup-event",
+		display, "popup-event",
 		G_CALLBACK (mail_shell_view_popup_event_cb),
 		mail_shell_view, G_CONNECT_SWAPPED);
 
 	g_signal_connect_object (
-		web_view, "scroll",
+		display, "scroll",
 		G_CALLBACK (mail_shell_view_scroll_cb),
 		mail_shell_view,
 		G_CONNECT_AFTER | G_CONNECT_SWAPPED);
 
 	g_signal_connect_object (
-		web_view, "status-message",
+		display, "status-message",
 		G_CALLBACK (e_shell_taskbar_set_message),
 		shell_taskbar, G_CONNECT_SWAPPED);
+	*/
 }
 
 static void
@@ -616,7 +617,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
 	EShellTaskbar *shell_taskbar;
 	EShellWindow *shell_window;
 	EShellSearchbar *searchbar;
-	EMFormatHTML *formatter;
 	EMFolderTree *folder_tree;
 	EActionComboBox *combo_box;
 	ERuleContext *context;
@@ -627,7 +627,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
 	GtkWidget *message_list;
 	EMailReader *reader;
 	EMailView *mail_view;
-	EWebView *web_view;
+	EMailDisplay *display;
 	const gchar *source;
 	guint merge_id;
 	gint ii = 0;
@@ -670,7 +670,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
 	combo_box = e_shell_searchbar_get_scope_combo_box (searchbar);
 
 	reader = E_MAIL_READER (shell_content);
-	formatter = e_mail_reader_get_formatter (reader);
+	display = e_mail_reader_get_mail_display (reader);
 	message_list = e_mail_reader_get_message_list (reader);
 
 	em_folder_tree_set_selectable_widget (folder_tree, message_list);
@@ -683,8 +683,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
 		G_BINDING_BIDIRECTIONAL |
 		G_BINDING_SYNC_CREATE);
 
-	web_view = em_format_html_get_web_view (formatter);
-
 	g_signal_connect_object (
 		folder_tree, "folder-selected",
 		G_CALLBACK (mail_shell_view_folder_tree_selected_cb),
@@ -756,27 +754,28 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
 		G_CALLBACK (e_mail_shell_view_update_search_filter),
 		mail_shell_view, G_CONNECT_SWAPPED);
 
+	/* FIXME WEBKIT: EMailDisplay does no have these signals (for now)
 	g_signal_connect_object (
-		web_view, "key-press-event",
+		display, "key-press-event",
 		G_CALLBACK (mail_shell_view_key_press_event_cb),
 		mail_shell_view, G_CONNECT_SWAPPED);
 
 	g_signal_connect_object (
-		web_view, "popup-event",
+		display, "popup-event",
 		G_CALLBACK (mail_shell_view_popup_event_cb),
 		mail_shell_view, G_CONNECT_SWAPPED);
 
 	g_signal_connect_object (
-		web_view, "scroll",
+		display, "scroll",
 		G_CALLBACK (mail_shell_view_scroll_cb),
 		mail_shell_view,
 		G_CONNECT_AFTER | G_CONNECT_SWAPPED);
 
 	g_signal_connect_object (
-		web_view, "status-message",
+		display, "status-message",
 		G_CALLBACK (e_shell_taskbar_set_message),
 		shell_taskbar, G_CONNECT_SWAPPED);
-
+	*/
 	g_signal_connect_object (
 		mail_shell_view, "toggled",
 		G_CALLBACK (e_mail_shell_view_update_send_receive_menus),



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