Index: em-format-html-display.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html-display.c,v
retrieving revision 1.107
diff -u -p -r1.107 em-format-html-display.c
--- em-format-html-display.c	16 Oct 2006 12:37:02 -0000	1.107
+++ em-format-html-display.c	17 Nov 2006 05:46:50 -0000
@@ -74,6 +74,7 @@
 #include <bonobo/bonobo-widget.h>
 
 #include <camel/camel-stream.h>
+#include <camel/camel-stream-filter.h>
 #include <camel/camel-stream-mem.h>
 #include <camel/camel-mime-filter-tohtml.h>
 #include <camel/camel-mime-part.h>
@@ -182,6 +183,9 @@ struct _attach_puri {
 	int fit_height;
 	GtkImage *image;
 
+	/* Optional Text Mem Stream */
+	CamelStreamMem *mstream;
+	
 	/* Signed / Encrypted */
         camel_cipher_validity_sign_t sign;
         camel_cipher_validity_encrypt_t encrypt;
@@ -199,6 +203,7 @@ static void efhd_format_clone(EMFormat *
 static void efhd_format_error(EMFormat *emf, CamelStream *stream, const char *txt);
 static void efhd_format_source(EMFormat *, CamelStream *, CamelMimePart *);
 static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *);
+static void efhd_format_optional(EMFormat *, CamelStream *, CamelMimePart *, CamelStream *);
 static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid);
 static void efhd_complete(EMFormat *);
 gboolean efhd_mnemonic_show_bar (GtkWidget *widget, gboolean focus, GtkWidget *efhd);
@@ -353,6 +358,7 @@ efhd_class_init(GObjectClass *klass)
 	((EMFormatClass *)klass)->format_error = efhd_format_error;
 	((EMFormatClass *)klass)->format_source = efhd_format_source;
 	((EMFormatClass *)klass)->format_attachment = efhd_format_attachment;
+	((EMFormatClass *)klass)->format_optional = efhd_format_optional;	
 	((EMFormatClass *)klass)->format_secure = efhd_format_secure;
 	((EMFormatClass *)klass)->complete = efhd_complete;
 
@@ -1509,7 +1515,7 @@ efhd_attachment_popup(GtkWidget *w, GdkE
 	}
 
 	e_popup_add_items((EPopup *)emp, menus, NULL, efhd_menu_items_free, info);
-
+	
 	menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)target, 0);
 	if (event)
 		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
