[evolution/webkit: 141/177] Revert "Convert EMFormatPURI to a thread-safe EMPart object"



commit e9feca4ab7ec5595c14a9c0faf8453ff2f293505
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Feb 8 14:49:03 2012 +0100

    Revert "Convert EMFormatPURI to a thread-safe EMPart object"
    
    This reverts commit 7ed74b300c689e21d7c730f044765f59599fa26f.

 em-format/Makefile.am                |    2 -
 em-format/em-format-quote.c          |  125 +++----
 em-format/em-format.c                |  249 +++++++-----
 em-format/em-format.h                |   75 +++--
 em-format/em-part.c                  |  678 -------------------------------
 em-format/em-part.h                  |  140 -------
 mail/Makefile.am                     |    2 -
 mail/e-mail-request.c                |   78 ++---
 mail/em-format-html-display-parts.c  |  722 ----------------------------------
 mail/em-format-html-display-parts.h  |  242 ------------
 mail/em-format-html-display.c        |  387 +++++++++----------
 mail/em-format-html-display.h        |   46 +++
 mail/em-format-html-print.c          |  190 +++------
 mail/em-format-html.c                |  295 ++++++---------
 mail/em-format-html.h                |    1 +
 mail/em-utils.c                      |   12 +-
 plugins/audio-inline/Makefile.am     |    4 +-
 plugins/audio-inline/audio-inline.c  |  232 ++++++-----
 plugins/audio-inline/em-part-audio.c |  346 ----------------
 plugins/audio-inline/em-part-audio.h |  112 ------
 widgets/misc/e-web-view.c            |  185 +++++++++-
 widgets/misc/e-web-view.h            |    4 +
 22 files changed, 1018 insertions(+), 3109 deletions(-)
---
diff --git a/em-format/Makefile.am b/em-format/Makefile.am
index 186f300..392a195 100644
--- a/em-format/Makefile.am
+++ b/em-format/Makefile.am
@@ -6,7 +6,6 @@ emformatinclude_HEADERS =				\
 	em-format.h					\
 	em-format-quote.h				\
 	em-inline-filter.h				\
-	em-part.h					\
 	em-stripsig-filter.h
 
 libemformat_la_CPPFLAGS =				\
@@ -22,7 +21,6 @@ libemformat_la_SOURCES =				\
 	em-format.c					\
 	em-format-quote.c				\
 	em-inline-filter.c				\
-	em-part.c					\
 	em-stripsig-filter.c
 
 libemformat_la_LDFLAGS = -avoid-version $(NO_UNDEFINED)
diff --git a/em-format/em-format-quote.c b/em-format/em-format-quote.c
index d107757..23994f2 100644
--- a/em-format/em-format-quote.c
+++ b/em-format/em-format-quote.c
@@ -32,7 +32,6 @@
 #include "em-inline-filter.h"
 #include "em-stripsig-filter.h"
 #include "em-format-quote.h"