@@ -2398,7 +2404,6 @@ efhd_format_attachment(EMFormat *emf, Ca
 	if (handle) {
 		if (info->shown)
 			handle->handler(emf, stream, part, handle);
-		/*camel_stream_printf(stream, "<iframe src=\"%s\" marginheight=0 marginwidth=0>%s</iframe>\n", classid, _("Attachment content could not be loaded"));*/
 	} else if (efhd_use_component(mime_type)) {
 		g_free(classid); /* messy */
 
@@ -2406,6 +2411,164 @@ efhd_format_attachment(EMFormat *emf, Ca
 		em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_bonobo_object);
 		camel_stream_printf(stream, "<object classid=\"%s\" type=\"%s\"></object><br>>\n", classid, mime_type);
 	}
+
+	g_free(classid);
+}
+
+static void 
+efhd_optional_button_show (GtkWidget *widget, GtkWidget *w)
+{
+	GtkWidget *label = g_object_get_data (widget, "text-label");
+	
+	if (GTK_WIDGET_VISIBLE (w)) {
+		gtk_widget_hide (w);
+		gtk_label_set_text_with_mnemonic (label, _("View _Unformatted"));
+	} else {
+		gtk_label_set_text_with_mnemonic (label, _("Hide _Unformatted"));		
+		gtk_widget_show (w);
+	}
+}
+
+static void
+efhd_resize (GtkWidget *w, GtkAllocation *event, EMFormatHTML *efh)
+{
+	gtk_widget_set_size_request (w, ((GtkWidget *)efh->html)->allocation.width-48, 250);
+}
+
+/* optional render attachment button callback */
+static gboolean
+efhd_attachment_optional(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
+{
+	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
+	EAttachment *new;
+	struct _attach_puri *info;
+	GtkWidget *hbox, *vbox, *w, *button, *mainbox, *scroll, *label, *img;
+	char *simple_type, *tmp, *new_file = NULL;
+	const char *file;
+	GdkPixbuf *pixbuf, *mini;
+	AtkObject *a11y;
+	GtkTextView *view;
+	GtkTextBuffer *buffer;
+	GtkTargetEntry drag_types[] = {
+		{ NULL, 0, 0 },
+		{ "text/uri-list", 0, 1 },
+	};
+
+	/* FIXME: handle default shown case */
+	d(printf("adding attachment button/content for optional rendering\n"));
+
+	info = (struct _attach_puri *)em_format_find_puri((EMFormat *)efh, pobject->classid);
+	g_assert(info != NULL);
+	g_assert(info->forward == NULL);
+
+	scroll = gtk_scrolled_window_new (NULL, NULL);	
+	mainbox = gtk_hbox_new(FALSE, 0);
+
+	button = gtk_button_new();
+	hbox = gtk_hbox_new (FALSE, 0);
+	img = e_icon_factory_get_image ("stock_show-all", E_ICON_SIZE_BUTTON);
+	label = gtk_label_new_with_mnemonic(_("View _Unformatted"));
+	g_object_set_data (button, "text-label", (gpointer)label);
+	gtk_box_pack_start ((GtkBox *)hbox, img, TRUE, TRUE, 2);
+	gtk_box_pack_start ((GtkBox *)hbox, label, TRUE, TRUE, 2);
+	gtk_widget_show_all (hbox);
+	gtk_container_add (button, hbox);
+	if (info->handle)
+		g_signal_connect(button, "clicked", G_CALLBACK(efhd_optional_button_show), scroll);
+	else {
+		gtk_widget_set_sensitive(button, FALSE);
+		GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
+	}
+	
+	vbox = gtk_vbox_new (FALSE, 0);
+	gtk_box_pack_start((GtkBox *)mainbox, button, FALSE, FALSE, 6);
+
+	button = gtk_button_new();
+	hbox = gtk_hbox_new (FALSE, 0);
+	img = e_icon_factory_get_image ("stock_open", E_ICON_SIZE_BUTTON);
+	label = gtk_label_new_with_mnemonic(_("O_pen With"));
+	gtk_box_pack_start ((GtkBox *)hbox, img, TRUE, TRUE, 2);
+	gtk_box_pack_start ((GtkBox *)hbox, label, TRUE, TRUE, 2);
+	gtk_box_pack_start ((GtkBox *)hbox, gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE), TRUE, TRUE, 2);
+	gtk_widget_show_all (hbox);
+	gtk_container_add (button, hbox);
+	
+	a11y = gtk_widget_get_accessible (button);
+	atk_object_set_name (a11y, _("Attachment"));
+
+	g_signal_connect(button, "button_press_event", G_CALLBACK(efhd_attachment_popup), info);
+	g_signal_connect(button, "popup_menu", G_CALLBACK(efhd_attachment_popup_menu), info);
+	g_signal_connect(button, "clicked", G_CALLBACK(efhd_attachment_popup_menu), info);
+	gtk_box_pack_start((GtkBox *)mainbox, button, FALSE, FALSE, 6);
+
+	gtk_widget_show_all(mainbox);
+
+	gtk_box_pack_start((GtkBox *)vbox, mainbox, FALSE, FALSE, 6);
+
+	view = gtk_text_view_new ();
+	gtk_text_view_set_editable (view, FALSE);
+	gtk_text_view_set_cursor_visible (view, FALSE);
+	buffer = gtk_text_view_get_buffer(view);
+	gtk_text_buffer_set_text (buffer, info->mstream->buffer->data, info->mstream->buffer->len);
+	camel_object_unref(info->mstream);
+	info->mstream = NULL;
+	gtk_scrolled_window_set_policy (scroll, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
+	gtk_container_add (scroll, view);
+	gtk_box_pack_start((GtkBox *)vbox, scroll, TRUE, TRUE, 6);
+	gtk_widget_show (view);
+	gtk_widget_set_size_request (scroll, ((GtkWidget *)efh->html)->allocation.width-48, 250);
+	g_signal_connect (scroll, "size_allocate", G_CALLBACK(efhd_resize), efh);
+	gtk_widget_show (scroll);
+
+	if (!info->shown)
+		gtk_widget_hide (scroll);
+	
+	gtk_widget_show (vbox);
+	gtk_container_add((GtkContainer *)eb, vbox);
+	info->handle = NULL;
+
+	return TRUE;
+}
+
+static void
+efhd_format_optional(EMFormat *emf, CamelStream *fstream, CamelMimePart *part, CamelStream *mstream)
+{
+	char *classid, *text, *html;
+	struct _attach_puri *info;
+	CamelStream *stream = ((CamelStreamFilter *) fstream)->source;
+	
+	classid = g_strdup_printf("optional%s", emf->part_id->str);
+	info = (struct _attach_puri *)em_format_add_puri(emf, sizeof(*info), classid, part, efhd_attachment_frame);
+	em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_optional);
+	info->handle = em_format_find_handler(emf, "text/plain");;
+	info->shown = FALSE;
+	info->snoop_mime_type = g_strdup("text/plain");
+	info->attachment = e_attachment_new_from_mime_part (info->puri.part);
+	info->mstream = mstream;
+	if (emf->valid) {
+		info->sign = emf->valid->sign.status;
+		info->encrypt = emf->valid->encrypt.status;
+	}
+
+	camel_stream_write_string(stream,
+				  EM_FORMAT_HTML_VPAD
+				  "<table cellspacing=0 cellpadding=0><tr><td><h3><font size=-1 color=red>");
+
+	html = camel_text_to_html(_("Evolution cannot render this as it is too large to handle. You can view it unformatted or with an external viewer."), ((EMFormatHTML *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
+	camel_stream_write_string(stream, html);
+	camel_stream_write_string(stream,
+				  "</font></h3></td></tr></table>\n");
+	camel_stream_write_string(stream,
+				  "<table cellspacing=0 cellpadding=0>"
+				  "<tr>");	
+	camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td></tr></table>", classid);
+
+	g_free(html);
+
+	camel_stream_write_string(stream,
+/* 				  "</font></h2></td></tr></table>\n" */
+				  EM_FORMAT_HTML_VPAD);
 
 	g_free(classid);
 }
Index: em-format-html.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
retrieving revision 1.93
diff -u -p -r1.93 em-format-html.c
--- em-format-html.c	29 Sep 2006 17:54:48 -0000	1.93
+++ em-format-html.c	17 Nov 2006 05:46:51 -0000
@@ -767,7 +767,7 @@ efh_text_plain(EMFormatHTML *efh, CamelS
    					"<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px;\">\n",
    					efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff);
 			camel_stream_write_string(stream, "<tt>\n");
-			em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, camel_medium_get_content_object((CamelMedium *)newpart));
+			em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, newpart);
 			camel_stream_flush((CamelStream *)filtered_stream);
 			camel_stream_write_string(stream, "</tt>\n");
 			camel_stream_write_string(stream, "</div>\n");
@@ -807,7 +807,7 @@ efh_text_enriched(EMFormatHTML *efh, Cam
 			     "<div style=\"border: solid #%06x 1px; background-color: #%06x; padding: 10px;\">\n",
 			     efh->frame_colour & 0xffffff, efh->content_colour & 0xffffff);
 
-	em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, dw);
+	em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, part);
 	
 	camel_object_unref(filtered_stream);
 	camel_stream_write_string(stream, "</div>");
@@ -829,7 +829,7 @@ efh_write_text_html(EMFormat *emf, Camel
 		camel_data_wrapper_write_to_stream(dw, out);
 	camel_object_unref(out);
 #endif
-	em_format_format_text(emf, stream, camel_medium_get_content_object((CamelMedium *)puri->part));
+	em_format_format_text(emf, stream, puri->part);
 }
 
 static void
@@ -985,7 +985,7 @@ efh_message_deliverystatus(EMFormatHTML 
 	camel_object_unref(html_filter);
 
 	camel_stream_write_string(stream, "<tt>\n");
-	em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, camel_medium_get_content_object((CamelMedium *)part));
+	em_format_format_text((EMFormat *)efh, (CamelStream *)filtered_stream, part);
 	camel_stream_flush((CamelStream *)filtered_stream);
 	camel_stream_write_string(stream, "</tt>\n");
 
Index: em-format-quote.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-quote.c,v
retrieving revision 1.19
diff -u -p -r1.19 em-format-quote.c
--- em-format-quote.c	8 Aug 2005 04:30:38 -0000	1.19
+++ em-format-quote.c	17 Nov 2006 05:46:51 -0000
@@ -411,7 +411,7 @@ emfq_format_source(EMFormat *emf, CamelS
 	camel_stream_filter_add(filtered_stream, html_filter);
 	camel_object_unref(html_filter);
 	
-	em_format_format_text(emf, (CamelStream *)filtered_stream, dw);
+	em_format_format_text(emf, (CamelStream *)filtered_stream, part);
 	camel_object_unref(filtered_stream);
 }
 