-#include "em-part.h"
 
 #define EM_FORMAT_QUOTE_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -54,9 +53,9 @@ static void emfq_parse_text_enriched    (EMFormat *emf, CamelMimePart *part, GSt
 static void emfq_parse_text_html        (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 static void emfq_parse_attachment       (EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 
-static void emfq_write_text_plain	(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emfq_write_text_enriched	(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emfq_write_text_html	(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, 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 gpointer parent_class;
 
@@ -387,8 +386,8 @@ emfq_parse_text_plain (EMFormat* emf,
                        EMFormatParserInfo* info,
                        GCancellable* cancellable)
 {
-        EMPart *emp;
-	CamelMimePart *mp;
+        EMFormatPURI *puri;
+		CamelMimePart *mp;
         gint len;
 
         len = part_id->len;
@@ -404,9 +403,10 @@ emfq_parse_text_plain (EMFormat* emf,
 			g_object_unref (mp);
 		}
 
-	emp = em_part_new (emf, part, part_id->str, emfq_write_text_plain);
-        em_part_set_mime_type (emp, "text/html");
-	em_format_add_part_object (emf, emp);
+        puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+        puri->write_func = emfq_write_text_plain;
+        puri->mime_type = g_strdup ("text/html");
+        em_format_add_puri (emf, puri);
 
         g_string_truncate (part_id, len);
 }
@@ -418,15 +418,16 @@ emfq_parse_text_html (EMFormat* emf,
                       EMFormatParserInfo* info,
                       GCancellable* cancellable)
 {
-        EMPart *emp;
+        EMFormatPURI *puri;
         gint len;
 
         len = part_id->len;
         g_string_append (part_id, ".text_html");
 
-	emp = em_part_new (emf, part, part_id->str, emfq_write_text_html);
-        em_part_set_mime_type (emp, "text/html");
-	em_format_add_part_object (emf, emp);
+        puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+        puri->write_func = emfq_write_text_html;
+        puri->mime_type = g_strdup ("text/html");
+        em_format_add_puri (emf, puri);
 
         g_string_truncate (part_id, len);
 }
@@ -438,15 +439,16 @@ emfq_parse_text_enriched (EMFormat* emf,
                           EMFormatParserInfo* info,
                           GCancellable* cancellable)
 {
-        EMPart *emp;
+        EMFormatPURI *puri;
         gint len;
 
         len = part_id->len;
         g_string_append (part_id, ".text_enriched");
 
-	emp = em_part_new (emf, part, part_id->str, emfq_write_text_enriched);
-	em_part_set_mime_type (emp, "text/html");
-	em_format_add_part_object (emf, emp);
+        puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+        puri->write_func = emfq_write_text_enriched;
+        puri->mime_type = g_strdup ("text/html");
+        em_format_add_puri (emf, puri);
 
         g_string_truncate (part_id, len);
 }
@@ -458,16 +460,17 @@ emfq_parse_attachment (EMFormat* emf,
                        EMFormatParserInfo* info,
                        GCancellable* cancellable)
 {
-        EMPart *emp;
+        EMFormatPURI *puri;
         gint len;
 
         len = part_id->len;
         g_string_append (part_id, ".attachment");
 
-	emp = em_part_new (emf, part, part_id->str, emfq_write_text_html);
-        em_part_set_mime_type (emp, "text/html");
-        em_part_set_is_attachment (emp, TRUE);
-        em_format_add_part_object (emf, emp);
+        puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+        puri->write_func = emfq_write_text_html;
+        puri->mime_type = g_strdup ("text/html");
+        puri->is_attachment = TRUE;
+        em_format_add_puri (emf, puri);
 
         g_string_truncate (part_id, len);
 }
@@ -480,7 +483,7 @@ emfq_parse_attachment (EMFormat* emf,
 
 static void
 emfq_write_attachment (EMFormat *emf,
-		       EMPart *emp,
+		       EMFormatPURI *puri,
                        CamelStream *stream,
                        EMFormatWriterInfo *info,
                        GCancellable *cancellable)
@@ -489,13 +492,9 @@ emfq_write_attachment (EMFormat *emf,
 	const EMFormatHandler *handler;
 	gchar *text, *html;
 	CamelContentType *ct;
-	CamelMimePart *part;
 	const gchar *mime_type;
-	gchar *uri;
 
-	part = em_part_get_mime_part (emp);
-	uri = em_part_get_uri (emp);
-	ct = camel_mime_part_get_content_type (part);
+	ct = camel_mime_part_get_content_type (puri->part);
 	if (ct) {
 		mime_type = camel_content_type_simple (ct);
 		camel_content_type_unref (ct);
@@ -505,18 +504,15 @@ emfq_write_attachment (EMFormat *emf,
 
 	handler = em_format_find_handler (emf, mime_type);
 
-	if (!em_format_is_inline (emf, uri, part, handler)) {
-		g_free (uri);
-		g_object_unref (part);
+	if (!em_format_is_inline (emf, puri->uri, puri->part, handler))
 		return;
-	}
 
 	camel_stream_write_string (
 		stream, "<table border=1 cellspacing=0 cellpadding=0>"
 		"<tr><td><font size=-1>\n", cancellable, NULL);
 
 	/* output some info about it */
-	text = em_format_describe_part (part, mime_type);
+	text = em_format_describe_part (puri->part, mime_type);
 	html = camel_text_to_html (
 		text, emfq->priv->text_html_flags &
 		CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
@@ -528,10 +524,7 @@ emfq_write_attachment (EMFormat *emf,
 		stream, "</font></td></tr></table>", cancellable, NULL);
 
 	if (handler && handler->write_func)
-		handler->write_func (emf, emp, stream, info, cancellable);
-
-	g_object_unref (part);
-	g_free (uri);
+		handler->write_func (emf, puri, stream, info, cancellable);
 }
 
 static void
@@ -634,7 +627,7 @@ em_format_quote_write (EMFormatQuote* emfq,
 		camel_stream_write_string (
 			stream, "<br>\n", cancellable, NULL);
 	g_object_unref (settings);
-
+       
         if (emfq->priv->credits && *emfq->priv->credits) {
                 gchar *credits = g_strdup_printf ("%s<br/>", emfq->priv->credits);
                 camel_stream_write_string (stream, credits, cancellable, NULL);
@@ -650,26 +643,21 @@ em_format_quote_write (EMFormatQuote* emfq,
                         "<blockquote type=cite>\n", cancellable, NULL);
 
         for (iter = emf->mail_part_list; iter; iter = iter->next) {
-                EMPart *emp = iter->data;
-		EMPartObjectWriteFunc write_func;
-		
-		write_func = em_part_get_write_func (emp);
-		if (em_part_get_is_attachment (emp) || !write_func)
+                EMFormatPURI *puri = iter->data;
+
+                if (puri->is_attachment || !puri->write_func)
                         continue;
 
-		if (emfq->priv->flags & EM_FORMAT_QUOTE_HEADERS) {
-                        GString *buffer = g_string_new ("");
-			CamelMimePart *part;
+                puri = iter->data;
 
-			part = em_part_get_mime_part (emp);
-                        emfq_format_headers (emfq, buffer, (CamelMedium *) part);
+                if (emfq->priv->flags & EM_FORMAT_QUOTE_HEADERS) {
+                        GString *buffer = g_string_new ("");
+                        emfq_format_headers (emfq, buffer, (CamelMedium *) puri->part);
                         camel_stream_write_string (stream, buffer->str, cancellable, NULL);
-
                         g_string_free (buffer, TRUE);
-			g_object_unref (part);
                 }
 
-                em_part_write (emp, stream, &info, cancellable);
+                puri->write_func (emf, puri, stream, &info, cancellable);
         }
 
         if (emfq->priv->flags & EM_FORMAT_QUOTE_CITE)
@@ -681,7 +669,7 @@ em_format_quote_write (EMFormatQuote* emfq,
 
 static void
 emfq_write_text_plain (EMFormat *emf,
-		       EMPart *emp,
+		       EMFormatPURI *puri,
 		       CamelStream *stream,
 		       EMFormatWriterInfo *info,
 		       GCancellable *cancellable)
@@ -691,16 +679,16 @@ emfq_write_text_plain (EMFormat *emf,
 	CamelMimeFilter *html_filter;
 	CamelMimeFilter *sig_strip;
 	CamelContentType *type;
-	CamelMimePart *part;
 	const gchar *format;
 	guint32 rgb = 0x737373, flags;
 
-	flags = emfq->priv->text_html_flags;
+	if (!puri->part)
+		return;
 
-	part = em_part_get_mime_part (emp);
+	flags = emfq->priv->text_html_flags;
 
 	/* Check for RFC 2646 flowed text. */
-	type = camel_mime_part_get_content_type (part);
+	type = camel_mime_part_get_content_type (puri->part);
 	if (camel_content_type_is(type, "text", "plain")
 	    && (format = camel_content_type_param(type, "format"))
 	    && !g_ascii_strcasecmp(format, "flowed"))
@@ -722,17 +710,15 @@ emfq_write_text_plain (EMFormat *emf,
 
 	em_format_format_text (
 		EM_FORMAT (emfq), filtered_stream,
-		CAMEL_DATA_WRAPPER (part), cancellable);
+		CAMEL_DATA_WRAPPER (puri->part), cancellable);
 
 	camel_stream_flush (filtered_stream, cancellable, NULL);
 	g_object_unref (filtered_stream);
-
-	g_object_unref (part);
 }
 
 static void
 emfq_write_text_enriched (EMFormat *emf,
-			  EMPart *emp,
+			  EMFormatPURI *puri,
                     	  CamelStream *stream,
                     	  EMFormatWriterInfo *info,
                     	  GCancellable *cancellable)
@@ -741,12 +727,9 @@ emfq_write_text_enriched (EMFormat *emf,
 	CamelMimeFilter *enriched;
 	guint32 flags = 0;
 	CamelContentType *ct;
-	CamelMimePart *part;
 	const gchar *mime_type = NULL;
 
-	part = em_part_get_mime_part (emp);
-
-	ct = camel_mime_part_get_content_type (part);
+	ct = camel_mime_part_get_content_type (puri->part);
 	if (ct) {
 		mime_type = camel_content_type_simple (ct);
 		camel_content_type_unref (ct);
@@ -771,25 +754,21 @@ emfq_write_text_enriched (EMFormat *emf,
 
 	camel_stream_write_string (stream, "<br><hr><br>", cancellable, NULL);
 	em_format_format_text (
-		emf, filtered_stream, CAMEL_DATA_WRAPPER (part), cancellable);
+		emf, filtered_stream, CAMEL_DATA_WRAPPER (puri->part), cancellable);
 	camel_stream_flush (filtered_stream, cancellable, NULL);
 	g_object_unref (filtered_stream);
-
-	g_object_unref (part);
 }
 
 static void
 emfq_write_text_html (EMFormat *emf,
-		      EMPart *emp,
+		      EMFormatPURI *puri,
 	              CamelStream *stream,
 	              EMFormatWriterInfo *info,
 	              GCancellable *cancellable)
 {
 	EMFormatQuotePrivate *priv;
-	CamelMimePart *part;
 
 	priv = EM_FORMAT_QUOTE_GET_PRIVATE (emf);
-	part = em_part_get_mime_part (emp);
 
 	camel_stream_write_string (
 		stream, "\n<!-- text/html -->\n", cancellable, NULL);
@@ -807,16 +786,14 @@ emfq_write_text_html (EMFormat *emf,
 
 		em_format_format_text (
 			emf, filtered_stream,
-			(CamelDataWrapper *) part, cancellable);
+			(CamelDataWrapper *) puri->part, cancellable);
 		camel_stream_flush (filtered_stream, cancellable, NULL);
 		g_object_unref (filtered_stream);
 	} else {
 		em_format_format_text (
 			emf, stream,
-			(CamelDataWrapper *) part, cancellable);
+			(CamelDataWrapper *) puri->part, cancellable);
 	}
-
-	g_object_unref (part);
 }
 
 /****************************************************************************/
diff --git a/em-format/em-format.c b/em-format/em-format.c
index caf0cdb..a7c2935 100644
--- a/em-format/em-format.c
+++ b/em-format/em-format.c
@@ -92,9 +92,9 @@ 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, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emf_write_source			(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void emf_write_error			(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, 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_write_error			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
 
 /**************************************************************************/
 
@@ -636,7 +636,7 @@ emf_parse_multipart_signed (EMFormat *emf,
 					emf, "%s",
 					local_error->message);
 			g_clear_error (&local_error);
-			emf_parse_multipart_mixed (emf, part, part_id, info, cancellable);
+			emf_parse_multipart_mixed (emf, part, part_id,info,  cancellable);
 		} else {
 			gint i, nparts, len = part_id->len;
 			gboolean secured;
@@ -792,7 +792,7 @@ emf_parse_message_deliverystatus (EMFormat *emf,
                             	  EMFormatParserInfo *info,
                             	  GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	gint len;
 
 	if (g_cancellable_is_cancelled (cancellable))
@@ -801,14 +801,15 @@ emf_parse_message_deliverystatus (EMFormat *emf,
 	len = part_id->len;
 	g_string_append (part_id, ".deliverystatus");
 
-        emp = em_part_new (emf, part, part_id->str, emf_write_text);
-        em_part_set_mime_type (emp, "text/html");
-        em_part_set_validity (emp, info->validity);
-	em_part_set_validity_type (emp, info->validity_type);
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->write_func = emf_write_text;
+	puri->mime_type = g_strdup ("text/html");
+	puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
+	puri->validity_type = info->validity_type;
 
 	g_string_truncate (part_id, len);
 
-	em_format_add_part_object (emf, emp);
+	em_format_add_puri (emf, puri);
 }
 
 static void
@@ -1043,15 +1044,16 @@ emf_parse_headers (EMFormat *emf,
 		   EMFormatParserInfo *info,
 		   GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	gint len;
 
 	len = part_id->len;
 	g_string_append (part_id, ".headers");
 
-        emp = em_part_new (emf, part, part_id->str, info->handler->write_func);
-	em_part_set_mime_type (emp, "text/html");
-        em_format_add_part_object (emf, emp);
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->write_func = info->handler->write_func;
+	puri->mime_type = g_strdup ("text/html");
+	em_format_add_puri (emf, puri);
 
 	g_string_truncate (part_id, len);
 }
@@ -1076,7 +1078,7 @@ emf_parse_source (EMFormat *emf,
 		  EMFormatParserInfo *info,
 		  GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	gint len;
 
 	if (g_cancellable_is_cancelled (cancellable))
@@ -1085,18 +1087,19 @@ emf_parse_source (EMFormat *emf,
 	len = part_id->len;
 	g_string_append (part_id, ".source");
 
-        emp = em_part_new (emf, part, part_id->str, info->handler->write_func);
-	em_part_set_mime_type (emp, "text/html");
-        em_format_add_part_object (emf, emp);
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->write_func = info->handler->write_func;
+	puri->mime_type = g_strdup ("text/html");
+	g_string_truncate (part_id, len);
 
-        g_string_truncate (part_id, len);
+	em_format_add_puri (emf, puri);
 }
 
 /**************************************************************************/
 
 void
 em_format_empty_writer (EMFormat *emf,
-			EMPart *emp,
+			EMFormatPURI *puri,
 			CamelStream *stream,
 			EMFormatWriterInfo *info,
 			GCancellable *cancellable)
@@ -1106,62 +1109,48 @@ em_format_empty_writer (EMFormat *emf,
 
 static void
 emf_write_error (EMFormat* emf,
-		 EMPart *emp,
+		 EMFormatPURI* puri,
 		 CamelStream* stream,
 		 EMFormatWriterInfo* info,
 		 GCancellable* cancellable)
 {
-        CamelMimePart *part;
-
-        part = em_part_get_mime_part (emp);
-	camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) part,
+	camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) puri->part,
 		stream, cancellable, NULL);
-
-        g_object_unref (part);
 }
 
 static void
 emf_write_text (EMFormat *emf,
-		EMPart *emp,
+		EMFormatPURI *puri,
 		CamelStream *stream,
 		EMFormatWriterInfo *info,
 		GCancellable *cancellable)
 {
 	CamelContentType *ct;
-        CamelMimePart *part;
 
-        part = em_part_get_mime_part (emp);
-	ct = camel_mime_part_get_content_type (part);
+	ct = camel_mime_part_get_content_type (puri->part);
 	if (!camel_content_type_is (ct, "text", "plain")) {
 		camel_stream_write_string (stream, _("Cannot proccess non-text mime/part"),
 			cancellable, NULL);
-
-                g_object_unref (part);
 		return;
 	}
-	
-	camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) part,
-		stream, cancellable, NULL);
 
-        g_object_unref (part);
+	camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) puri->part,
+		stream, cancellable, NULL);
 }
 
 static void
 emf_write_source (EMFormat *emf,
-		  EMPart *emp,
+		  EMFormatPURI *puri,
 		  CamelStream *stream,
 		  EMFormatWriterInfo *info,
 		  GCancellable *cancellable)
 {
-        CamelMimePart *part;
 	GByteArray *ba;
 	gchar *data;
 
 	g_return_if_fail (EM_IS_FORMAT (emf));
 
-        part = em_part_get_mime_part (emp);
-	ba = camel_data_wrapper_get_byte_array ((CamelDataWrapper *) part);
-        g_object_unref (part);
+	ba = camel_data_wrapper_get_byte_array ((CamelDataWrapper *) puri->part);
 
 	data = g_strndup ((gchar *) ba->data, ba->len);
 	camel_stream_write_string (stream, data, cancellable, NULL);
@@ -1333,7 +1322,8 @@ em_format_finalize (GObject *object)
 	}
 
 	if (emf->mail_part_table) {
-		/* This will destroy all the EMPartObjects stored inside!!!! */
+		/* This will destroy all the EMFormatPURI objects stored
+		 * inside!!!! */
 		g_hash_table_destroy (emf->mail_part_table);
 		emf->mail_part_table = NULL;
 	}
@@ -1440,9 +1430,9 @@ static void
 mail_part_table_item_free (gpointer data)
 {
 	GList *iter = data;
-	EMPart *emp = iter->data;
+	EMFormatPURI *puri = iter->data;
 
-	g_object_unref (emp);
+	em_format_puri_free (puri);
 }
 
 static void
@@ -1458,7 +1448,8 @@ em_format_init (EMFormat *emf)
 	emf->folder = NULL;
 	emf->mail_part_list = NULL;
 	emf->mail_part_table = g_hash_table_new_full (g_str_hash, g_str_equal,
-			                g_free, mail_part_table_item_free);
+			NULL, (GDestroyNotify) mail_part_table_item_free);
+	/* No need to free the key, because it's owned and free'd by the PURI */
 	
 	shell = e_shell_get_default ();
 	shell_settings = e_shell_get_shell_settings (shell);
@@ -1734,48 +1725,27 @@ em_format_remove_header_struct (EMFormat* emf,
 	em_format_remove_header (emf, header->name, header->value);
 }
 
-/**
- * em_format_add_part_object:
- * 
- * @emf: an #EMFormat
- * @emp: an #EMPart to be added
- * 
- * Reference count of @emp is not increased, the #EMFormat takes
- * ownership from caller.
- */
 void
-em_format_add_part_object (EMFormat *emf,
-                           EMPart *emp)
+em_format_add_puri (EMFormat *emf,
+                    EMFormatPURI *puri)
 {
         GList *item;
-        gchar *uri;
 
         g_return_if_fail (EM_IS_FORMAT (emf));
-        g_return_if_fail (EM_IS_PART (emp));
+        g_return_if_fail (puri != NULL);
 
-        emf->mail_part_list = g_list_append (emf->mail_part_list, emp);
+        emf->mail_part_list = g_list_append (emf->mail_part_list, puri);
         item = g_list_last (emf->mail_part_list);
 
-        uri = em_part_get_uri (emp);
-        g_hash_table_insert (emf->mail_part_table, uri, item);
+        g_hash_table_insert (emf->mail_part_table,
+                        puri->uri, item);
 
-        d(printf("Added EMPart %s\n", uri));
+        d(printf("Added PURI %s\n", puri->uri));
 }
 
-/**
- * em_format_find_part_object:
- *
- * @emf: an #EMFormat object
- * @id: an part URI or CID.
- *
- * Looks up EMPartObject by it's URI or CID.
- *
- * Returns: Referenced #EMPart that has to be unreferenced when no
- *          longer needed, or %NULL when no part with such %id is found.
- */
-EMPart *
-em_format_find_part_object (EMFormat *emf,
-                            const gchar *id)
+EMFormatPURI*
+em_format_find_puri (EMFormat *emf,
+		     const gchar *id)
 {
 	GList *list_iter;
 
@@ -1786,11 +1756,9 @@ em_format_find_part_object (EMFormat *emf,
 
 		g_hash_table_iter_init (&iter, emf->mail_part_table);
 		while (g_hash_table_iter_next (&iter, &key, &value)) {
-                        EMPart *emp = ((GList *) value)->data;
-                        gchar *cid = em_part_get_cid (emp);
-
-			if (g_strcmp0 (cid, id) == 0)
-				return g_object_ref (emp);
+			EMFormatPURI *puri = ((GList *) value)->data;
+			if (g_strcmp0 (puri->cid, id) == 0)
+				return puri;
 		}
 
 		return NULL;
@@ -1798,7 +1766,7 @@ em_format_find_part_object (EMFormat *emf,
 
 	list_iter = g_hash_table_lookup (emf->mail_part_table, id);
 	if (list_iter)
-		return g_object_ref (list_iter->data);
+		return list_iter->data;
 
 	return NULL;
 }
@@ -1904,7 +1872,7 @@ em_format_parse (EMFormat *emf,
 		 GCancellable *cancellable)
 {
 	GString *part_id;
-	EMPart *emp;
+	EMFormatPURI *puri;
 	EMFormatParserInfo info = { 0 };
 
 	g_return_if_fail (EM_IS_FORMAT (emf));
@@ -1934,10 +1902,11 @@ em_format_parse (EMFormat *emf,
 
 	part_id = g_string_new (".message");
 
-        /* Create a special EMPart with entire message */
-        emp = em_part_new (emf, (CamelMimePart *) emf->message, part_id->str, NULL);
-        em_part_set_mime_type (emp, "text/plain");
-        em_format_add_part_object (emf, emp);
+	/* Create a special PURI with entire message */
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI),
+		(CamelMimePart *) emf->message, part_id->str);
+	puri->mime_type = g_strdup ("text/html");
+	em_format_add_puri (emf, puri);
 
         info.force_handler = TRUE;
 	em_format_parse_part_as (emf, CAMEL_MIME_PART (emf->message), part_id, &info,
@@ -1993,7 +1962,6 @@ em_format_parse_async (EMFormat *emf,
 
 	result = g_simple_async_result_new (G_OBJECT (emf), callback,
 					    user_data, em_format_parse_async);
-
 	g_simple_async_result_run_in_thread (result, emf_start_async_parser,
 					     G_PRIORITY_DEFAULT, cancellable);
 }
@@ -2094,7 +2062,7 @@ em_format_format_error (EMFormat *emf,
                         const gchar *format,
                         ...)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	CamelMimePart *part;
 	const EMFormatHandler *handler;
 	gchar *errmsg;
@@ -2116,16 +2084,14 @@ em_format_format_error (EMFormat *emf,
 
 	emf->priv->last_error++;
 	uri = g_strdup_printf (".error.%d", emf->priv->last_error);
-
-        emp = em_part_new (emf, part, uri, NULL);
-	em_part_set_mime_type (emp, "text/html");
-
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, uri);
+	puri->mime_type = g_strdup ("text/html");
 	if (handler && handler->write_func)
-		em_part_set_write_func (emp, handler->write_func);
+		puri->write_func = handler->write_func;
 	else
-		em_part_set_write_func (emp, emf_write_error);
+		puri->write_func = emf_write_error;
 
-	em_format_add_part_object (emf, emp);
+	em_format_add_puri (emf, puri);
 
 	g_free (uri);
 	g_object_unref (part);
@@ -2543,6 +2509,95 @@ em_format_redraw (EMFormat *emf)
 
 
 /**************************************************************************/
+EMFormatPURI*
+em_format_puri_new (EMFormat *emf,
+		    gsize puri_size,
+		    CamelMimePart *part,
+		    const gchar *uri)
+{
+	EMFormatPURI *puri;
+
+	g_return_val_if_fail (EM_IS_FORMAT (emf), NULL);
+	g_return_val_if_fail (puri_size >= sizeof (EMFormatPURI), NULL);
+
+	puri = (EMFormatPURI *) g_malloc0 (puri_size);
+	puri->emf = emf;
+
+	if (part)
+		puri->part = g_object_ref (part);
+
+	if (uri)
+		puri->uri = g_strdup (uri);
+
+	return puri;
+}
+
+void
+em_format_puri_free (EMFormatPURI *puri)
+{
+	g_return_if_fail (puri);
+
+	if (puri->part)
+		g_object_unref (puri->part);
+
+	if (puri->uri)
+		g_free (puri->uri);
+
+	if (puri->cid)
+		g_free (puri->cid);
+
+	if (puri->mime_type)
+		g_free (puri->mime_type);
+
+	if (puri->validity)
+		camel_cipher_validity_free (puri->validity);
+
+	if (puri->validity_parent)
+		camel_cipher_validity_free (puri->validity_parent);
+
+	if (puri->free)
+		puri->free(puri);
+
+	g_free (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, info, cancellable);
+	} else {
+		const EMFormatHandler *handler;
+		const gchar *mime_type;
+
+		if (puri->mime_type) {
+			mime_type = puri->mime_type;
+		} else {
+			mime_type = (gchar *) "plain/text";
+		}
+
+		handler = em_format_find_handler (puri->emf, mime_type);
+		if (handler && handler->write_func) {
+			handler->write_func (puri->emf,
+					puri, stream, info, cancellable);
+		}
+	}
+}
+
 EMFormatHeader*
 em_format_header_new (const gchar *name,
 		      const gchar *value)
diff --git a/em-format/em-format.h b/em-format/em-format.h
index d9c27d8..c9c38be 100644
--- a/em-format/em-format.h
+++ b/em-format/em-format.h
@@ -60,29 +60,26 @@ typedef struct _EMFormat EMFormat;
 typedef struct _EMFormatClass EMFormatClass;
 typedef struct _EMFormatPrivate EMFormatPrivate;
 
+typedef struct _EMFormatPURI EMFormatPURI;
 typedef struct _EMFormatHeader EMFormatHeader;
 typedef struct _EMFormatHandler EMFormatHandler;
 typedef struct _EMFormatParserInfo EMFormatParserInfo;
 typedef struct _EMFormatWriterInfo EMFormatWriterInfo;
 
-typedef struct _EMPart EMPart;
-
 typedef void		(*EMFormatParseFunc)	(EMFormat *emf,
 					 	 CamelMimePart *part,
 					 	 GString *part_id,
 					 	 EMFormatParserInfo *info,
 					 	 GCancellable *cancellable);
-/* FIXME: Redeclared in em-part-object.h */
-typedef void            (*EMPartObjectWriteFunc)
-                                                (EMFormat *emf,
-                                                 EMPart *empo,
-                                                 CamelStream *stream,
-                                                 EMFormatWriterInfo *info,
-                                                 GCancellable *cancellable);
-typedef GtkWidget*      (*EMPartObjectWidgetFunc)
-                                                (EMFormat *emf,
-                                                 EMPart *empo,
-                                                 GCancellable *cancellable);
+typedef void		(*EMFormatWriteFunc)	(EMFormat *emf,
+					 	 EMFormatPURI *puri,
+					 	 CamelStream *stream,
+					 	 EMFormatWriterInfo *info,
+					 	 GCancellable *cancellable);
+typedef GtkWidget*	(*EMFormatWidgetFunc)	(EMFormat *emf,
+					 	 EMFormatPURI *puri,
+					 	 GCancellable *cancellable);
+
 
 typedef enum {
 	EM_FORMAT_HANDLER_INLINE = 1 << 0,
@@ -100,7 +97,7 @@ typedef enum {
 struct _EMFormatHandler {
 	gchar *mime_type;
 	EMFormatParseFunc parse_func;
-	EMPartObjectWriteFunc write_func;
+	EMFormatWriteFunc write_func;
 	EMFormatHandlerFlags flags;
 
 	EMFormatHandler *old;
@@ -127,7 +124,7 @@ struct _EMFormatWriterInfo {
 	gboolean headers_collapsable;
 	gboolean headers_collapsed;
 
-	/* When TRUE, EMPartObjectWriteFunc's will put the content of the EMPart
+	/* When TRUE, EMFormatWriteFunc's will put the content of the PURI part
 	   between EFH_HTML_HEADER and EFH_HTML_FOOTER */
 	gboolean with_html_header;
 };
@@ -141,6 +138,28 @@ struct _EMFormatHeader {
 #define EM_FORMAT_HEADER_BOLD (1<<0)
 #define EM_FORMAT_HEADER_LAST (1<<4) /* reserve 4 slots */
 
+
+struct _EMFormatPURI {
+	CamelMimePart *part;
+
+	EMFormat *emf;
+	EMFormatWriteFunc write_func;
+	EMFormatWidgetFunc widget_func;
+
+	gchar *uri;
+	gchar *cid;
+	gchar *mime_type;
+
+	/* EM_FORMAT_VALIDITY_* flags */
+	guint32 validity_type;
+	CamelCipherValidity *validity;
+	CamelCipherValidity *validity_parent;
+
+	gboolean is_attachment;
+
+	void (*free)(EMFormatPURI *puri); /* optional callback for freeing user-fields */
+};
+
 struct _EMFormat {
 	GObject parent;
 	EMFormatPrivate *priv;
@@ -213,9 +232,9 @@ void	        	em_format_remove_header		(EMFormat *emf,
 void                    em_format_remove_header_struct	(EMFormat *emf,
 							 const EMFormatHeader *header);
 
-void			em_format_add_part_object	(EMFormat *emf,
-							 EMPart *empo);
-EMPart*			em_format_find_part_object	(EMFormat *emf,
+void			em_format_add_puri		(EMFormat *emf,
+							 EMFormatPURI *puri);
+EMFormatPURI*		em_format_find_puri		(EMFormat *emf,
 							 const gchar *id);
 
 void			em_format_class_add_handler	(EMFormatClass *emfc,
@@ -233,11 +252,6 @@ void			em_format_parse			(EMFormat *emf,
 							 CamelFolder *folder,
 							 GCancellable *cancellable);
 
-void                    em_format_write                 (EMFormat *emf,
-                                                         CamelStream *stream,
-                                                         EMFormatWriterInfo *info,
-                                                         GCancellable *cancellable);
-
 void                    em_format_parse_async           (EMFormat *emf,
                                                          CamelMimeMessage *message,
                                                          CamelFolder *folder,
@@ -289,10 +303,10 @@ void			em_format_empty_parser 		(EMFormat *emf,
 							 EMFormatParserInfo *info,
 							 GCancellable *cancellable);
 
-/* EMPartObjectWriteFunc that does nothing. Use it to disable
+/* EMFormatWriteFunc that does nothing. Use it to disable
  * writing of a specific mime type parts */
 void			em_format_empty_writer 		(EMFormat *emf,
-							 EMPart *empo,
+							 EMFormatPURI *puri,
 							 CamelStream *stream,
 							 EMFormatWriterInfo *info,
 							 GCancellable *cancellable);
@@ -300,6 +314,17 @@ void			em_format_empty_writer 		(EMFormat *emf,
 void			em_format_redraw		(EMFormat *emf);
 
 
+EMFormatPURI*		em_format_puri_new 		(EMFormat *emf,
+							 gsize puri_size,
+							 CamelMimePart *part,
+							 const gchar *uri);
+void			em_format_puri_free 		(EMFormatPURI *puri);
+
+void			em_format_puri_write 		(EMFormatPURI *puri,
+							 CamelStream *stream,
+							 EMFormatWriterInfo *info,
+							 GCancellable *cancellable);
+
 EMFormatHeader*		em_format_header_new		(const gchar *name,
 							 const gchar *value);
 void			em_format_header_free		(EMFormatHeader *header);
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 3ca6fc4..48119c1 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -83,7 +83,6 @@ mailinclude_HEADERS =					\
 	em-folder-utils.h				\
 	em-format-hook.h				\
 	em-format-html-display.h			\
-	em-format-html-display-parts.h			\
 	em-format-html-print.h				\
 	em-format-html.h				\
 	em-search-context.h				\
@@ -150,7 +149,6 @@ libevolution_mail_la_SOURCES =				\
 	em-folder-utils.c				\
 	em-format-hook.c				\
 	em-format-html-display.c			\
-	em-format-html-display-parts.c			\
 	em-format-html-print.c				\
 	em-format-html.c				\
 	em-search-context.c				\
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 4220058..ea59a6d 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -11,8 +11,6 @@
 
 #include "em-format-html.h"
 
-#include <em-format/em-part.h>
-
 #include <e-util/e-icon-factory.h>
 #include <e-util/e-util.h>
 
@@ -25,7 +23,7 @@ struct _EMailRequestPrivate {
 	EMFormatHTML *efh;
 
 	CamelStream *output_stream;
-	EMPart *emp;
+	EMFormatPURI *puri;
 	gchar *mime_type;
 
 	gint content_length;
@@ -47,8 +45,6 @@ handle_mail_request (GSimpleAsyncResult *res,
 	GInputStream *stream;
 	GByteArray *ba;
 	gchar *part_id;
-        EMFormatWriterInfo info = {0};
-        gchar *val;
 
 	if (g_cancellable_is_cancelled (cancellable))
 		return;
@@ -61,33 +57,34 @@ handle_mail_request (GSimpleAsyncResult *res,
 
 	part_id = g_hash_table_lookup (request->priv->uri_query, "part_id");
 
-        val = g_hash_table_lookup (request->priv->uri_query, "headers_collapsed");
-        if (val)
-                info.headers_collapsed = atoi (val);
+	if (part_id) {
+                /* original part_id is owned by the GHashTable */
+                part_id = soup_uri_decode (part_id);
+		request->priv->puri = em_format_find_puri (emf, part_id);
 
-        val = g_hash_table_lookup (request->priv->uri_query, "headers_collapsable");
-        if (val)
-                info.headers_collapsable = atoi (val);
+		if (request->priv->puri) {
+			EMFormatWriterInfo info = {0};
+			gchar *val;
 
-        val = g_hash_table_lookup (request->priv->uri_query, "mode");
-        if (val)
-                info.mode = atoi (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, "with_html_headers");
-        if (val)
-                info.with_html_header = atoi (val);
-        else
-                info.with_html_header = FALSE; /* By default this is TRUE!! */
+			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);
 
-	if (part_id) {
-                /* original part_id is owned by the GHashTable */
-                part_id = soup_uri_decode (part_id);
-                request->priv->emp = em_format_find_part_object (emf, part_id);
+			val = g_hash_table_lookup (request->priv->uri_query, "with_html_headers");
+			if (val)
+				info.with_html_header = atoi (val);
+			else
+				info.with_html_header = TRUE; /* By default this is TRUE!! */
 
-		if (request->priv->emp) {
-                        em_part_write (request->priv->emp, request->priv->output_stream,
-                                &info, NULL);
+			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);
 		}
@@ -439,7 +436,7 @@ e_mail_request_init (EMailRequest *request)
 	request->priv->efh = NULL;
 	request->priv->output_stream = NULL;
 	request->priv->uri_query = NULL;
-	request->priv->emp = NULL;
+	request->priv->puri = NULL;
 	request->priv->mime_type = NULL;
 	request->priv->content_length = 0;
 }
@@ -474,11 +471,6 @@ mail_request_finalize (GObject *object)
                 request->priv->ret_data = NULL;
         }
 
-        if (request->priv->emp) {
-		g_object_unref (request->priv->emp);
-		request->priv->emp = NULL;
-	}
-
 	G_OBJECT_CLASS (e_mail_request_parent_class)->finalize (object);
 }
 
@@ -534,7 +526,7 @@ mail_request_send_async (SoupRequest *request,
         formatters = g_object_get_data (G_OBJECT (session), "formatters");
                                         g_return_if_fail (formatters != NULL);
 
-        /* Get HTML content of given EMPart */
+        /* Get HTML content of given PURI part */
         if (g_strcmp0 (uri->scheme, "mail") == 0) {
                 gchar *uri_str;
 
@@ -621,27 +613,17 @@ static const gchar*
 mail_request_get_content_type (SoupRequest *request)
 {
 	EMailRequest *emr = E_MAIL_REQUEST (request);
-	gchar *mime_type, *part_mime_type;
-
-	if (emr->priv->emp)
-		part_mime_type = em_part_get_mime_type (emr->priv->emp);
-	else
-		part_mime_type = NULL;
+	gchar *mime_type;
 
 	if (emr->priv->mime_type) {
 		mime_type = g_strdup (emr->priv->mime_type);
-	} else if (!emr->priv->emp) {
+	} else if (!emr->priv->puri) {
 		mime_type = g_strdup ("text/html");
-	} else if (!part_mime_type) {
-		CamelMimePart *part;
-		CamelContentType *ct;
-		
-		part = em_part_get_mime_part (emr->priv->emp);
-		ct = camel_mime_part_get_content_type (part);
+	} else if (!emr->priv->puri->mime_type) {
+		CamelContentType *ct = camel_mime_part_get_content_type (emr->priv->puri->part);
 		mime_type = camel_content_type_simple (ct);
-		g_object_unref (part);
 	} else {
-		mime_type = em_part_get_mime_type (emr->priv->emp);
+		mime_type = g_strdup (emr->priv->puri->mime_type);
 	}
 
 	if (g_strcmp0 (mime_type, "text/html") == 0) {
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 130b4bd..d119695 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -60,7 +60,6 @@
 #include "e-mail-display.h"
 #include "e-mail-attachment-bar.h"
 #include "em-format-html-display.h"
-#include "em-format-html-display-parts.h"
 #include "em-utils.h"
 #include "widgets/misc/e-attachment.h"
 #include "widgets/misc/e-attachment-button.h"
@@ -114,10 +113,11 @@ static void efhd_parse_attachment	(EMFormat *emf, CamelMimePart *part, GString *
 static void efhd_parse_secure		(EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 static void efhd_parse_optional		(EMFormat *emf, CamelMimePart *part, GString *part_id, EMFormatParserInfo *info, GCancellable *cancellable);
 
-static GtkWidget* efhd_attachment_bar		(EMFormat *emf, EMPart *emp, GCancellable *cancellable);
-static GtkWidget* efhd_attachment_button	(EMFormat *emf, EMPart *emp, GCancellable *cancellable);
-static GtkWidget* efhd_attachment_optional	(EMFormat *emf, EMPart *emp, GCancellable *cancellable);
+static GtkWidget* efhd_attachment_bar		(EMFormat *emf, EMFormatPURI *puri, GCancellable *cancellable);
+static GtkWidget* efhd_attachment_button	(EMFormat *emf, EMFormatPURI *puri, GCancellable *cancellable);
+static GtkWidget* efhd_attachment_optional	(EMFormat *emf, EMFormatPURI *puri, GCancellable *cancellable);
 
+static void efhd_free_attach_puri_data (EMFormatPURI *puri);
 static void efhd_builtin_init (EMFormatHTMLDisplayClass *efhc);
 
 static gpointer parent_class;
@@ -126,7 +126,7 @@ static EAttachmentStore*
 find_parent_attachment_store (EMFormatHTMLDisplay *efhd, GString *part_id)
 {
 	EMFormat *emf = (EMFormat *) efhd;
-        EMPartAttachmentBar *empab;
+	EMFormatAttachmentBarPURI *abp;
 	gchar *tmp, *pos;
         GList *item;
 
@@ -151,27 +151,55 @@ find_parent_attachment_store (EMFormatHTMLDisplay *efhd, GString *part_id)
 
 	g_free (tmp);
 
-	empab = item->data;
+	abp = (EMFormatAttachmentBarPURI *) item->data;
 
-        if (empab)
-	        return em_part_attachment_bar_get_store (empab);
+        if (abp)
+	        return abp->store;
         else
                 return NULL;
 }
 
 static void
+efhd_attachment_bar_puri_free (EMFormatPURI *puri)
+{
+	EMFormatAttachmentBarPURI *abp;
+
+	abp = (EMFormatAttachmentBarPURI *) puri;
+
+	if (abp->store) {
+		g_object_unref (abp->store);
+		abp->store = NULL;
+	}
+}
+
+static void
+efhd_xpkcs7mime_free (EMFormatPURI *puri)
+{
+	EMFormatSMIMEPURI *sp = (EMFormatSMIMEPURI *) puri;
+
+	if (sp->widget)
+		gtk_widget_destroy (sp->widget);
+
+	if (sp->description)
+		g_free (sp->description);
+
+	if (sp->valid)
+		camel_cipher_validity_free (sp->valid);
+}
+
+static void
 efhd_xpkcs7mime_info_response (GtkWidget *widget,
                                guint button,
-                               EMPartSMIME *emps)
+                               EMFormatSMIMEPURI *po)
 {
 	gtk_widget_destroy (widget);
-	em_part_smime_set_widget (emps, NULL);
+	po->widget = NULL;
 }
 
 #if defined (HAVE_NSS) && defined (ENABLE_SMIME)
 static void
 efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
-                                  EMPartSMIME *emps)
+                                  EMFormatSMIMEPURI *po)
 {
 	CamelCipherCertInfo *info = g_object_get_data((GObject *)button, "e-cert-info");
 	ECert *ec = NULL;
@@ -181,7 +209,6 @@ efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
 
 	if (ec != NULL) {
 		GtkWidget *w = certificate_viewer_show (ec);
-		GtkWidget *widget;
 
 		/* oddly enough certificate_viewer_show doesn't ... */
 		gtk_widget_show (w);
@@ -189,12 +216,8 @@ efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
 			w, "response",
 			G_CALLBACK (gtk_widget_destroy), NULL);
 
-		widget = em_part_smime_get_widget (emps);
-		if (w && widget)
-			gtk_window_set_transient_for ((GtkWindow *) w, (GtkWindow *) widget);
-
-		if (widget)
-			g_object_unref (widget);
+		if (w && po->widget)
+			gtk_window_set_transient_for ((GtkWindow *) w, (GtkWindow *) po->widget);
 
 		g_object_unref (ec);
 	} else {
@@ -206,7 +229,7 @@ efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
 static void
 efhd_xpkcs7mime_add_cert_table (GtkWidget *grid,
                                 GQueue *certlist,
-                                EMPartSMIME *emps)
+                                EMFormatSMIMEPURI *po)
 {
 	GList *head, *link;
 	GtkTable *table;
@@ -268,39 +291,31 @@ efhd_xpkcs7mime_add_cert_table (GtkWidget *grid,
 
 static void
 efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
-                                  EMPartSMIME *emps)
+                                  EMFormatPURI *puri)
 {
+	EMFormatSMIMEPURI *po = (EMFormatSMIMEPURI *) puri;
 	GtkBuilder *builder;
 	GtkWidget *grid, *w;
-	GtkWidget *part_widget;
-	CamelCipherValidity *validity;
 
-	part_widget = em_part_smime_get_widget (emps);
-	if (part_widget) {
-		g_object_unref (part_widget);
+	if (po->widget)
 		/* FIXME: window raise? */
 		return;
-	}
-
-	validity = em_part_get_validity ((EMPart *) emps);
 
 	builder = gtk_builder_new ();
 	e_load_ui_builder_definition (builder, "mail-dialogs.ui");
 
-	part_widget = e_builder_get_widget(builder, "message_security_dialog");
-	em_part_smime_set_widget (emps, part_widget);
+	po->widget = e_builder_get_widget(builder, "message_security_dialog");
 
 	grid = e_builder_get_widget(builder, "signature_grid");
-	w = gtk_label_new (_(smime_sign_table[validity->sign.status].description));
+	w = gtk_label_new (_(smime_sign_table[po->valid->sign.status].description));
 	gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
 	gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
 	gtk_container_add (GTK_CONTAINER (grid), w);
-	if (validity->sign.description) {
+	if (po->valid->sign.description) {
 		GtkTextBuffer *buffer;
 
 		buffer = gtk_text_buffer_new (NULL);
-		gtk_text_buffer_set_text (buffer, validity->sign.description, 
-			strlen (validity->sign.description));
+		gtk_text_buffer_set_text (buffer, po->valid->sign.description, strlen (po->valid->sign.description));
 		w = g_object_new (gtk_scrolled_window_get_type (),
 				 "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
 				 "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
@@ -320,21 +335,20 @@ efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
 	}
 
 	if (!g_queue_is_empty (&po->valid->sign.signers))
-		efhd_xpkcs7mime_add_cert_table (grid, &validity->sign.signers, emps);
+		efhd_xpkcs7mime_add_cert_table (grid, &po->valid->sign.signers, po);
 
 	gtk_widget_show_all (grid);
 
 	grid = e_builder_get_widget(builder, "encryption_grid");
-	w = gtk_label_new (_(smime_encrypt_table[validity->encrypt.status].description));
+	w = gtk_label_new (_(smime_encrypt_table[po->valid->encrypt.status].description));
 	gtk_misc_set_alignment ((GtkMisc *) w, 0.0, 0.5);
 	gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
 	gtk_container_add (GTK_CONTAINER (grid), w);
-	if (validity->encrypt.description) {
+	if (po->valid->encrypt.description) {
 		GtkTextBuffer *buffer;
 
 		buffer = gtk_text_buffer_new (NULL);
-		gtk_text_buffer_set_text (buffer, validity->encrypt.description,
-			strlen (validity->encrypt.description));
+		gtk_text_buffer_set_text (buffer, po->valid->encrypt.description, strlen (po->valid->encrypt.description));
 		w = g_object_new (gtk_scrolled_window_get_type (),
 				 "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
 				 "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
@@ -354,8 +368,7 @@ efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
 	}
 
 	if (!g_queue_is_empty (&po->valid->encrypt.encrypters))
-		efhd_xpkcs7mime_add_cert_table (grid, 
-			&validity->encrypt.encrypters, emps);
+		efhd_xpkcs7mime_add_cert_table (grid, &po->valid->encrypt.encrypters, po);
 
 	gtk_widget_show_all (grid);
 
@@ -372,29 +385,23 @@ efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
 
 static GtkWidget*
 efhd_xpkcs7mime_button (EMFormat *emf,
-                        EMPart *emp,
+                        EMFormatPURI *puri,
                         GCancellable *cancellable)
 {
 	GtkWidget *box, *button, *layout, *widget;
-	EMPartSMIME *emps = (EMPartSMIME *) emp;
+	EMFormatSMIMEPURI *po = (EMFormatSMIMEPURI *) puri;
 	const gchar *icon_name;
-	gchar *description;
-	CamelCipherValidity *validity;
-
-	validity = em_part_get_validity (emp);
-	if (!validity)
-		return NULL;
 
 	/* FIXME: need to have it based on encryption and signing too */
-	if (validity->sign.status != 0)
-		icon_name = smime_sign_table[validity->sign.status].icon;
+	if (po->valid->sign.status != 0)
+		icon_name = smime_sign_table[po->valid->sign.status].icon;
 	else
-		icon_name = smime_encrypt_table[validity->encrypt.status].icon;
+		icon_name = smime_encrypt_table[po->valid->encrypt.status].icon;
 
 	box = gtk_event_box_new ();
-	if (validity->sign.status != 0)
+	if (po->valid->sign.status != 0)
 		gtk_widget_override_background_color (box, GTK_STATE_FLAG_NORMAL,
-			&smime_sign_colour[validity->sign.status]);
+			&smime_sign_colour[po->valid->sign.status]);
 
 	layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
 	gtk_container_add (GTK_CONTAINER (box), layout);
@@ -402,21 +409,17 @@ efhd_xpkcs7mime_button (EMFormat *emf,
 	button = gtk_button_new ();
 	gtk_box_pack_start (GTK_BOX (layout), button, FALSE, FALSE, 0);
 	g_signal_connect (button, "clicked",
-		G_CALLBACK (efhd_xpkcs7mime_validity_clicked), emp);
+		G_CALLBACK (efhd_xpkcs7mime_validity_clicked), puri);
 
 	widget = gtk_image_new_from_icon_name (
 			icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
 	gtk_button_set_image (GTK_BUTTON (button), widget);
 
-	description = em_part_smime_get_description (emps);
-	widget = gtk_label_new (description);
+	widget = gtk_label_new (po->description);
 	gtk_box_pack_start (GTK_BOX (layout), widget, FALSE, FALSE, 0);
 
 	gtk_widget_show_all (box);
 
-	g_free (description);
-	camel_cipher_validity_free (validity);
-
 	return box;
 }
 
@@ -464,9 +467,8 @@ efhd_parse_attachment (EMFormat *emf,
 {
 	gchar *text, *html;
 	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
-	EMPartAttachment *empa;
+	EMFormatAttachmentPURI *puri;
 	EAttachmentStore *store;
-	EAttachment *attachment;
 	const EMFormatHandler *handler;
 	CamelContentType *ct;
 	gchar *mime_type;
@@ -496,46 +498,39 @@ efhd_parse_attachment (EMFormat *emf,
 	g_free (text);
 	g_free (mime_type);
 
-        attachment = e_attachment_new ();
-        empa = EM_PART_ATTACHMENT (em_part_attachment_new (emf, part, 
-                        part_id->str, NULL));
-        em_part_set_widget_func ((EMPart *) empa, efhd_attachment_button);
-        em_part_attachment_set_is_shown (empa, 
-                (handler && em_format_is_inline (emf, part_id->str, part, handler)));
-        em_part_attachment_set_snoop_mime_type (empa, em_format_snoop_type (part));
-	em_part_attachment_set_attachment (empa, attachment);
-        em_part_attachment_set_view_part_id (empa, part_id->str);
-        em_part_attachment_set_description (empa, html);
-	em_part_attachment_set_handler (empa, handler);
-        em_part_set_validity ((EMPart *) empa, info->validity);
+	puri = (EMFormatAttachmentPURI*) em_format_puri_new (
+			emf, sizeof (EMFormatAttachmentPURI), part, part_id->str);
+	puri->puri.free = efhd_free_attach_puri_data;
+	puri->puri.widget_func = efhd_attachment_button;
+	puri->shown = (handler && em_format_is_inline (emf, part_id->str, part, handler));
+	puri->snoop_mime_type = em_format_snoop_type (part);
+	puri->attachment = e_attachment_new ();
+	puri->attachment_view_part_id = g_strdup (part_id->str);
+	puri->description = html;
+	puri->handle = handler;
+        if (info->validity)
+                puri->puri.validity = camel_cipher_validity_clone (info->validity);
 
 	cid = camel_mime_part_get_content_id (part);
-	if (cid) {
-                gchar *new_cid = g_strdup_printf ("cid:%s", cid);
-                em_part_set_cid ((EMPart *) empa, new_cid);
-		g_free (new_cid);
-        }
+	if (cid)
+		puri->puri.cid = g_strdup_printf ("cid:%s", cid);
 
 	if (handler) {
                 CamelContentType *ct;
-                em_part_set_write_func ((EMPart *) empa, handler->write_func);
+                puri->puri.write_func = handler->write_func;
 
                 /* This mime_type is important for WebKit to determine content type.
                  * We have converted text/ * to text/html, other (binary) formats remained
                  * untouched. */
                 ct = camel_content_type_decode (handler->mime_type);
                 if (g_strcmp0 (ct->type, "text") == 0)
-                        em_part_set_mime_type ((EMPart *) empa, "text/html");
-                else {
-                        gchar *ct_s = camel_content_type_simple (ct);
-                        em_part_set_mime_type ((EMPart *) empa, ct_s);
-                        g_free (ct_s);
-                }
-
+                        puri->puri.mime_type = g_strdup ("text/html");
+                else
+                        puri->puri.mime_type = camel_content_type_simple (ct);
                 camel_content_type_unref (ct);
         }
 
-        em_format_add_part_object (emf, (EMPart *) empa);
+	em_format_add_puri (emf, (EMFormatPURI *) puri);
 
         /* Though it is an attachment, we still might be able to parse it and
          * so discover some parts that we might be event able to display. */
@@ -544,34 +539,34 @@ efhd_parse_attachment (EMFormat *emf,
              (handler->flags & EM_FORMAT_HANDLER_INLINE_DISPOSITION))) {
                 EMFormatParserInfo attachment_info = { .handler = handler,
                                                        .is_attachment = TRUE };
-                handler->parse_func (emf, part, part_id, &attachment_info, cancellable);
+                handler->parse_func (emf, puri->puri.part, part_id, &attachment_info, cancellable);
         }
 
-	e_attachment_set_mime_part (attachment, part);
-	e_attachment_set_shown (attachment, em_part_attachment_get_is_shown (empa));
-        if (info->validity) {
-	        e_attachment_set_signed (attachment, info->validity->sign.status);
-	        e_attachment_set_encrypted (attachment, info->validity->encrypt.status);
+	e_attachment_set_mime_part (puri->attachment, part);
+	e_attachment_set_shown (puri->attachment, puri->shown);
+        if (puri->puri.validity) {
+	        e_attachment_set_signed (puri->attachment, puri->puri.validity->sign.status);
+	        e_attachment_set_encrypted (puri->attachment, puri->puri.validity->encrypt.status);
         }
-	e_attachment_set_can_show (attachment, handler != NULL && handler->write_func);
+	e_attachment_set_can_show (puri->attachment, puri->handle != NULL && puri->handle->write_func);
 
 	store = find_parent_attachment_store (efhd, part_id);
-	e_attachment_store_add_attachment (store, attachment);
+	e_attachment_store_add_attachment (store, puri->attachment);
 
 	if (emf->folder && emf->folder->summary && emf->message_uid) {
-                CamelDataWrapper *dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+                CamelDataWrapper *dw = camel_medium_get_content (CAMEL_MEDIUM (puri->puri.part));
                 GByteArray *ba;
                 ba = camel_data_wrapper_get_byte_array (dw);
                 if (ba) {
                         size = ba->len;
 
-                        if (camel_mime_part_get_encoding (part) == CAMEL_TRANSFER_ENCODING_BASE64)
+                        if (camel_mime_part_get_encoding (puri->puri.part) == CAMEL_TRANSFER_ENCODING_BASE64)
                                 size = size / 1.37;
                 }
 	}
 
 	load_data = g_new0 (struct attachment_load_data, 1);
-	load_data->attachment = g_object_ref (attachment);
+	load_data->attachment = g_object_ref (puri->attachment);
 	load_data->flag = e_flag_new ();
 
         e_flag_clear (load_data->flag);
@@ -588,9 +583,9 @@ efhd_parse_attachment (EMFormat *emf,
 	if (size != 0) {
 		GFileInfo *fileinfo;
 
-		fileinfo = e_attachment_get_file_info (attachment);
+		fileinfo = e_attachment_get_file_info (puri->attachment);
 		g_file_info_set_size (fileinfo, size);
-		e_attachment_set_file_info (attachment, fileinfo);
+		e_attachment_set_file_info (puri->attachment, fileinfo);
 	}
 
 	g_string_truncate (part_id, len);
@@ -603,42 +598,35 @@ efhd_parse_optional (EMFormat *emf,
                      EMFormatParserInfo *info,
                      GCancellable *cancellable)
 {
-	EMPartAttachment *empa;
-	EAttachment *attachment;
-	CamelStream *stream;
+	EMFormatAttachmentPURI *puri;
         gint len;
 
         len = part_id->len;
         g_string_append (part_id, ".optional");
 
-	attachment = e_attachment_new ();
-	empa = (EMPartAttachment *) em_part_attachment_new (
-			emf, part, part_id->str, NULL);
-	em_part_attachment_set_view_part_id (empa, part_id->str);
-	em_part_attachment_set_handler (empa, em_format_find_handler (emf, "text/plain"));
-	em_part_attachment_set_is_shown (empa, FALSE);
-	em_part_attachment_set_snoop_mime_type (empa, "text/plain");
-	em_part_attachment_set_attachment (empa, attachment);
-	em_part_set_widget_func ((EMPart *) empa, efhd_attachment_optional);
-	
-	e_attachment_set_mime_part (attachment, part);
-	em_part_attachment_set_description (empa, 
-		N_("Evolution cannot render this email as it is too "
-		  "large to process. You can view it unformatted or "
-		  "with an external text editor."));
+	puri = (EMFormatAttachmentPURI *) em_format_puri_new (
+			emf, sizeof (EMFormatAttachmentPURI), part, part_id->str);
+	puri->puri.free = efhd_free_attach_puri_data;
+	puri->puri.widget_func = efhd_attachment_optional;
+	puri->attachment_view_part_id = g_strdup (part_id->str);
+	puri->handle = em_format_find_handler (emf, "text/plain");
+	puri->shown = FALSE;
+	puri->snoop_mime_type = "text/plain";
+	puri->attachment = e_attachment_new ();
+	e_attachment_set_mime_part (puri->attachment, puri->puri.part);
+	puri->description = g_strdup(_("Evolution cannot render this email as it is too "
+				       "large to process. You can view it unformatted or "
+				       "with an external text editor."));
 	
-
-	stream = camel_stream_mem_new ();
-	em_part_attachment_set_mstream (empa, stream);	
-
+	puri->mstream = CAMEL_STREAM_MEM (camel_stream_mem_new ());
 	camel_data_wrapper_decode_to_stream_sync ((CamelDataWrapper *) part, 
-		(CamelStream *) stream, cancellable, NULL);
+		(CamelStream *) puri->mstream, cancellable, NULL);
 
 	if (info->validity) {
-		em_part_set_validity ((EMPart *) empa, info->validity);
+		puri->puri.validity = camel_cipher_validity_clone (info->validity);
 	}
 
-	em_format_add_part_object (emf, (EMPart *) empa);
+	em_format_add_puri (emf, (EMFormatPURI *) puri);
 
 	g_string_truncate (part_id, len);
 }
@@ -654,13 +642,15 @@ efhd_parse_secure (EMFormat *emf,
 	    && (info->validity->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
 		|| info->validity->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) {
 		GString *buffer;
-                EMPart *emp;
+		EMFormatSMIMEPURI *pobj;
+
+		pobj = (EMFormatSMIMEPURI *) em_format_puri_new (
+				emf, sizeof (EMFormatSMIMEPURI), part, part_id->str);
+		pobj->puri.free = efhd_xpkcs7mime_free;
+		pobj->valid = camel_cipher_validity_clone (info->validity);
+		pobj->puri.widget_func = efhd_xpkcs7mime_button;
 
-                emp = em_part_smime_new (emf, part, part_id->str, NULL);
-                em_part_set_widget_func (emp, efhd_xpkcs7mime_button);
-                em_part_set_validity (emp, info->validity);
-		
-                em_format_add_part_object (emf, emp);
+		em_format_add_puri (emf, (EMFormatPURI*) pobj);
 
 		buffer = g_string_new ("");
 
@@ -689,8 +679,7 @@ efhd_parse_secure (EMFormat *emf,
 			g_string_append (buffer, gettext (desc));
 		}
 
-		em_part_smime_set_description ((EMPartSMIME *) emp, buffer->str);
-		g_string_free (buffer, TRUE);
+		pobj->description = g_string_free (buffer, FALSE);
 	}
 }
 
@@ -801,25 +790,20 @@ efhd_message_prefix (EMFormat *emf,
 	time_t date;
 	gchar *iconpath, *due_date_str;
 	GString *buffer;
-	EMPartAttachment *empa;
+	EMFormatAttachmentPURI *puri;
 
-	if ((emf->folder == NULL) || (emf->message_uid == NULL)
-	    || ((flag = camel_folder_get_message_user_tag (emf->folder,
-				emf->message_uid, "follow-up")) == NULL)
-	    || (flag[0] == 0))
+	if (emf->folder == NULL || emf->message_uid == NULL
+	    || (flag = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "follow-up")) == NULL
+	    || flag[0] == 0)
 		return;
 
-	empa = (EMPartAttachment *) em_part_attachment_new (
-			emf, part, ".message_prefix", NULL);
-	em_part_attachment_set_view_part_id (empa, part_id->str);
+	puri = (EMFormatAttachmentPURI *) em_format_puri_new (
+			emf, sizeof (EMFormatAttachmentPURI), part, ".message_prefix");
 
-	comp = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "completed-on");
-	iconpath = e_icon_factory_get_icon_filename (
-		comp && comp[0] ?
-			"stock_mail-flag-for-followup-done" :
-			"stock_mail-flag-for-followup", 
-		GTK_ICON_SIZE_MENU);
+	puri->attachment_view_part_id = g_strdup (part_id->str);
 
+	comp = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "completed-on");
+	iconpath = e_icon_factory_get_icon_filename (comp && comp[0] ? "stock_mail-flag-for-followup-done" : "stock_mail-flag-for-followup", GTK_ICON_SIZE_MENU);
 	if (iconpath) {
 		gchar *classid;
 
@@ -828,7 +812,7 @@ efhd_message_prefix (EMFormat *emf,
 			part_id->str,
 			comp && comp[0] ? "comp" : "uncomp");
 
-		em_part_set_uri ((EMPart *) empa, classid);
+		puri->puri.uri = classid;
 
 		g_free (classid);
 	}
@@ -844,8 +828,7 @@ efhd_message_prefix (EMFormat *emf,
 			flag, _("Completed on"),
 			due_date_str ? due_date_str : "???");
 		g_free (due_date_str);
-	} else if ((due = camel_folder_get_message_user_tag (emf->folder, 
-			emf->message_uid, "due-by")) != NULL && due[0]) {
+	} else if ((due = camel_folder_get_message_user_tag(emf->folder, emf->message_uid, "due-by")) != NULL && due[0]) {
 		time_t now;
 
 		date = camel_header_decode_date (due, NULL);
@@ -869,8 +852,7 @@ efhd_message_prefix (EMFormat *emf,
 		g_string_append (buffer, flag);
 	}
 
-	em_part_attachment_set_description (empa, buffer->str);
-	g_string_free (buffer, TRUE);
+	puri->description = g_string_free (buffer, FALSE);
 }
 
 /* ********************************************************************** */
@@ -878,11 +860,10 @@ efhd_message_prefix (EMFormat *emf,
 /* attachment button callback */
 static GtkWidget*
 efhd_attachment_button (EMFormat *emf,
-			EMPart *emp,
+			EMFormatPURI *puri,
 			GCancellable *cancellable)
 {
-	EMPartAttachment *empa = (EMPartAttachment *) emp;
-	EAttachment *attachment;
+	EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
 	GtkWidget *widget;
 
 	/* FIXME: handle default shown case */
@@ -891,38 +872,29 @@ efhd_attachment_button (EMFormat *emf,
 	if (g_cancellable_is_cancelled (cancellable))
 		return NULL;
 
-	widget = em_part_attachment_get_forward_widget (empa);
-	if (widget) {
+	if (!info || info->forward) {
 		g_warning ("unable to expand the attachment\n");
-		g_object_unref (widget);
 		return NULL;
 	}
-	g_object_unref (widget);
 
-	attachment = em_part_attachment_get_attachment (empa);
 	widget = e_attachment_button_new ();
 	e_attachment_button_set_attachment (
-		E_ATTACHMENT_BUTTON (widget), attachment);
+		E_ATTACHMENT_BUTTON (widget), info->attachment);
 	gtk_widget_set_can_focus (widget, TRUE);
 	gtk_widget_show (widget);
 
-	g_object_unref (attachment);
-
 	return widget;
 }
 
 static GtkWidget*
 efhd_attachment_bar (EMFormat *emf,
-		     EMPart *emp,
+		     EMFormatPURI *puri,
 		     GCancellable *cancellable)
 {
-	EMPartAttachmentBar *empab = (EMPartAttachmentBar *) emp;
+	EMFormatAttachmentBarPURI *abp = (EMFormatAttachmentBarPURI *) puri;
 	GtkWidget *widget;
-	EAttachmentStore *store;
 
-	store = em_part_attachment_bar_get_store (empab);
-	widget = e_mail_attachment_bar_new (store);
-	g_object_unref (store);
+	widget = e_mail_attachment_bar_new (abp->store);
 
 	return widget;
 }
@@ -934,8 +906,7 @@ efhd_message_add_bar (EMFormat *emf,
                       EMFormatParserInfo *info,
                       GCancellable *cancellable)
 {
-	EMPart *emp;
-	EAttachmentStore *store;
+	EMFormatAttachmentBarPURI *puri;
 	gint len;
 
 	if (g_cancellable_is_cancelled (cancellable))
@@ -943,18 +914,15 @@ efhd_message_add_bar (EMFormat *emf,
 
 	len = part_id->len;
 	g_string_append (part_id, ".attachment-bar");
+	puri = (EMFormatAttachmentBarPURI *) em_format_puri_new (
+			emf, sizeof (EMFormatAttachmentBarPURI), part, part_id->str);
+	puri->puri.widget_func = efhd_attachment_bar;
+	puri->puri.free = efhd_attachment_bar_puri_free;
+	puri->store = E_ATTACHMENT_STORE (e_attachment_store_new ());
 
-        store = E_ATTACHMENT_STORE (e_attachment_store_new ());
-
-        emp = em_part_attachment_bar_new (emf, part, part_id->str, NULL);
-        em_part_set_widget_func (emp, efhd_attachment_bar);
-        em_part_attachment_bar_set_store ((EMPartAttachmentBar *) emp, store);
-        em_format_add_part_object (emf, emp);
+	em_format_add_puri (emf, (EMFormatPURI*) puri);
 
 	g_string_truncate (part_id, len);
-
-        /* Store is now owned only by the EMPart */
-        g_object_unref (store);
 }
 
 static void
@@ -976,7 +944,7 @@ efhd_optional_button_show (GtkWidget *widget,
 /* optional render attachment button callback */
 static GtkWidget*
 efhd_attachment_optional (EMFormat *efh,
-			  EMPart *emp,
+			  EMFormatPURI *puri,
 			  GCancellable *cancellable)
 {
 	GtkWidget *hbox, *vbox, *button, *mainbox, *scroll, *label, *img;
@@ -984,9 +952,7 @@ efhd_attachment_optional (EMFormat *efh,
 	GtkWidget *view;
 	GtkTextBuffer *buffer;
 	GByteArray *byte_array;
-	EMPartAttachment *empa = (EMPartAttachment *) emp;
-	const EMFormatHandler *handler;
-	CamelStream *stream;
+	EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
 
 	if (g_cancellable_is_cancelled (cancellable))
 		return NULL;
@@ -994,13 +960,10 @@ efhd_attachment_optional (EMFormat *efh,
 	/* FIXME: handle default shown case */
 	d(printf("adding attachment button/content for optional rendering\n"));
 
-	button = em_part_attachment_get_forward_widget (empa);
-	if (button) {
+	if (!info || info->forward) {
 		g_warning ("unable to expand the attachment\n");
-		g_object_unref (button);
 		return NULL;
 	}
-	g_object_unref (button);
 
 	scroll = gtk_scrolled_window_new (NULL, NULL);
 	mainbox = gtk_hbox_new (FALSE, 0);
@@ -1015,9 +978,7 @@ efhd_attachment_optional (EMFormat *efh,
 	gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 2);
 	gtk_widget_show_all (hbox);
 	gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (hbox));
-
-	handler = em_part_attachment_get_handler (empa);
-	if (handler)
+	if (info->handle)
 		g_signal_connect (
 			button, "clicked",
 			G_CALLBACK (efhd_optional_button_show), scroll);
@@ -1054,14 +1015,11 @@ efhd_attachment_optional (EMFormat *efh,
 	gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
 	gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-
-	stream = em_part_attachment_get_mstream (empa);
-	byte_array = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (stream));
+	byte_array = camel_stream_mem_get_byte_array (info->mstream);
 	gtk_text_buffer_set_text (
 		buffer, (gchar *) byte_array->data, byte_array->len);
-	g_object_unref (stream);
-	em_part_attachment_set_mstream (empa, NULL);
-
+	g_object_unref (info->mstream);
+	info->mstream = NULL;
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
 					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
@@ -1069,12 +1027,39 @@ efhd_attachment_optional (EMFormat *efh,
 	gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 6);
 	gtk_widget_show (GTK_WIDGET (view));
 
-	if (!em_part_attachment_get_is_shown (empa))
+	if (!info->shown)
 		gtk_widget_hide (scroll);
 
 	gtk_widget_show (vbox);
-
-	em_part_attachment_set_handler (empa, NULL);
+	info->handle = NULL;
 
 	return view;
 }
+
+static void
+efhd_free_attach_puri_data (EMFormatPURI *puri)
+{
+	EMFormatAttachmentPURI *info = (EMFormatAttachmentPURI *) puri;
+
+	g_return_if_fail (puri != NULL);
+
+	if (info->attachment) {
+		g_object_unref (info->attachment);
+		info->attachment = NULL;
+	}
+
+	if (info->description) {
+		g_free (info->description);
+		info->description = NULL;
+	}
+
+	if (info->attachment_view_part_id) {
+		g_free (info->attachment_view_part_id);
+		info->attachment_view_part_id = NULL;
+	}
+
+	if (info->mstream) {
+		g_object_unref (info->mstream);
+		info->mstream = NULL;
+	}
+}
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
index 52d95e0..cf3cac4 100644
--- a/mail/em-format-html-display.h
+++ b/mail/em-format-html-display.h
@@ -52,6 +52,52 @@ G_BEGIN_DECLS
 typedef struct _EMFormatHTMLDisplay EMFormatHTMLDisplay;
 typedef struct _EMFormatHTMLDisplayClass EMFormatHTMLDisplayClass;
 typedef struct _EMFormatHTMLDisplayPrivate EMFormatHTMLDisplayPrivate;
+typedef struct _EMFormatAttachmentBarPURI EMFormatAttachmentBarPURI;
+typedef struct _EMFormatAttachmentPURI EMFormatAttachmentPURI;
+typedef struct _EMFormatSMIMEPURI EMFormatSMIMEPURI;
+
+struct _EMFormatAttachmentBarPURI {
+	EMFormatPURI puri;
+
+	EAttachmentStore *store;
+};
+
+struct _EMFormatAttachmentPURI {
+	EMFormatPURI puri;
+
+	const EMFormatHandler *handle;
+
+	const gchar *snoop_mime_type;
+
+	/* for the > and V buttons */
+	GtkWidget *forward, *down;
+	guint shown:1;
+
+	/* Attachment */
+	EAttachment *attachment;
+	gchar *attachment_view_part_id;
+	gchar *description;
+
+	/* image stuff */
+	gint fit_width;
+	gint fit_height;
+	GtkImage *image;
+	GtkWidget *event_box;
+
+	/* Optional Text Mem Stream */
+	CamelStreamMem *mstream;
+};
+
+struct _EMFormatSMIMEPURI {
+	EMFormatPURI puri;
+
+	gchar *description;
+
+	gint signature;
+	CamelCipherValidity *valid;
+	GtkWidget *widget;
+};
+
 
 struct _EMFormatHTMLDisplay {
 	EMFormatHTML parent;
diff --git a/mail/em-format-html-print.c b/mail/em-format-html-print.c
index a86e7fb..f968ede 100644
--- a/mail/em-format-html-print.c
+++ b/mail/em-format-html-print.c
@@ -31,7 +31,6 @@
 
 #include "em-format-html-print.h"
 #include "em-format-html-display.h"
-#include "em-format-html-display-parts.h"
 #include "e-mail-attachment-bar.h"
 #include <e-util/e-print.h>
 #include <e-util/e-util.h>
@@ -40,15 +39,14 @@
 
 #include "em-format-html-print.h"
 
-
 static gpointer parent_class = NULL;
 
 struct _EMFormatHTMLPrintPrivate {
 
 	EMFormatHTML *original_formatter;
-	EMPart *top_level_part;
+	EMFormatPURI *top_level_puri;
 
-        /* List of attachment EMParts */
+        /* List of attachment PURIs */
         GList *attachments;
 
 };
@@ -58,9 +56,9 @@ enum {
 	PROP_ORIGINAL_FORMATTER
 };
 
-static void efhp_write_print_layout	(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efhp_write_headers		(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efhp_write_inline_attachment(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efhp_write_print_layout	(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efhp_write_headers		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efhp_write_inline_attachment(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
 
 static void
 efhp_write_attachments_list (EMFormatHTMLPrint *efhp,
@@ -81,20 +79,17 @@ efhp_write_attachments_list (EMFormatHTMLPrint *efhp,
                 _("Attachments"), _("Name"), _("Size"));
 
         for (iter = efhp->priv->attachments; iter; iter = iter->next) {
-                EMPart *emp = iter->data;
+                EMFormatPURI *puri = iter->data;
                 EAttachment *attachment;
                 GFileInfo *fi;
                 gchar *name, *size;
                 GByteArray *ba;
                 CamelDataWrapper *dw;
-		CamelMimePart *part;
 
-                attachment = em_part_attachment_get_attachment (EM_PART_ATTACHMENT (emp));
+                attachment = ((EMFormatAttachmentPURI *) puri)->attachment;
                 fi = e_attachment_get_file_info (attachment);
-                if (!fi) {
-			g_object_unref (attachment);
+                if (!fi)
                         continue;
-		}
 
                 if (e_attachment_get_description (attachment) &&
                     *e_attachment_get_description (attachment)) {
@@ -105,8 +100,7 @@ efhp_write_attachments_list (EMFormatHTMLPrint *efhp,
                         name = g_strdup (g_file_info_get_display_name (fi));
                 }
 
-                part = em_part_get_mime_part (emp);
-                dw = camel_medium_get_content ((CamelMedium *) part);
+                dw = camel_medium_get_content ((CamelMedium *) puri->part);
                 ba = camel_data_wrapper_get_byte_array (dw);
                 size = g_format_size (ba->len);
 
@@ -115,9 +109,6 @@ efhp_write_attachments_list (EMFormatHTMLPrint *efhp,
 
                 g_free (name);
                 g_free (size);
-
-		g_object_unref (attachment);
-		g_object_unref (part);
         }
 
         g_string_append (str, "</table>\n");
@@ -128,7 +119,7 @@ efhp_write_attachments_list (EMFormatHTMLPrint *efhp,
 
 static void
 efhp_write_headers (EMFormat *emf,
-		    EMPart *emp,
+		    EMFormatPURI *puri,
 		    CamelStream *stream,
 		    EMFormatWriterInfo *info,
 		    GCancellable *cancellable)
@@ -137,17 +128,12 @@ efhp_write_headers (EMFormat *emf,
 	GString *str, *tmp;
 	gchar *subject;
 	const gchar *buf;
-	EMPart *p;
+	EMFormatPURI *p;
 	GList *iter;
 	gint attachments_count;
         gchar *puri_prefix;
-	CamelMimePart *part;
-	gchar *uri;
-
-	part = em_part_get_mime_part (emp);
-	buf = camel_medium_get_header (CAMEL_MEDIUM (part), "subject");
-	g_object_unref (part);
 
+	buf = camel_medium_get_header (CAMEL_MEDIUM (puri->part), "subject");
 	subject = camel_header_decode_string (buf, "UTF-8");
 	str = g_string_new ("<table border=\"0\" cellspacing=\"5\" " \
                             "cellpadding=\"0\" class=\"printing-header\">\n");
@@ -167,7 +153,7 @@ efhp_write_headers (EMFormat *emf,
 		if (header->value && *header->value) {
 			raw_header.value = header->value;
 			em_format_html_format_header (emf, str,
-				CAMEL_MEDIUM (part), &raw_header,
+				CAMEL_MEDIUM (puri->part), &raw_header,
 				header->flags | EM_FORMAT_HTML_HEADER_NOLINKS,
 				"UTF-8");
 		} else {
@@ -176,7 +162,7 @@ efhp_write_headers (EMFormat *emf,
 
 			if (raw_header.value && *raw_header.value) {
 				em_format_html_format_header (emf, str,
-					CAMEL_MEDIUM (part), &raw_header,
+					CAMEL_MEDIUM (puri->part), &raw_header,
 					header->flags | EM_FORMAT_HTML_HEADER_NOLINKS,
 					"UTF-8");
 			}
@@ -186,51 +172,40 @@ efhp_write_headers (EMFormat *emf,
 		}
 	}
 
-        /* Get prefix of this EMPart */
-	uri = em_part_get_uri (emp);
-        puri_prefix = g_strndup (uri, g_strrstr (uri, ".") - uri);
-	g_free (uri);
+        /* Get prefix of this PURI */
+        puri_prefix = g_strndup (puri->uri, g_strrstr (puri->uri, ".") - puri->uri);
 
 	/* Add encryption/signature header */
 	raw_header.name = _("Security");
 	tmp = g_string_new ("");
 	/* Find first secured part. */
-	for (iter = emf->mail_part_list, emp; iter; iter = iter->next) {
-
-		gint32 validity_type;
-		gchar *uri;
+	for (iter = emf->mail_part_list, puri; iter; iter = iter->next) {
 
 		p = iter->data;
 
-		validity_type = em_part_get_validity_type (p);
-
-                if (validity_type == 0)
+                if (p->validity_type == 0)
                         continue;
 
-		uri = em_part_get_uri (p);
-                if (!g_str_has_prefix (uri, puri_prefix)) {
-			g_free (uri);
+                if (!g_str_has_prefix (p->uri, puri_prefix))
                         continue;
-		}
-		g_free (uri);
 
-		if ((validity_type & EM_FORMAT_VALIDITY_FOUND_PGP) &&
-		    (validity_type & EM_FORMAT_VALIDITY_FOUND_SIGNED)) {
+		if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_PGP) &&
+		    (p->validity_type & EM_FORMAT_VALIDITY_FOUND_SIGNED)) {
 			g_string_append (tmp, _("GPG signed"));
 		}
-		if ((validity_type & EM_FORMAT_VALIDITY_FOUND_PGP) &&
-		    (validity_type & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED)) {
+		if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_PGP) &&
+		    (p->validity_type & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED)) {
 			if (tmp->len > 0) g_string_append (tmp, ", ");
 			g_string_append (tmp, _("GPG encrpyted"));
 		}
-		if ((validity_type & EM_FORMAT_VALIDITY_FOUND_SMIME) &&
-		    (validity_type & EM_FORMAT_VALIDITY_FOUND_SIGNED)) {
+		if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_SMIME) &&
+		    (p->validity_type & EM_FORMAT_VALIDITY_FOUND_SIGNED)) {
 
 			if (tmp->len > 0) g_string_append (tmp, ", ");
 			g_string_append (tmp, _("S/MIME signed"));
 		}
-		if ((validity_type & EM_FORMAT_VALIDITY_FOUND_SMIME) &&
-		    (validity_type & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED)) {
+		if ((p->validity_type & EM_FORMAT_VALIDITY_FOUND_SMIME) &&
+		    (p->validity_type & EM_FORMAT_VALIDITY_FOUND_ENCRYPTED)) {
 
 			if (tmp->len > 0) g_string_append (tmp, ", ");
 			g_string_append (tmp, _("S/MIME encrpyted"));
@@ -239,19 +214,11 @@ efhp_write_headers (EMFormat *emf,
 		break;
 	}
 
-	if (!p) {
-                g_free (puri_prefix);
-		g_string_free (str, TRUE);
-		return;
-	}
-
-	part = em_part_get_mime_part (p);
 	if (tmp->len > 0) {
 		raw_header.value = tmp->str;
-		em_format_html_format_header (emf, str, CAMEL_MEDIUM (part),
+		em_format_html_format_header (emf, str, CAMEL_MEDIUM (p->part),
 			&raw_header, EM_FORMAT_HEADER_BOLD | EM_FORMAT_HTML_HEADER_NOLINKS, "UTF-8");
 	}
-	g_object_unref (p);
 	g_string_free (tmp, TRUE);
 
 	/* Count attachments and display the number as a header */
@@ -259,31 +226,21 @@ efhp_write_headers (EMFormat *emf,
 
 	for (iter = emf->mail_part_list; iter; iter = iter->next) {
 
-		gchar *uri;
-
 		p = iter->data;
 
-		uri = em_part_get_uri (p);
-                if (!g_str_has_prefix (uri, puri_prefix)) {
-			g_free (uri);
+                if (!g_str_has_prefix (p->uri, puri_prefix))
                         continue;
-		}
 
-		if (em_part_get_is_attachment (p) || g_str_has_suffix(uri, ".attachment"))
+		if (p->is_attachment || g_str_has_suffix(p->uri, ".attachment"))
 			attachments_count++;
-
-		g_free (uri);
 	}
-
-	part = em_part_get_mime_part (emp);	
 	if (attachments_count > 0) {
 		raw_header.name = _("Attachments");
 		raw_header.value = g_strdup_printf ("%d", attachments_count);
-		em_format_html_format_header (emf, str, CAMEL_MEDIUM (part),
+		em_format_html_format_header (emf, str, CAMEL_MEDIUM (puri->part),
 			&raw_header, EM_FORMAT_HEADER_BOLD | EM_FORMAT_HTML_HEADER_NOLINKS, "UTF-8");
 		g_free (raw_header.value);
 	}
-	g_object_unref (part);
 
 	g_string_append (str, "</table>");
 
@@ -294,17 +251,17 @@ efhp_write_headers (EMFormat *emf,
 
 static void
 efhp_write_inline_attachment (EMFormat *emf,
-                              EMPart *emp,
+                              EMFormatPURI *puri,
                               CamelStream *stream,
                               EMFormatWriterInfo *info,
                               GCancellable *cancellable)
 {
         gchar *name;
-	EMPartAttachment *empa = (EMPartAttachment *) emp;
+        EMFormatAttachmentPURI *att_puri = (EMFormatAttachmentPURI *) puri;
         EAttachment *attachment;
         GFileInfo *fi;
 
-        attachment = em_part_attachment_get_attachment (empa);
+        attachment = att_puri->attachment;
         fi = e_attachment_get_file_info (attachment);
 
         if (e_attachment_get_description (attachment) &&
@@ -319,14 +276,13 @@ efhp_write_inline_attachment (EMFormat *emf,
 
         camel_stream_write_string (stream, name, cancellable, NULL);
         g_free (name);
-	g_object_unref (attachment);
 
-	em_part_write (emp, stream, info, cancellable);
+        puri->write_func (emf, puri, stream, info, cancellable);
 }
 
 static void
 efhp_write_print_layout (EMFormat *emf,
-			 EMPart *emp,
+			 EMFormatPURI *puri,
 			 CamelStream *stream,
 			 EMFormatWriterInfo *info,
 			 GCancellable *cancellable)
@@ -349,58 +305,46 @@ efhp_write_print_layout (EMFormat *emf,
 
 	for (iter = emf->mail_part_list; iter != NULL; iter = iter->next) {
 
-		EMPart *p = iter->data;
-		gchar *uri;
+		EMFormatPURI *puri = iter->data;
 
-		uri = em_part_get_uri (p);
-		if (g_str_has_suffix (uri, "print_layout")) {
-			g_free (uri);
+		if (g_str_has_suffix (puri->uri, "print_layout"))
 			continue;
-		}
 
 		/* To late to change .headers writer_func, do it manually. */
-		if (g_str_has_suffix (uri, ".headers")) {
-			efhp_write_headers (emf, emp, stream, info, cancellable);
-			g_free (uri);
+		if (g_str_has_suffix (puri->uri, ".headers")) {
+			efhp_write_headers (emf, puri, stream, info, cancellable);
 			continue;
 		}
 
-		if (em_part_get_is_attachment (p) || g_str_has_suffix (uri, ".attachment")) {
+		if (puri->is_attachment || g_str_has_suffix (puri->uri, ".attachment")) {
 			const EMFormatHandler *handler;
-			CamelMimePart *part;
-			CamelContentType *ct;
-			gchar *mime_type;
 
-			part = em_part_get_mime_part (p);
-			ct = camel_mime_part_get_content_type (part);
-			mime_type = camel_content_type_simple (ct);			
+			CamelContentType *ct = camel_mime_part_get_content_type (puri->part);
+			gchar *mime_type = camel_content_type_simple (ct);
 
-			handler = em_format_find_handler (emf, mime_type);
-                        g_message ("Handler for EMPart %s (%s): %s", uri, mime_type,
+			handler = em_format_find_handler (puri->emf, mime_type);
+                        g_message ("Handler for PURI %s (%s): %s", puri->uri, mime_type,
                                  handler ? handler->mime_type : "(null)");
                         g_free (mime_type);
 
                         efhp->priv->attachments =
-                                g_list_append (efhp->priv->attachments, emp);
+                                g_list_append (efhp->priv->attachments, puri);
 
 			/* If we can't inline this attachment, skip it */
-			if (handler && em_part_get_write_func (p)) {
-                                efhp_write_inline_attachment (emf, emp,
+			if (handler && puri->write_func) {
+                                efhp_write_inline_attachment (puri->emf, puri,
                                         stream, &print_info, cancellable);
                         }
 
-                        g_free (uri);
                         continue;
 		}
 
-		g_free (uri);
-
 		/* Ignore widget parts and unwritable non-attachment parts */
-                if (em_part_get_write_func (p) == NULL)
+                if (puri->write_func == NULL)
                         continue;
 
                 /* Passed all tests, probably a regular part - display it */
-		em_part_write (emp, stream, &print_info, cancellable);
+                puri->write_func(puri->emf, puri, stream, &print_info, cancellable);
 
         }
 
@@ -420,9 +364,9 @@ efhp_finalize (GObject *object)
 		efhp->priv->original_formatter = NULL;
 	}
 
-	if (efhp->priv->top_level_part) {
-		g_object_unref (efhp->priv->top_level_part);
-		efhp->priv->top_level_part = NULL;
+	if (efhp->priv->top_level_puri) {
+		em_format_puri_free (efhp->priv->top_level_puri);
+		efhp->priv->top_level_puri = NULL;
 	}
 
 	if (efhp->priv->attachments) {
@@ -449,7 +393,7 @@ efhp_set_orig_formatter (EMFormatHTMLPrint *efhp,
 		    	 EMFormat *formatter)
 {
 	EMFormat *emfp, *emfs;
-	EMPart *emp;
+	EMFormatPURI *puri;
 	GHashTableIter iter;
 	gpointer key, value;
 
@@ -460,31 +404,29 @@ efhp_set_orig_formatter (EMFormatHTMLPrint *efhp,
 
 	emfp->mail_part_list = g_list_copy (emfs->mail_part_list);
 
-	/* Make a shallow copy of the table. */
+	/* Make a shallow copy of the table. This table will NOT destroy
+	 * the PURIs when free'd! */
         if (emfp->mail_part_table)
                 g_hash_table_unref (emfp->mail_part_table);
 
-	emfp->mail_part_table = g_hash_table_new_full 
-		(g_str_hash, g_str_equal, g_free, g_object_unref);
+	emfp->mail_part_table = g_hash_table_new (g_str_hash, g_str_equal);
 	g_hash_table_iter_init (&iter, emfs->mail_part_table);
-	while (g_hash_table_iter_next (&iter, &key, &value)) {
-		GList *item = value;
-		g_hash_table_insert (emfp->mail_part_table, 
-			g_strdup ((gchar *) key), g_object_ref (item->data));
-	}
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		g_hash_table_insert (emfp->mail_part_table, key, value);
 
         if (emfs->folder)
 	        emfp->folder = g_object_ref (emfs->folder);
 	emfp->message_uid = g_strdup (emfs->message_uid);
 	emfp->message = g_object_ref (emfs->message);
 
-	/* Add a generic EMPart that will write a HTML layout
+	/* Add a generic PURI that will write a HTML layout
 	   for all the parts */
-	emp = em_part_new (emfp, NULL, "print_layout", efhp_write_print_layout);
-	em_part_set_mime_type (emp, "text/html");
-	em_format_add_part_object (emfp, emp);
-
-	efhp->priv->top_level_part = g_object_ref (emp);
+	puri = em_format_puri_new (EM_FORMAT (efhp),
+		sizeof (EMFormatPURI), NULL, "print_layout");
+	puri->write_func = efhp_write_print_layout;
+	puri->mime_type = g_strdup ("text/html");
+	em_format_add_puri (EM_FORMAT (efhp), puri);
+	efhp->priv->top_level_puri = puri;
 }
 
 static EMFormatHandler type_builtin_table[] = {
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 034d585..1ff57a3 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -66,9 +66,7 @@
 #include "em-format-html.h"
 #include "em-utils.h"
 #include "e-mail-display.h"
-
 #include <em-format/em-inline-filter.h>
-#include <em-format/em-part.h>
 
 #define EM_FORMAT_HTML_GET_PRIVATE(obj) \
 	(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -123,16 +121,16 @@ 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, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_text_enriched		(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_text_plain		(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_text_html			(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_source			(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_headers			(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_attachment		(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
-static void efh_write_error			(EMFormat *emf, EMPart *emp, CamelStream *stream, EMFormatWriterInfo *info, 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_headers			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_attachment		(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
+static void efh_write_error			(EMFormat *emf, EMFormatPURI *puri, CamelStream *stream, EMFormatWriterInfo *info, GCancellable *cancellable);
 
-static GtkWidget* efh_widget_message_rfc822     (EMFormat *emf, EMPart *emp, GCancellable *cancellable);
+static GtkWidget* efh_widget_message_rfc822     (EMFormat *emf, EMFormatPURI *puri, 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);
@@ -140,17 +138,14 @@ static void efh_format_short_headers 		(EMFormatHTML *efh, GString *buffer, Came
 /*****************************************************************************/
 static GtkWidget*
 efh_widget_message_rfc822 (EMFormat* emf,
-                           EMPart *emp,
+                           EMFormatPURI* puri,
                            GCancellable* cancellable)
 {
         EMailDisplay *display;
         gchar *msg_uri;
-	gchar *uri;
 
-	uri = em_part_get_uri (emp);
         msg_uri = em_format_build_mail_uri (emf->folder, emf->message_uid,
-                "part_id", G_TYPE_STRING, uri, NULL);
-	g_free (uri);
+                "part_id", G_TYPE_STRING, puri->uri, NULL);
 
         display = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
         e_mail_display_set_formatter (display, EM_FORMAT_HTML (emf));
@@ -170,7 +165,7 @@ efh_parse_image (EMFormat *emf,
 		 EMFormatParserInfo *info,
 		 GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	const gchar *tmp;
 	gchar *cid;
 	gint len;
@@ -181,26 +176,23 @@ efh_parse_image (EMFormat *emf,
 
 	tmp = camel_mime_part_get_content_id (part);
 	if (!tmp) {
-		em_format_parse_part_as (emf, part, part_id, info,
-                        "x-evolution/message/attachment", cancellable);
+		em_format_parse_part_as (emf, part, part_id, info, "x-evolution/message/attachment", cancellable);
 		return;
 	}
 
 	cid = g_strdup_printf ("cid:%s", tmp);
 	len = part_id->len;
 	g_string_append (part_id, ".image");
-	emp = em_part_new (emf, part, part_id->str, efh_write_image);
-	em_part_set_cid (emp, cid);
-	em_part_set_mime_type (emp, info->handler->mime_type);
-	em_part_set_is_attachment (emp, TRUE);
-	em_part_set_validity_type (emp, info->validity_type);
-	em_part_set_validity (emp, info->validity);
-
-	em_format_add_part_object (emf, emp);
-
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->cid = cid;
+	puri->write_func = efh_write_image;
+	puri->mime_type = g_strdup (info->handler->mime_type);
+	puri->is_attachment = TRUE;
+	puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
+	puri->validity_type = info->validity_type;
+
+	em_format_add_puri (emf, puri);
 	g_string_truncate (part_id, len);
-
-	g_free (cid);
 }
 
 static void
@@ -210,7 +202,7 @@ efh_parse_text_enriched (EMFormat *emf,
 			 EMFormatParserInfo *info,
 			 GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	const gchar *tmp;
 	gchar *cid;
 	gint len;
@@ -227,18 +219,16 @@ efh_parse_text_enriched (EMFormat *emf,
 
 	len = part_id->len;
 	g_string_append (part_id, ".text_enriched");
-
-	emp = em_part_new (emf, part, part_id->str, efh_write_text_enriched);
-	em_part_set_cid (emp, cid);
-	em_part_set_mime_type (emp, info->handler->mime_type);
-	em_part_set_is_attachment (emp, info->is_attachment);
-	em_part_set_validity_type (emp, info->validity_type);
-	em_part_set_validity (emp, info->validity);
-
-	em_format_add_part_object (emf, emp);
-
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->cid = cid;
+	puri->mime_type = g_strdup (info->handler->mime_type);
+	puri->write_func = efh_write_text_enriched;
+	puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
+	puri->validity_type = info->validity_type;
+        puri->is_attachment = info->is_attachment;
+
+	em_format_add_puri (emf, puri);
 	g_string_truncate (part_id, len);
-	g_free (cid);
 }
 
 static void
@@ -248,7 +238,7 @@ efh_parse_text_plain (EMFormat *emf,
 		      EMFormatParserInfo *info,
 		      GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	CamelStream *filtered_stream, *null;
 	CamelMultipart *mp;
 	CamelDataWrapper *dw;
@@ -327,15 +317,14 @@ efh_parse_text_plain (EMFormat *emf,
 			gint s_len = part_id->len;
 
 			g_string_append (part_id, ".plain_text");
-
-			emp = em_part_new (emf, newpart, part_id->str, efh_write_text_plain);
-			em_part_set_mime_type (emp, "text/html");
-			em_part_set_is_attachment (emp, info->is_attachment);
-			em_part_set_validity_type (emp, info->validity_type);
-			em_part_set_validity (emp, info->validity);
-
+			puri = em_format_puri_new (emf, sizeof (EMFormatPURI), newpart, part_id->str);
+			puri->write_func = efh_write_text_plain;
+			puri->mime_type = g_strdup ("text/html");
+			puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
+			puri->validity_type = info->validity_type;
+                        puri->is_attachment = info->is_attachment;
 			g_string_truncate (part_id, s_len);
-			em_format_add_part_object (emf, emp);
+			em_format_add_puri (emf, puri);
 		} else {
 			g_string_append_printf (part_id, ".inline.%d", i);
 			em_format_parse_part (emf, CAMEL_MIME_PART (newpart), part_id, info, cancellable);
@@ -353,7 +342,7 @@ efh_parse_text_html (EMFormat *emf,
 		     EMFormatParserInfo *info,
 		     GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	const gchar *location;
 	gchar *cid = NULL;
 	CamelURL *base;
@@ -383,15 +372,13 @@ efh_parse_text_html (EMFormat *emf,
 
 	len = part_id->len;
 	g_string_append (part_id, ".text_html");
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->write_func = efh_write_text_html;
+	puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
+	puri->validity_type = info->validity_type;
+        puri->is_attachment = info->is_attachment;
 
-	emp = em_part_new (emf, part, part_id->str, efh_write_text_html);
-	em_part_set_is_attachment (emp, info->is_attachment);
-	em_part_set_validity_type (emp, info->validity_type);
-	em_part_set_validity (emp, info->validity);
-	em_part_set_cid (emp, cid);
-
-	em_format_add_part_object (emf, emp);
-
+	em_format_add_puri (emf, puri);
 	g_string_truncate (part_id, len);
 
 	if (cid)
@@ -405,7 +392,7 @@ efh_parse_message_external (EMFormat *emf,
 			    EMFormatParserInfo *info,
 			    GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	CamelMimePart *newpart;
 	CamelContentType *type;
 	const gchar *access_type;
@@ -507,12 +494,11 @@ fail:
 addPart:
 	len = part_id->len;
 	g_string_append (part_id, ".msg_external");
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->write_func = efh_write_text_html;
+	puri->mime_type = g_strdup ("text/html");
 
-	emp = em_part_new (emf, part, part_id->str, efh_write_text_html);
-	em_part_set_mime_type (emp, "text/html");
-
-	em_format_add_part_object (emf, emp);
-
+	em_format_add_puri (emf, puri);
 	g_string_truncate (part_id, len);
 }
 
@@ -523,7 +509,7 @@ efh_parse_message_deliverystatus (EMFormat *emf,
 				  EMFormatParserInfo *info,
 				  GCancellable *cancellable)
 {
-	EMPart *emp;
+	EMFormatPURI *puri;
 	gint len;
 
 	if (g_cancellable_is_cancelled (cancellable))
@@ -531,15 +517,14 @@ efh_parse_message_deliverystatus (EMFormat *emf,
 
 	len = part_id->len;
 	g_string_append (part_id, ".deliverystatus");
-
-	emp = em_part_new (emf, part, part_id->str, efh_write_source);
-	em_part_set_mime_type (emp, "text/html");
-	em_part_set_is_attachment (emp, info->is_attachment);
-	em_part_set_validity_type (emp, info->validity_type);
-	em_part_set_validity (emp, info->validity);
-
-	em_format_add_part_object (emf, emp);
-
+	puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+	puri->write_func = efh_write_source;
+	puri->mime_type = g_strdup ("text/html");
+	puri->validity = info->validity ? camel_cipher_validity_clone (info->validity) : NULL;
+	puri->validity_type = info->validity_type;
+        puri->is_attachment = info->is_attachment;
+
+	em_format_add_puri (emf, puri);
 	g_string_truncate (part_id, len);
 }
 
@@ -556,21 +541,18 @@ efh_parse_message_rfc822 (EMFormat *emf,
 	CamelMimeParser *parser;
 	gint len;
 	EMFormatParserInfo oinfo = *info;
-	EMPart *emp;
+	EMFormatPURI *puri;
 
 	len = part_id->len;
 	g_string_append (part_id, ".rfc822");
 
-        /* Create an empty EMPart that will represent start of the RFC message */
-	emp = em_part_new (emf, part, part_id->str, NULL);
-        em_part_set_widget_func (emp, efh_widget_message_rfc822);
-	em_part_set_write_func (emp, info->handler->write_func ? 
-		info->handler->write_func : 
-		em_format_empty_writer);
-	
-        em_format_add_part_object (emf, emp);
+        /* Create an empty PURI that will represent start of the RFC message */
+        puri = em_format_puri_new (emf, sizeof (EMFormatPURI), part, part_id->str);
+        puri->widget_func = efh_widget_message_rfc822;
+        puri->write_func = info->handler->write_func ? info->handler->write_func : em_format_empty_writer;
+        em_format_add_puri (emf, puri);
 
-        /* Now parse the message, creating multiple sub-EMParts */
+        /* Now parse the message, creating multiple sub-PURIs */
 	stream = camel_stream_mem_new ();
 	dw = camel_medium_get_content ((CamelMedium *) part);
 	camel_data_wrapper_write_to_stream_sync (dw, stream, cancellable, NULL);
@@ -585,15 +567,14 @@ efh_parse_message_rfc822 (EMFormat *emf,
 	em_format_parse_part_as (emf, opart, part_id, &oinfo,
 		"x-evolution/message", cancellable);
 
-        /* Add another generic EMPart that represents end of the RFC message.
-         * This is required for every EMPart that has EMailDisplay widget_func.
-         * The parent EMailDisplay then skips all EMParts between the ".rfc822" EMPart
-         * ".rfc822.end" EMPart (they were displayed by the child EMailDisplay called
-         * from ".rfc822"'s widget_func) and continues with the following EMPart. */
+        /* Add another generic PURI that represents end of the RFC message.
+         * This is required for every PURI that has EMailDisplay widget_func.
+         * The parent EMailDisplay then skips all PURIs between the ".rfc822" PURI
+         * ".rfc822.end" PURI (they were displayed by the child EMailDisplay called
+         * from ".rfc822"'s widget_func) and continues with the following PURI. */
         g_string_append (part_id, ".end");
-
-	emp = em_part_new (emf, NULL, part_id->str, NULL);
-	em_format_add_part_object (emf, emp);
+        puri = em_format_puri_new (emf, sizeof (EMFormatPURI), NULL, part_id->str);
+        em_format_add_puri (emf, puri);
 
 	g_string_truncate (part_id, len);
 
@@ -607,7 +588,7 @@ efh_parse_message_rfc822 (EMFormat *emf,
 
 static void
 efh_write_image (EMFormat *emf,
-		 EMPart *emp,
+		 EMFormatPURI *puri,
 		 CamelStream *stream,
  		 EMFormatWriterInfo *info,
 		 GCancellable *cancellable)
@@ -615,15 +596,11 @@ efh_write_image (EMFormat *emf,
 	gchar *content;
 	CamelDataWrapper *dw;
 	GByteArray *ba;
-	CamelMimePart *part;
 
 	if (g_cancellable_is_cancelled (cancellable))
 		return;
 
-	part = em_part_get_mime_part (emp);
-	dw = camel_medium_get_content (CAMEL_MEDIUM (part));
-	g_object_unref (part);
-
+	dw = camel_medium_get_content (CAMEL_MEDIUM (puri->part));
 	g_return_if_fail (dw);
 
 	ba = camel_data_wrapper_get_byte_array (dw);
@@ -638,21 +615,15 @@ efh_write_image (EMFormat *emf,
 	   image. */
 	if (!info->with_html_header) {
 		gchar *buffer;
-		gchar *mime_type;
 
-		mime_type = em_part_get_mime_type (emp);
-                if (!mime_type)
-                        mime_type = g_strdup ("image/*");
 		/* The image is already base64-encrypted so we can directly
 		   paste it to the output */
 		buffer = g_strdup_printf ("<img src=\"data:%s;base64,%s\" style=\"max-width: 100%%;\" />",
-			mime_type, content);
+			puri->mime_type, content);
 
 		camel_stream_write_string (stream, buffer, cancellable, NULL);
 
 		g_free (buffer);
-		if (mime_type)
-			g_free (mime_type);
 
 	} else {
 
@@ -674,7 +645,7 @@ efh_write_image (EMFormat *emf,
 
 static void
 efh_write_text_enriched (EMFormat *emf,
-			 EMPart *emp,
+			 EMFormatPURI *puri,
 			 CamelStream *stream,
 			 EMFormatWriterInfo *info,
 			 GCancellable *cancellable)
@@ -685,14 +656,12 @@ efh_write_text_enriched (EMFormat *emf,
 	guint32 flags = 0;
 	GString *buffer;
 	CamelContentType *ct;
-	CamelMimePart *part;
 	gchar *mime_type = NULL;
 
 	if (g_cancellable_is_cancelled (cancellable))
 		return;
 
-	part = em_part_get_mime_part (emp);
-	ct = camel_mime_part_get_content_type (part);
+	ct = camel_mime_part_get_content_type (puri->part);
 	if (ct) {
 		mime_type = camel_content_type_simple (ct);
 	}
@@ -741,28 +710,24 @@ efh_write_text_enriched (EMFormat *emf,
 
 	em_format_format_text (
 		emf, (CamelStream *) filtered_stream,
-		(CamelDataWrapper *) part, cancellable);
+		(CamelDataWrapper *) puri->part, cancellable);
 
 	g_object_unref (filtered_stream);
 	camel_stream_write_string (stream, "</div>", cancellable, NULL);
 
-	if (info->with_html_header) {
+	if (info->with_html_header)
 		camel_stream_write_string (stream, EFH_HTML_FOOTER,
 			cancellable, NULL);
-	}
-
-	g_object_unref (part);
 }
 
 static void
 efh_write_text_plain (EMFormat *emf,
-		      EMPart *emp,
+		      EMFormatPURI *puri,
 		      CamelStream *stream,
  		      EMFormatWriterInfo *info,
 		      GCancellable *cancellable)
 {
 	CamelDataWrapper *dw;
-	CamelMimePart *part;
 	CamelStream *filtered_stream;
 	CamelMimeFilter *html_filter;
 	EMFormatHTML *efh = (EMFormatHTML*) emf;
@@ -776,8 +741,7 @@ efh_write_text_plain (EMFormat *emf,
 
 	flags = efh->text_html_flags;
 
-	part = em_part_get_mime_part (emp);
-	dw = camel_medium_get_content (CAMEL_MEDIUM (part));
+	dw = camel_medium_get_content (CAMEL_MEDIUM (puri->part));
 
 	/* Check for RFC 2646 flowed text. */
 	if (camel_content_type_is(dw->mime_type, "text", "plain")
@@ -804,7 +768,7 @@ efh_write_text_plain (EMFormat *emf,
 			e_color_to_value (&efh->priv->colors[EM_FORMAT_HTML_COLOR_CONTENT]));
 
 	camel_stream_write_string (stream, content, cancellable, NULL);
-	em_format_format_text (emf, filtered_stream, (CamelDataWrapper *) part, cancellable);
+	em_format_format_text (emf, filtered_stream, (CamelDataWrapper *) puri->part, cancellable);
 
 	g_object_unref (filtered_stream);
 	g_free (content);
@@ -813,27 +777,21 @@ efh_write_text_plain (EMFormat *emf,
 
 	if (info->with_html_header)
 		camel_stream_write_string (stream, EFH_HTML_FOOTER, cancellable, NULL);
-
-	g_object_unref (part);
 }
 
 static void
 efh_write_text_html (EMFormat *emf,
-		     EMPart *emp,
+		     EMFormatPURI *puri,
 		     CamelStream *stream,
 		     EMFormatWriterInfo *info,
 		     GCancellable *cancellable)
 {
-	CamelMimePart *part;
-
-	part = em_part_get_mime_part (emp);
-
 	if (g_cancellable_is_cancelled (cancellable))
 		return;
 
 	if (info->with_html_header) {
 		em_format_format_text (emf, stream,
-			(CamelDataWrapper *) part, cancellable);
+			(CamelDataWrapper *) puri->part, cancellable);
 
 	} else {
 		CamelStream *format_stream;
@@ -843,7 +801,7 @@ efh_write_text_html (EMFormat *emf,
 
 		format_stream = camel_stream_mem_new ();
 		em_format_format_text (
-			emf, format_stream, (CamelDataWrapper *) part, cancellable);
+			emf, format_stream, (CamelDataWrapper *) puri->part, cancellable);
 
 		str  = g_string_new ("");
 		ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (format_stream));
@@ -870,13 +828,11 @@ efh_write_text_html (EMFormat *emf,
 
 		g_string_free (str, TRUE);
 	}
-
-	g_object_unref (part);
 }
 
 static void
 efh_write_source (EMFormat *emf,
-		  EMPart *emp,
+		  EMFormatPURI *puri,
 		  CamelStream *stream,
 		  EMFormatWriterInfo *info,
 		  GCancellable *cancellable)
@@ -885,11 +841,7 @@ efh_write_source (EMFormat *emf,
 	GString *buffer;
 	CamelStream *filtered_stream;
 	CamelMimeFilter *filter;
-	CamelMimePart *part;
-	CamelDataWrapper *dw;
-
-	part = em_part_get_mime_part (emp);
-	dw = (CamelDataWrapper *) part;
+	CamelDataWrapper *dw = (CamelDataWrapper *) puri->part;
 
 	filtered_stream = camel_stream_filter_new (stream);
 
@@ -927,25 +879,21 @@ efh_write_source (EMFormat *emf,
 		camel_stream_write_string (stream, EFH_HTML_FOOTER, cancellable, NULL);
 
 	g_object_unref (filtered_stream);
-	g_object_unref (part);	
 	g_string_free (buffer, TRUE);
 }
 
 static void
 efh_write_headers (EMFormat *emf,
-		   EMPart *emp,
+		   EMFormatPURI *puri,
 		   CamelStream *stream,
 		   EMFormatWriterInfo *info,
 		   GCancellable *cancellable)
 {
 	GString *buffer;
 	EMFormatHTML *efh = (EMFormatHTML *) emf;
-	CamelMimePart *part;
 	gint bg_color;
 
-	part = em_part_get_mime_part (emp);
-
-	if (!part)
+	if (!puri->part)
 		return;
 
 	buffer = g_string_new ("");
@@ -1009,12 +957,12 @@ efh_write_headers (EMFormat *emf,
 			EVOLUTION_IMAGESDIR,
 			(info->headers_collapsed) ? "plus.png" : "minus.png");
 
-		efh_format_short_headers (efh, buffer, (CamelMedium *) part,
+		efh_format_short_headers (efh, buffer, (CamelMedium *) puri->part,
 			info->headers_collapsed,
 			cancellable);
 	}
 
-	efh_format_full_headers (efh, buffer, (CamelMedium *) part,
+	efh_format_full_headers (efh, buffer, (CamelMedium *) puri->part,
 		(info->mode == EM_FORMAT_WRITE_MODE_ALL_HEADERS),
 		!info->headers_collapsed,
 		cancellable);
@@ -1027,27 +975,23 @@ efh_write_headers (EMFormat *emf,
 	camel_stream_write_string (stream, buffer->str, cancellable, NULL);
 
 	g_string_free (buffer, true);
-
-	g_object_unref (part);
 }
 
 static void
 efh_write_error (EMFormat *emf,
-		 EMPart *emp,
+		 EMFormatPURI *puri,
 		 CamelStream *stream,
 		 EMFormatWriterInfo *info,
 		 GCancellable *cancellable)
 {
 	CamelStream *filtered_stream;
 	CamelMimeFilter *filter;
-	CamelMimePart *part;
 	CamelDataWrapper *dw;
 
 	if (info->with_html_header)
 		camel_stream_write_string (stream, EFH_HTML_HEADER, cancellable, NULL);
 
-	part = em_part_get_mime_part (emp);
-	dw = camel_medium_get_content ((CamelMedium *) part);
+	dw = camel_medium_get_content ((CamelMedium *) puri->part);
 
 	camel_stream_write_string (stream, "<em><font color=\"red\">", cancellable, NULL);
 
@@ -1065,8 +1009,6 @@ efh_write_error (EMFormat *emf,
 
 	if (info->with_html_header)
 		camel_stream_write_string (stream, EFH_HTML_FOOTER, cancellable, NULL);
-
-	g_object_unref (part);
 }
 
 /*****************************************************************************/
@@ -1319,21 +1261,18 @@ efh_finalize (GObject *object)
 
 static void
 efh_write_attachment (EMFormat *emf,
-		      EMPart *emp,
-		      CamelStream *stream,
-		      EMFormatWriterInfo *info,
+					  EMFormatPURI *puri,
+					  CamelStream *stream,
+					  EMFormatWriterInfo *info,
                       GCancellable *cancellable)
 {
 	gchar *text, *html;
 	CamelContentType *ct;
-	CamelMimePart *part;
 	gchar *mime_type;
 	const EMFormatHandler *handler;
 
 	/* we display all inlined attachments only */
 
-	part = em_part_get_mime_part (emp);
-
 	/* this could probably be cleaned up ... */
 	camel_stream_write_string (
 		stream,
@@ -1344,11 +1283,11 @@ efh_write_attachment (EMFormat *emf,
 		"<tr><td></td></tr></table></td><td><font size=-1>\n",
 		cancellable, NULL);
 
-	ct = camel_mime_part_get_content_type (part);
+	ct = camel_mime_part_get_content_type (puri->part);
 	mime_type = camel_content_type_simple (ct);
 
 	/* output some info about it */
-	text = em_format_describe_part (part, mime_type);
+	text = em_format_describe_part (puri->part, mime_type);
 	html = camel_text_to_html (
 		text, ((EMFormatHTML *) emf)->text_html_flags &
 		CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
@@ -1361,14 +1300,11 @@ efh_write_attachment (EMFormat *emf,
 
 	handler = em_format_find_handler (emf, mime_type);
 	if (handler && handler->write_func && handler->write_func != efh_write_attachment) {
-		gchar *uri = em_part_get_uri (emp);
-		if (em_format_is_inline (emf, uri, part, handler))
-			handler->write_func (emf, emp, stream, info, cancellable);
-		g_free (uri);
+		if (em_format_is_inline (emf, puri->uri, puri->part, handler))
+			handler->write_func (emf, puri, stream, info, cancellable);
 	}
 
 	g_free (mime_type);
-	g_object_unref (part);
 }
 
 static void
@@ -2508,7 +2444,7 @@ efh_format_full_headers (EMFormatHTML *efh,
 		photopart = em_utils_contact_photo (cia, only_local_photo);
 
 		if (photopart) {
-			EMPart *emp;
+			EMFormatPURI *puri;
 			contact_has_photo = TRUE;
 			classid = "icon:///em-format-html/headers/photo";
 			g_string_append_printf (
@@ -2516,9 +2452,10 @@ efh_format_full_headers (EMFormatHTML *efh,
 				"<td align=\"right\" valign=\"top\">"
 				"<img width=64 src=\"%s\"></td>",
 				classid);
-
-			emp = em_part_new (emf, photopart, classid, efh_write_image);
-			em_format_add_part_object (emf, emp);
+			puri = em_format_puri_new (
+					emf, sizeof (EMFormatPURI), photopart, classid);
+			puri->write_func = efh_write_image;
+			em_format_add_puri (emf, puri);
 			g_object_unref (photopart);
 		}
 		g_object_unref (cia);
@@ -2527,7 +2464,7 @@ efh_format_full_headers (EMFormatHTML *efh,
 	if (!contact_has_photo && face_decoded) {
 		const gchar *classid;
 		CamelMimePart *part;
-		EMPart *emp;
+		EMFormatPURI *puri;
 
 		part = camel_mime_part_new ();
 		camel_mime_part_set_content (
@@ -2541,8 +2478,10 @@ efh_format_full_headers (EMFormatHTML *efh,
 			"<img width=48 src=\"%s\"></td>",
 			classid);
 
-		emp = em_part_new (emf, part, classid, efh_write_image);
-		em_format_add_part_object (emf, emp);
+		puri = em_format_puri_new (
+			emf, sizeof (EMFormatPURI), part, classid);
+		puri->write_func = efh_write_image;
+		em_format_add_puri (emf, puri);
 
 		g_object_unref (part);
 		g_free (face_header_value);
@@ -2552,7 +2491,7 @@ efh_format_full_headers (EMFormatHTML *efh,
 		GtkIconInfo *icon_info;
 		const gchar *classid;
 		CamelMimePart *iconpart = NULL;
-		EMPart *emp;
+		EMFormatPURI *puri;
 
 		classid = "icon:///em-format-html/header/icon";
 		g_string_append_printf (
@@ -2571,8 +2510,10 @@ efh_format_full_headers (EMFormatHTML *efh,
 			gtk_icon_info_free (icon_info);
 		}
 		if (iconpart) {
-			emp = em_part_new (emf, iconpart, classid, efh_write_image);
-			em_format_add_part_object (emf, emp);
+			puri = em_format_puri_new (
+					emf, sizeof (EMFormatPURI), iconpart, classid);
+			puri->write_func = efh_write_image;
+			em_format_add_puri (emf, puri);
 			g_object_unref (iconpart);
 		}
 	}
diff --git a/mail/em-format-html.h b/mail/em-format-html.h
index 170b2ae..689167f 100644
--- a/mail/em-format-html.h
+++ b/mail/em-format-html.h
@@ -56,6 +56,7 @@ G_BEGIN_DECLS
 typedef struct _EMFormatHTML EMFormatHTML;
 typedef struct _EMFormatHTMLClass EMFormatHTMLClass;
 typedef struct _EMFormatHTMLPrivate EMFormatHTMLPrivate;
+typedef struct _EMFormatWidgetPURI EMFormatWidgetPURI;
 
 enum _em_format_html_header_flags {
 	EM_FORMAT_HTML_HEADER_TO = 1 << 0,
diff --git a/mail/em-utils.c b/mail/em-utils.c
index b0b4354..f019863 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -77,7 +77,6 @@
 #include "em-utils.h"
 #include "e-mail-printer.h"
 #include "em-format/em-format-quote.h"
-#include "em-format/em-part.h"
 
 /* XXX This is a dirty hack on a dirty hack.  We really need
  *     to rework or get rid of the functions that use this. */
@@ -1221,15 +1220,12 @@ em_utils_message_to_html (CamelMimeMessage *message,
 		/* Return all found validities */
 		for (iter = emf->mail_part_list; iter; iter = iter->next) {
 			
-			EMPart *emp = iter->data;
-			gint32 validity_type;
-
-			if (!emp)
+			EMFormatPURI *puri = iter->data;
+			if (!puri)
 				continue;
 
-			validity_type = em_part_get_validity_type (emp);
-			if (*validity_found && validity_type)
-				*validity_found |= validity_type;
+			if (*validity_found && puri->validity_type)
+				*validity_found |= puri->validity_type;
 		}
 
 	}
diff --git a/plugins/audio-inline/Makefile.am b/plugins/audio-inline/Makefile.am
index 3e04573..fc204f9 100644
--- a/plugins/audio-inline/Makefile.am
+++ b/plugins/audio-inline/Makefile.am
@@ -20,9 +20,7 @@ liborg_gnome_audio_inline_la_CPPFLAGS =			\
 	$(GSTREAMER_CFLAGS)				\
 	$(GTKHTML_CFLAGS)
 
-liborg_gnome_audio_inline_la_SOURCES = 			\
-	audio-inline.c					\
-	em-part-audio.c
+liborg_gnome_audio_inline_la_SOURCES = audio-inline.c
 
 liborg_gnome_audio_inline_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
 
diff --git a/plugins/audio-inline/audio-inline.c b/plugins/audio-inline/audio-inline.c
index 7250277..4942370 100644
--- a/plugins/audio-inline/audio-inline.c
+++ b/plugins/audio-inline/audio-inline.c
@@ -24,14 +24,13 @@
 #include <config.h>
 #endif
 
-#include "em-part-audio.h"
-
 #include <gtk/gtk.h>
 #include <glib/gstdio.h>
 #include "e-util/e-mktemp.h"
 #include "mail/em-format-hook.h"
 #include "mail/em-format-html.h"
-#include <gst/gst.h>
+#include "gtkhtml/gtkhtml-embedded.h"
+#include "gst/gst.h"
 
 #define d(x)
 
@@ -48,31 +47,82 @@ void org_gnome_audio_inline_format (gpointer ep, EMFormatHookTarget *t);
 
 static volatile gint org_gnome_audio_class_id_counter = 0;
 
+typedef struct _EMFormatInlineAudioPURI EMFormatInlineAudioPURI;
+
+struct _EMFormatInlineAudioPURI {
+	EMFormatPURI puri;
+
+	gchar *filename;
+	GstElement *playbin;
+	gulong      bus_id;
+	GstState    target_state;
+	GtkWidget  *play_button;
+	GtkWidget  *pause_button;
+	GtkWidget  *stop_button;
+};
+
+static void
+org_gnome_audio_inline_pobject_free (EMFormatPURI *o)
+{
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) o;
+
+	d(printf ("audio inline formatter: pobject free\n"));
+
+	if (po->play_button) {
+		g_object_unref (po->play_button);
+		po->play_button = NULL;
+	}
+
+	if (po->pause_button) {
+		g_object_unref (po->pause_button);
+		po->pause_button = NULL;
+	}
+
+	if (po->stop_button) {
+		g_object_unref (po->stop_button);
+		po->stop_button = NULL;
+	}
+
+	if (po->filename) {
+		g_unlink (po->filename);
+		g_free (po->filename);
+		po->filename = NULL;
+	}
+
+	if (po->bus_id) {
+		g_source_remove (po->bus_id);
+		po->bus_id = 0;
+	}
+
+	if (po->playbin) {
+		gst_element_set_state (po->playbin, GST_STATE_NULL);
+		gst_object_unref (po->playbin);
+		po->playbin = NULL;
+	}
+}
 
 static void
 org_gnome_audio_inline_pause_clicked (GtkWidget *button,
-				      EMPartAudio *empa)
+									  EMFormatPURI *puri)
 {
-	GstElement *playbin = em_part_audio_get_playbin (empa);
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 
-	if (playbin) {
+	if (po->playbin) {
 		/* pause playing */
-		gst_element_set_state (playbin, GST_STATE_PAUSED);
-		g_object_unref (playbin);
+		gst_element_set_state (po->playbin, GST_STATE_PAUSED);
 	}
 }
 
 static void
 org_gnome_audio_inline_stop_clicked (GtkWidget *button,
-				     EMPartAudio *empa)
+									 EMFormatPURI *puri)
 {
-	GstElement *playbin = em_part_audio_get_playbin (empa);
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 
-	if (playbin) {
+	if (po->playbin) {
 		/* ready to play */
-		gst_element_set_state (playbin, GST_STATE_READY);
-		em_part_audio_set_target_state (empa, GST_STATE_READY);
-		g_object_unref (playbin);
+		gst_element_set_state (po->playbin, GST_STATE_READY);
+		po->target_state = GST_STATE_READY;
 	}
 }
 
@@ -97,57 +147,39 @@ org_gnome_audio_inline_gst_callback (GstBus *bus,
                                      GstMessage *message,
                                      gpointer data)
 {
-	EMPartAudio *empa = data;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) data;
 	GstMessageType msg_type;
-	GstElement *playbin;
-
-	g_return_val_if_fail (data != NULL, TRUE);
 
-	playbin = em_part_audio_get_playbin (empa);
-	g_return_val_if_fail (playbin != NULL, TRUE);
+	g_return_val_if_fail (po != NULL, TRUE);
+	g_return_val_if_fail (po->playbin != NULL, TRUE);
 
 	msg_type = GST_MESSAGE_TYPE (message);
 
 	switch (msg_type) {
 		case GST_MESSAGE_ERROR:
-			gst_element_set_state (playbin, GST_STATE_NULL);
+			gst_element_set_state (po->playbin, GST_STATE_NULL);
 			break;
 		case GST_MESSAGE_EOS:
-			gst_element_set_state (playbin, GST_STATE_READY);
+			gst_element_set_state (po->playbin, GST_STATE_READY);
 			break;
 		case GST_MESSAGE_STATE_CHANGED:
 			{
-				GstState old_state, new_state;
-				GtkWidget *button;
-
-				if (GST_MESSAGE_SRC (message) != GST_OBJECT (playbin))
-					break;
-
-				gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
-
-				if (old_state == new_state)
-					break;
-
-				button = em_part_audio_get_play_button (empa);
-				if (button) {
-					gtk_widget_set_sensitive (button, 
-						new_state <= GST_STATE_PAUSED);
-					g_object_unref (button);
-				}
-
-				button = em_part_audio_get_pause_button (empa);
-				if (button) {
-					gtk_widget_set_sensitive (button, 
-						new_state > GST_STATE_PAUSED);
-					g_object_unref (button);
-				}
-
-				button = em_part_audio_get_stop_button (empa);
-			      	if (button) {
-					gtk_widget_set_sensitive (button,
-						new_state >= GST_STATE_PAUSED);
-					g_object_unref (button);
-				}
+			      GstState old_state, new_state;
+
+			      if (GST_MESSAGE_SRC (message) != GST_OBJECT (po->playbin))
+				      break;
+
+			      gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
+
+			      if (old_state == new_state)
+				      break;
+
+			      if (po->play_button)
+					gtk_widget_set_sensitive (po->play_button, new_state <= GST_STATE_PAUSED);
+			      if (po->pause_button)
+					gtk_widget_set_sensitive (po->pause_button, new_state > GST_STATE_PAUSED);
+			      if (po->stop_button)
+					gtk_widget_set_sensitive (po->stop_button, new_state >= GST_STATE_PAUSED);
 			}
 
 			break;
@@ -155,45 +187,36 @@ org_gnome_audio_inline_gst_callback (GstBus *bus,
 			break;
 	}
 
-	g_object_unref (playbin);
-
 	return TRUE;
 }
 
 static void
 org_gnome_audio_inline_play_clicked (GtkWidget *button,
-				     EMPartAudio *empa)
+									 EMFormatPURI *puri)
 {
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
 	GstState cur_state;
-	GstElement *playbin;
-	gchar *filename;
 
 	d(printf ("audio inline formatter: play\n"));
 
-	filename = em_part_audio_get_filename (empa);
-	if (!filename) {
+	if (!po->filename) {
 		CamelStream *stream;
-		CamelMimePart *part;
 		CamelDataWrapper *data;
 		GError *error = NULL;
 		gint argc = 1;
 		const gchar *argv [] = { "org_gnome_audio_inline", NULL };
 
 		/* FIXME this is ugly, we should stream this directly to gstreamer */
-		
-		filename = e_mktemp ("org-gnome-audio-inline-file-XXXXXX");
-		em_part_audio_set_filename (empa, filename);
+		po->filename = e_mktemp ("org-gnome-audio-inline-file-XXXXXX");
 
-		d(printf ("audio inline formatter: write to temp file %s\n", filename));
+		d(printf ("audio inline formatter: write to temp file %s\n", po->filename));
 
-		stream = camel_stream_fs_new_with_name (filename, O_RDWR | O_CREAT | O_TRUNC, 0600, NULL);
-		part = em_part_get_mime_part (EM_PART (empa));
-		data = camel_medium_get_content (CAMEL_MEDIUM (part));
+		stream = camel_stream_fs_new_with_name (po->filename, O_RDWR | O_CREAT | O_TRUNC, 0600, NULL);
+		data = camel_medium_get_content (CAMEL_MEDIUM (po->puri.part));
 		camel_data_wrapper_decode_to_stream_sync (
 			data, stream, NULL, NULL);
 		camel_stream_flush (stream, NULL, NULL);
 		g_object_unref (stream);
-		g_object_unref (part);
 
 		d(printf ("audio inline formatter: init gst playbin\n"));
 
@@ -202,45 +225,38 @@ org_gnome_audio_inline_play_clicked (GtkWidget *button,
 			GstBus *bus;
 
 			/* create a disk reader */
-			playbin = gst_element_factory_make ("playbin", "playbin");
-			if (playbin == NULL) {
+			po->playbin = gst_element_factory_make ("playbin", "playbin");
+			if (po->playbin == NULL) {
 				g_printerr ("Failed to create gst_element_factory playbin; check your installation\n");
 				return;
 
 			}
-			em_part_audio_set_playbin (empa, playbin);
 
-			uri = g_filename_to_uri (filename, NULL, NULL);
-			g_object_set (playbin, "uri", uri, NULL);
+			uri = g_filename_to_uri (po->filename, NULL, NULL);
+			g_object_set (po->playbin, "uri", uri, NULL);
 			g_free (uri);
-			org_gnome_audio_inline_set_audiosink (playbin);
-
-			bus = gst_element_get_bus (playbin);
-			em_part_audio_set_bus_id (empa, 
-				gst_bus_add_watch (bus, org_gnome_audio_inline_gst_callback, empa));
+			org_gnome_audio_inline_set_audiosink (po->playbin);
 
+			bus = gst_element_get_bus (po->playbin);
+			po->bus_id = gst_bus_add_watch (bus, org_gnome_audio_inline_gst_callback, po);
 			gst_object_unref (bus);
 
 		} else {
 			g_printerr ("GStreamer failed to initialize: %s",error ? error->message : "");
 			g_error_free (error);
 		}
-
-		g_free (filename);
 	}
 
-	gst_element_get_state (playbin, &cur_state, NULL, 0);
+	gst_element_get_state (po->playbin, &cur_state, NULL, 0);
 
 	if (cur_state >= GST_STATE_PAUSED) {
-		gst_element_set_state (playbin, GST_STATE_READY);
+		gst_element_set_state (po->playbin, GST_STATE_READY);
 	}
 
-	if (playbin) {
+	if (po->playbin) {
 		/* start playing */
-		gst_element_set_state (playbin, GST_STATE_PLAYING);
+		gst_element_set_state (po->playbin, GST_STATE_PLAYING);
 	}
-
-	g_object_unref (playbin);
 }
 
 static GtkWidget *
@@ -264,26 +280,18 @@ org_gnome_audio_inline_add_button (GtkWidget *box,
 
 static GtkWidget*
 org_gnome_audio_inline_button_panel (EMFormat *emf,
-				     EMPartAudio *empa,
-				     GCancellable *cancellable)
+									 EMFormatPURI *puri,
+									 GCancellable *cancellable)
 {
 	GtkWidget *box;
+	EMFormatInlineAudioPURI *po = (EMFormatInlineAudioPURI *) puri;
+
 	/* it is OK to call UI functions here, since we are called from UI thread */
 
 	box = gtk_hbutton_box_new ();
-
-        em_part_audio_set_play_button (empa,
-                org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_PLAY,
-                        G_CALLBACK (org_gnome_audio_inline_play_clicked),
-                        empa, TRUE));
-        em_part_audio_set_pause_button (empa,
-	        org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_PAUSE,
-                        G_CALLBACK (org_gnome_audio_inline_pause_clicked),
-                        empa, FALSE));
-        em_part_audio_set_stop_button (empa,
-                org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_STOP,
-                        G_CALLBACK (org_gnome_audio_inline_stop_clicked),
-                        empa, FALSE));
+	po->play_button = g_object_ref (org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_PLAY, G_CALLBACK (org_gnome_audio_inline_play_clicked), po, TRUE));
+	po->pause_button = g_object_ref (org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_PAUSE, G_CALLBACK (org_gnome_audio_inline_pause_clicked), po, FALSE));
+	po->stop_button = g_object_ref (org_gnome_audio_inline_add_button (box, GTK_STOCK_MEDIA_STOP, G_CALLBACK (org_gnome_audio_inline_stop_clicked), po, FALSE));
 
 	gtk_widget_show (box);
 
@@ -294,7 +302,7 @@ void
 org_gnome_audio_inline_format (gpointer ep,
                                EMFormatHookTarget *t)
 {
-        EMPart *emp;
+	EMFormatInlineAudioPURI *pobj;
 	gchar *classid;
 
 	classid = g_strdup_printf (
@@ -305,8 +313,18 @@ org_gnome_audio_inline_format (gpointer ep,
 
 	d(printf ("audio inline formatter: format classid %s\n", classid));
 
-        emp = em_part_audio_new (t->format, t->part, t->part_id, NULL);
-        em_part_set_widget_func (emp, org_gnome_audio_inline_button_panel);
-
-        em_format_add_part_object (t->format, emp);
+	pobj = (EMFormatInlineAudioPURI *) em_format_puri_new (
+                        t->format, sizeof (EMFormatInlineAudioPURI), t->part, classid);
+	pobj->puri.widget_func = org_gnome_audio_inline_button_panel;
+	pobj->puri.part = g_object_ref (t->part);
+	pobj->filename = NULL;
+	pobj->playbin = NULL;
+	pobj->play_button = NULL;
+	pobj->stop_button = NULL;
+	pobj->pause_button = NULL;
+	pobj->bus_id = 0;
+	pobj->puri.free = org_gnome_audio_inline_pobject_free;
+	pobj->target_state = GST_STATE_NULL;
+
+        em_format_add_puri (t->format, (EMFormatPURI *) pobj);
 }
diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c
index 62fb2ca..4dd58bb 100644
--- a/widgets/misc/e-web-view.c
+++ b/widgets/misc/e-web-view.c
@@ -371,6 +371,24 @@ web_view_connect_proxy_cb (EWebView *web_view,
 		G_CALLBACK (web_view_menu_item_deselect_cb), web_view);
 }
 
+static GtkWidget *
+web_view_create_plugin_widget_cb (EWebView *web_view,
+                                  const gchar *mime_type,
+                                  const gchar *uri,
+                                  GHashTable *param)
+{
+	EWebViewClass *class;
+
+	/* XXX WebKitWebView does not provide a class method for
+	 *     this signal, so we do so we can override the default
+	 *     behavior from subclasses for special URI types. */
+
+	class = E_WEB_VIEW_GET_CLASS (web_view);
+	g_return_val_if_fail (class->create_plugin_widget != NULL, NULL);
+
+	return class->create_plugin_widget (web_view, mime_type, uri, param);
+}
+
 static void
 web_view_hovering_over_link_cb (EWebView *web_view,
                                 const gchar *title,
@@ -813,6 +831,165 @@ web_view_scroll_event (GtkWidget *widget,
 	return FALSE;
 }
 
+static void
+web_view_get_preferred_height (GtkWidget *widget,
+			       gint *minimum_height,
+			       gint *natural_height)
+{
+	WebKitWebView *web_view;
+	WebKitDOMDocument *document;
+	WebKitDOMElement *body, *last_el, *style_el;
+	gint doc_height;
+
+	if (!minimum_height && !natural_height)
+		return;
+
+	web_view = WEBKIT_WEB_VIEW (widget);
+	document = webkit_web_view_get_dom_document (web_view);
+	if (!document)
+		return;
+
+	body = WEBKIT_DOM_ELEMENT (webkit_dom_document_get_body (document));
+	if (!body)
+		return;
+
+	/* Make sure our Evo CSS stylesheet is loaded.
+	 * Note: there's 'user-stylesheet-uri' property of WebKitWebSettings but
+	 * it does not seem to be loaded in webviews with native text/html emails. */
+	style_el = webkit_dom_document_get_element_by_id (document, "_evo_stylesheet");
+	if (!style_el) {
+		WebKitDOMNodeList *list;
+		WebKitDOMNode *head;
+		style_el = webkit_dom_document_create_element (document, "LINK", NULL);
+		webkit_dom_html_link_element_set_rel (
+			WEBKIT_DOM_HTML_LINK_ELEMENT (style_el), "stylesheet");
+		webkit_dom_html_link_element_set_href(
+			WEBKIT_DOM_HTML_LINK_ELEMENT (style_el),
+			"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview.css");
+		webkit_dom_element_set_attribute (style_el, "type", "text/css", NULL);
+		webkit_dom_html_element_set_id (
+			WEBKIT_DOM_HTML_ELEMENT (style_el), "_evo_stylesheet");
+
+		list = webkit_dom_document_get_elements_by_tag_name (document, "head");
+		/* Broken HTML! Try to add head */
+		if (webkit_dom_node_list_get_length (list) == 0) {
+			WebKitDOMNodeList *body;
+			head = WEBKIT_DOM_NODE (
+				webkit_dom_document_create_element (
+					document, "HEAD", NULL));
+			body = webkit_dom_document_get_elements_by_tag_name (document, "body");
+			if (webkit_dom_node_list_get_length(body) == 0) {
+				/* The document is totally screwed up, there's
+				 * nothing more we can do. */
+				return;
+			}
+
+			webkit_dom_node_insert_before(WEBKIT_DOM_NODE (document),
+				head, webkit_dom_node_list_item (body, 0), NULL);
+
+		} else {
+			head = webkit_dom_node_list_item (list, 0);
+		}
+
+		webkit_dom_node_append_child (head, WEBKIT_DOM_NODE (style_el), NULL);
+	}
+
+	/* Last element in DOM != the undermost element displayed.
+	 * Thus we create our own element which is guaranteed to be displayed
+	 * at the very bottom (via CSS in webview.css) */
+	last_el = webkit_dom_document_get_element_by_id (document, "_evo_bottom_element");
+	if (!last_el) {
+		last_el = webkit_dom_document_create_element (document, "DIV", NULL);
+		webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (last_el),
+			"_evo_bottom_element");
+		webkit_dom_node_append_child (WEBKIT_DOM_NODE (body),
+			WEBKIT_DOM_NODE (last_el), NULL);
+
+		/* When the _evo_bottom_element is inserted to the DOM, the
+		 * subsequent call of webkit_dom_element_get_offset_top() makes
+		 * WebKit to recalculate layout and invoke content size change
+		 * which results in a recursive call of this function.
+		 * Gtk would prevent the recursion to happen but it would
+		 * throw an ugly warning, therefor we won't be doing any math now.
+		 * When the email is being rendered, the _get_preferred_height()
+		 * gets called multiple times, so we will calculate the actual
+		 * height next time, when WebKit will not be trying to update the
+		 * layout. */
+
+		return;
+	}
+
+	/* The _actual_ height of page content is top + height of the
+	 * very last element in body. The 2px height is hardocded in
+	 * webview.ccs in #_evo_bottom_element */
+	doc_height = webkit_dom_element_get_offset_top (last_el) + 2;
+
+
+	/* Hardcoded padding */
+	doc_height += 18;
+
+	/* When full content zoom is enabled then the elements are not resized
+	 * but rather scaled and thus they still report their original height
+	 * instead of their actual display height. */
+	if (webkit_web_view_get_full_content_zoom (web_view)) {
+		doc_height = ceil((gfloat) doc_height * 
+				webkit_web_view_get_zoom_level (web_view));
+	}
+
+	if (minimum_height)
+		*minimum_height = doc_height;
+
+	if (natural_height)
+		*natural_height = doc_height;
+
+}
+
+static GtkWidget *
+web_view_create_plugin_widget (EWebView *web_view,
+                               const gchar *mime_type,
+                               const gchar *uri,
+                               GHashTable *param)
+{
+	GtkWidget *widget = NULL;
+
+	if (g_strcmp0 (mime_type, "image/x-themed-icon") == 0) {
+		GtkIconTheme *icon_theme;
+		GdkPixbuf *pixbuf;
+		gpointer data;
+		glong size = 0;
+		GError *error = NULL;
+
+		icon_theme = gtk_icon_theme_get_default ();
+
+		if (size == 0) {
+			data = g_hash_table_lookup (param, "width");
+			if (data != NULL)
+				size = MAX (size, strtol (data, NULL, 10));
+		}
+
+		if (size == 0) {
+			data = g_hash_table_lookup (param, "height");
+			if (data != NULL)
+				size = MAX (size, strtol (data, NULL, 10));
+		}
+
+		if (size == 0)
+			size = 32;  /* arbitrary default */
+
+		pixbuf = gtk_icon_theme_load_icon (
+			icon_theme, uri, size, 0, &error);
+		if (pixbuf != NULL) {
+			widget = gtk_image_new_from_pixbuf (pixbuf);
+			g_object_unref (pixbuf);
+		} else if (error != NULL) {
+			g_warning ("%s", error->message);
+			g_error_free (error);
+		}
+	}
+
+	return widget;
+}
+
 static gchar *
 web_view_extract_uri (EWebView *web_view,
                       GdkEventButton *event)
@@ -1245,12 +1422,14 @@ e_web_view_class_init (EWebViewClass *class)
 	widget_class = GTK_WIDGET_CLASS (class);
 	widget_class->button_press_event = web_view_button_press_event;
 	widget_class->scroll_event = web_view_scroll_event;
+	widget_class->get_preferred_height = web_view_get_preferred_height;
 
 #if 0  /* WEBKIT */
 	html_class = GTK_HTML_CLASS (class);
 	html_class->url_requested = web_view_url_requested;
 #endif
 
+	class->create_plugin_widget = web_view_create_plugin_widget;
 	class->extract_uri = web_view_extract_uri;
 	class->hovering_over_link = web_view_hovering_over_link;
 	class->link_clicked = web_view_link_clicked;
@@ -1474,6 +1653,10 @@ e_web_view_init (EWebView *web_view)
 	web_view->priv = E_WEB_VIEW_GET_PRIVATE (web_view);
 
 	g_signal_connect (
+		web_view, "create-plugin-widget",
+		G_CALLBACK (web_view_create_plugin_widget_cb), NULL);
+
+	g_signal_connect (
 		web_view, "hovering-over-link",
 		G_CALLBACK (web_view_hovering_over_link_cb), NULL);
 
@@ -2599,7 +2782,7 @@ e_web_view_get_default_settings(GtkWidget *parent_widget)
                 "default-font-size", (pango_font_description_get_size (font) / PANGO_SCALE),
                 "default-monospace-font-size", (pango_font_description_get_size (font) / PANGO_SCALE),
                 "enable-frame-flattening", TRUE, 
-                "enable-plugins", TRUE,
+                "enable-plugins", FALSE,
                 "enable-java-applet", FALSE,
                 "enable-html5-database", FALSE,
                 "enable-html5-local-storage", FALSE,
diff --git a/widgets/misc/e-web-view.h b/widgets/misc/e-web-view.h
index 656c8b6..6b32501 100644
--- a/widgets/misc/e-web-view.h
+++ b/widgets/misc/e-web-view.h
@@ -69,6 +69,10 @@ struct _EWebViewClass {
 	WebKitWebViewClass parent_class;
 
 	/* Methods */
+	GtkWidget *	(*create_plugin_widget)	(EWebView *web_view,
+						 const gchar *mime_type,
+						 const gchar *uri,
+						 GHashTable *param);
 	gchar *		(*extract_uri)		(EWebView *web_view,
 						 GdkEventButton *event);
 	void		(*hovering_over_link)	(EWebView *web_view,



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