@@ -473,7 +473,7 @@ emfq_text_plain(EMFormatQuote *emfq, Cam
 	camel_stream_filter_add(filtered_stream, html_filter);
 	camel_object_unref(html_filter);
 	
-	em_format_format_text((EMFormat *)emfq, (CamelStream *)filtered_stream, camel_medium_get_content_object((CamelMedium *)part));
+	em_format_format_text((EMFormat *)emfq, (CamelStream *)filtered_stream, part);
 	camel_stream_flush((CamelStream *)filtered_stream);
 	camel_object_unref(filtered_stream);
 }
@@ -501,7 +501,7 @@ emfq_text_enriched(EMFormatQuote *emfq, 
 	camel_object_unref(enriched);
 
 	camel_stream_write_string(stream, "<br><hr><br>");
-	em_format_format_text((EMFormat *)emfq, (CamelStream *)filtered_stream, dw);
+	em_format_format_text((EMFormat *)emfq, (CamelStream *)filtered_stream, part);
 	camel_object_unref(filtered_stream);
 }
 
@@ -509,7 +509,7 @@ static void
 emfq_text_html(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info)
 {
 	camel_stream_write_string(stream, "\n<!-- text/html -->\n");
-	em_format_format_text(emf, stream, camel_medium_get_content_object((CamelMedium *)part));
+	em_format_format_text(emf, stream, part);
 }
 
 static void
Index: em-format.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.c,v
retrieving revision 1.52
diff -u -p -r1.52 em-format.c
--- em-format.c	20 Apr 2006 16:35:32 -0000	1.52
+++ em-format.c	17 Nov 2006 05:46:53 -0000
@@ -47,6 +47,7 @@
 #include <camel/camel-string-utils.h>
 #include <camel/camel-stream-filter.h>
 #include <camel/camel-stream-null.h>
+#include <camel/camel-stream-mem.h>
 #include <camel/camel-mime-filter-charset.h>
 #include <camel/camel-mime-filter-windows.h>
 #include <camel/camel-mime-filter-pgp.h>
@@ -55,6 +56,7 @@
 #include "em-utils.h"
 
 #define d(x) 
+#define MAX_TXT_ATTACHMENT_SIZE 4000000
 
 /* Used to cache various data/info for redraws
    The validity stuff could be cached at a higher level but this is easier
@@ -80,7 +82,6 @@ static const EMFormatHandler *emf_find_h
 static void emf_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *emfsource);
 static void emf_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid);
 static gboolean emf_busy(EMFormat *emf);
-
 enum {
 	EMF_COMPLETE,
 	EMF_LAST_SIGNAL,
@@ -117,11 +118,21 @@ static void
 emf_init(GObject *o)
 {
 	EMFormat *emf = (EMFormat *)o;
-	
+	char * asize;
+		
 	emf->inline_table = g_hash_table_new(g_str_hash, g_str_equal);
+	emf->composer = FALSE;
 	e_dlist_init(&emf->header_list);
 	em_format_default_headers(emf);
 	emf->part_id = g_string_new("");
+	emf->max_file_size = MAX_TXT_ATTACHMENT_SIZE;
+	
+	asize = getenv("EVO_MAX_TEXT_SIZE");
+	if (asize && *asize) {
+		long lsize = atoi (asize);
+		if (lsize)
+			emf->max_file_size = lsize;
+	}
 }
 
 static void
@@ -469,6 +480,7 @@ em_format_find_visible_puri(EMFormat *em
  * Return value: 
  **/
 EMFormatPURI *
+
 em_format_find_puri(EMFormat *emf, const char *uri)
 {
 	return g_hash_table_lookup(emf->pending_uri_table, uri);
@@ -1016,7 +1028,7 @@ em_format_format_content(EMFormat *emf, 
 	CamelDataWrapper *dw = camel_medium_get_content_object((CamelMedium *)part);
 
 	if (camel_content_type_is (dw->mime_type, "text", "*"))
-		em_format_format_text(emf, stream, dw);
+		em_format_format_text(emf, stream, part);
 	else
 		camel_data_wrapper_decode_to_stream(dw, stream);
 }
@@ -1036,6 +1048,8 @@ em_format_format_text(EMFormat *emf, Cam
 	CamelMimeFilterCharset *filter;
 	const char *charset = NULL;
 	CamelMimeFilterWindows *windows = NULL;
+	CamelStream *mem_stream = NULL;
+	size_t size;
 	
 	if (emf->charset) {
 		charset = emf->charset;
@@ -1064,17 +1078,26 @@ em_format_format_text(EMFormat *emf, Cam
 	} else if (charset == NULL) {
 		charset = emf->default_charset;
 	}
-	
-	filter_stream = camel_stream_filter_new_with_stream(stream);
+
+	mem_stream = (CamelStreamMem *)camel_stream_mem_new ();
+	filter_stream = camel_stream_filter_new_with_stream(mem_stream);
 	
 	if ((filter = camel_mime_filter_charset_new_convert(charset, "UTF-8"))) {
 		camel_stream_filter_add(filter_stream, (CamelMimeFilter *) filter);
 		camel_object_unref(filter);
 	}
-	
-	camel_data_wrapper_decode_to_stream(dw, (CamelStream *)filter_stream);
+
+	size = camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)dw), (CamelStream *)filter_stream);
 	camel_stream_flush((CamelStream *)filter_stream);
 	camel_object_unref(filter_stream);
+	camel_stream_reset (mem_stream);
+
+	if (size < emf->max_file_size || emf->composer) {
+		camel_stream_write_to_stream(mem_stream, (CamelStream *)stream);
+		camel_stream_flush((CamelStream *)stream);
+	} else {
+		((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_optional(emf, stream, (CamelMimePart *)dw, mem_stream);
+	}
 
 	if (windows)
 		camel_object_unref(windows);
@@ -1495,7 +1518,7 @@ emf_message_rfc822(EMFormat *emf, CamelS
 static void
 emf_message_deliverystatus(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info)
 {
-	em_format_format_text(emf, stream, camel_medium_get_content_object((CamelMedium *)part));
+	em_format_format_tex(emf, stream, part);
 }
 
 static void
Index: em-format.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.h,v
retrieving revision 1.16
diff -u -p -r1.16 em-format.h
--- em-format.h	19 May 2005 06:06:35 -0000	1.16
+++ em-format.h	17 Nov 2006 05:46:53 -0000
@@ -226,6 +226,8 @@ struct _EMFormat {
 	em_format_mode_t mode;	/* source/headers/etc */
 	char *charset;		/* charset override */
 	char *default_charset;	/* charset fallback */
+	gboolean composer; /* Formatting from composer ?*/
+	long max_file_size; /* Max text size attachment */
 };
 
 struct _EMFormatClass {
@@ -257,6 +259,9 @@ struct _EMFormatClass {
 	/* returns true if the formatter is still busy with pending stuff */
 	gboolean (*busy)(EMFormat *);
 
+	/* Shows optional way to open messages  */
+	void (*format_optional)(EMFormat *, struct _CamelStream *, struct _CamelMimePart *, struct _CamelStream* );
+	
 	/* signals */
 	/* complete, alternative to polling busy, for asynchronous work */
 	void (*complete)(EMFormat *);
Index: em-utils.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-utils.c,v
retrieving revision 1.83
diff -u -p -r1.83 em-utils.c
--- em-utils.c	23 Aug 2006 14:05:19 -0000	1.83
+++ em-utils.c	17 Nov 2006 05:46:54 -0000
@@ -1605,6 +1605,7 @@ em_utils_part_to_html(CamelMimePart *par
 	camel_stream_mem_set_byte_array (mem, buf);
 	
 	emfq = em_format_quote_new(NULL, (CamelStream *)mem, 0);
+	((EMFormat *) emfq)->composer = TRUE;
 	em_format_set_session((EMFormat *)emfq, session);
 	if (source) {
 		/* copy over things we can, other things are internal, perhaps need different api than 'clone' */
@@ -1653,6 +1654,7 @@ em_utils_message_to_html(CamelMimeMessag
 	camel_stream_mem_set_byte_array (mem, buf);
 
 	emfq = em_format_quote_new(credits, (CamelStream *)mem, flags);
+	((EMFormat *) emfq)->composer = TRUE;	
 	em_format_set_session((EMFormat *)emfq, session);
 	
 	if (!source) {
