evolution r35313 - in trunk: . addressbook addressbook/gui/widgets calendar calendar/gui composer mail plugins/exchange-operations plugins/groupwise-features plugins/mailing-list-actions plugins/print-message po tools ui widgets/misc



Author: mbarnes
Date: Wed Apr  2 19:37:22 2008
New Revision: 35313
URL: http://svn.gnome.org/viewvc/evolution?rev=35313&view=rev

Log:
2008-04-02  Matthew Barnes <mbarnes redhat com>

	** Merge the mbarnes-composer branch

	* configure.in:
	Bump libgtkhtml requirement to 3.19.1.
	Add gtkhtml-editor dependency for addressbook, calendar and mail.
	Remove print-message plugin; new composer implements this natively.

	* tools/Makefile.am:
	Remove CORBA rules for the old composer.

	* addressbook/gui/widgets/Makefile.am:
	Remove CORBA rules for the old composer.

	* addressbook/gui/widgets/eab-gui-util.c
	(eab_send_to_contact_and_email_num_list),
	(eab_send_contact_list_as_attachment):
	Adapt to new Bonobo-less composer widget.

	* calendar/gui/Makefile.am:
	Remove CORBA rules for the old composer.

	* calendar/gui/itip-utils.c (comp_from), (comp_to_list),
	(comp_subject), (comp_content_type), (comp_filename),
	(comp_description), (append_cal_attachments), (itip_send_comp),
	(reply_to_calendar_comp):
	Adapt to new Bonobo-less composer widget.

	* composer/Makefile.am:
	Remove CORBA rules for the old composer.

	* composer/e-msg-composer.c:
	* composer/e-msg-composer.h:
	EMsgComposer is now a subclass of GtkhtmlEditor.
	Extensive refactoring and cleanup, too much to list in detail.

	* composer/e-composer-header.c:
	* composer/e-composer-header.h:
	Add "sensitive" property along with get/set functions.

	* composer/e-composer-from-header.c:
	* composer/e-composer-from-header.h:
	Propagate "refreshed" signal from EAccountComboBox.
	Add function e_composer_from_header_get_account_list().

	* composer/e-composer-private.c:
	* composer/e-composer-private.h:
	New files manage composer's private data.
	Allows other composer files to manipulate private data.

	* composer/e-msg-composer-hdrs.c:
	* composer/e-msg-composer-hdrs.h:
	Remove these files; replaced by EComposerHeaderTable widget.

	* composer/evolution-composer.c:
	* composer/evolution-composer.h:
	Remove these files; composer is now a subclass of GtkhtmlEditor.

	* composer/e-msg-composer-select-file.c:
	* composer/e-msg-composer-select-file.h:
	Remove these files; logic moved to e-msg-composer.c.

	* composer/listener.c:
	* composer/listener.h:
	Remove these files; event handlers moved to e-msg-composer.c.

	* composer/Composer.idl:
	* composer/Evolution-Composer.idl:
	Remove these files; composer is no longer a Bonobo object.

	* mail/em-composer-prefs (sig_edit_cb),
	(em_composer_prefs_new_signature):
	Adapt to new Bonobo-less signature editor.

	* mail/mail-signature-editor.c:
	* mail/mail-signature-editor.h:
	Rewrite the signature editor as a subclass of GtkhtmlEditor.
	Eliminates Bonobo from the equation.

	* mail/em-composer-utils.c (composer_get_message),
	(em_utils_composer_send_cb), (save_draft_done),
	(em_utils_composer_save_draft_cb), (create_new_composer),
	(em_utils_compose_new_message),
	(em_utils_compose_new_message_with_mailto), (em_utils_post_to_folder),
	(em_utils_post_to_url), (edit_message), (forward_attached),
	(forward_non_attached), (reply_get_composer), (composer_set_body),
	(em_utils_reply_to_message), (post_reply_to_message):
	Adapt to new Bonobo-less composer.

	* mail/mail-component-factory.c:
	Composer is no longer needs a Bonobo factory.

	* mail/mail-config.c:
	Fix style pattern for EMsgComposer widgets.

	* plugins/groupwise/mail-send-options.c
	(org_gnome_composer_send_options):
	Adapt to streamlined EMsgComposer API.

	* plugins/exchange-operations/Makefile.am:
	Add EVOLUTION_MAIL_CFLAGS and EVOLUTION_MAIL_LIBS.

	* plugins/exchange-operations/exchange-mail-send-options.c
	(append_to_header), (org_gnome_exchange_send_options):
	Adapt to streamlined EMsgComposer API.

	* plugins/mailing-list-actions/mailing-list-actions.c
	(emla_list_action_do):
	Adapt to streamlined EMsgComposer API.

	* po/POTFILES.in: Update file list for new composer.

	* ui/evolution-composer-entries.xml:
	Remove this file; obsoleted by new composer.

	* widgets/misc/Makefile.am:
	Add EVOLUTION_MAIL_LIBS.

	* widgets/misc/e-account-combo-box.c:
	* widgets/misc/e-account-combo-box.h:
	New function e_account_combo_box_get_account_list().
	Emit a "refreshed" signal when the EAccountList changes.
	Add an internal reverse-lookup index.

	* widgets/misc/e-charset-picker.c (e_charser_add_radio_actions):
	New function adds radio actions to an action group.
	Will eventually replace e_charset_picker_bonobo_ui_populate().

	* widgets/misc/e-signature-combo-box.c:
	* widgets/misc/e-signature-combo-box.h:
	New function e_signature_combo_box_get_signature_list().

	... separate issue ...

	* configure.in:
	Bump eds_minimum_version to 2.23.1 for
	CAMEL_FOLDER_JUNKED_NOT_DELETED symbol.



Added:
   trunk/composer/e-composer-actions.c
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-actions.c
   trunk/composer/e-composer-actions.h
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-actions.h
   trunk/composer/e-composer-autosave.c
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-autosave.c
   trunk/composer/e-composer-autosave.h
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-autosave.h
   trunk/composer/e-composer-header-table.c
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-header-table.c
   trunk/composer/e-composer-header-table.h
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-header-table.h
   trunk/composer/e-composer-private.c
   trunk/composer/e-composer-private.h
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/e-composer-private.h
   trunk/composer/evolution-composer.ui
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/evolution-composer.ui
   trunk/composer/gconf-bridge.c
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/gconf-bridge.c
   trunk/composer/gconf-bridge.h
      - copied unchanged from r35304, /branches/mbarnes-composer/composer/gconf-bridge.h
Removed:
   trunk/composer/Composer.idl
   trunk/composer/Evolution-Composer.idl
   trunk/composer/e-msg-composer-hdrs.c
   trunk/composer/e-msg-composer-hdrs.h
   trunk/composer/e-msg-composer-select-file.c
   trunk/composer/e-msg-composer-select-file.h
   trunk/composer/evolution-composer.c
   trunk/composer/evolution-composer.h
   trunk/composer/listener.c
   trunk/composer/listener.h
   trunk/plugins/print-message/
   trunk/ui/evolution-composer-entries.xml
   trunk/ui/evolution-message-composer.xml
Modified:
   trunk/ChangeLog
   trunk/addressbook/ChangeLog
   trunk/addressbook/gui/widgets/Makefile.am
   trunk/addressbook/gui/widgets/eab-gui-util.c
   trunk/calendar/ChangeLog
   trunk/calendar/gui/Makefile.am
   trunk/calendar/gui/itip-utils.c
   trunk/composer/ChangeLog
   trunk/composer/Makefile.am
   trunk/composer/e-composer-common.h
   trunk/composer/e-composer-from-header.c
   trunk/composer/e-composer-from-header.h
   trunk/composer/e-composer-header.c
   trunk/composer/e-composer-header.h
   trunk/composer/e-composer-name-header.c
   trunk/composer/e-composer-name-header.h
   trunk/composer/e-composer-post-header.c
   trunk/composer/e-composer-post-header.h
   trunk/composer/e-composer-text-header.c
   trunk/composer/e-composer-text-header.h
   trunk/composer/e-msg-composer.c
   trunk/composer/e-msg-composer.h
   trunk/configure.in
   trunk/mail/ChangeLog
   trunk/mail/em-composer-prefs.c
   trunk/mail/em-composer-utils.c
   trunk/mail/mail-component-factory.c
   trunk/mail/mail-config.c
   trunk/mail/mail-signature-editor.c
   trunk/mail/mail-signature-editor.h
   trunk/plugins/exchange-operations/ChangeLog
   trunk/plugins/exchange-operations/Makefile.am
   trunk/plugins/exchange-operations/exchange-mail-send-options.c
   trunk/plugins/groupwise-features/ChangeLog
   trunk/plugins/groupwise-features/mail-send-options.c
   trunk/plugins/mailing-list-actions/ChangeLog
   trunk/plugins/mailing-list-actions/mailing-list-actions.c
   trunk/po/ChangeLog
   trunk/po/POTFILES.in
   trunk/tools/Makefile.am
   trunk/ui/ChangeLog
   trunk/ui/Makefile.am
   trunk/widgets/misc/ChangeLog
   trunk/widgets/misc/Makefile.am
   trunk/widgets/misc/e-account-combo-box.c
   trunk/widgets/misc/e-account-combo-box.h
   trunk/widgets/misc/e-charset-picker.c
   trunk/widgets/misc/e-charset-picker.h
   trunk/widgets/misc/e-signature-combo-box.c
   trunk/widgets/misc/e-signature-combo-box.h

Modified: trunk/addressbook/gui/widgets/Makefile.am
==============================================================================
--- trunk/addressbook/gui/widgets/Makefile.am	(original)
+++ trunk/addressbook/gui/widgets/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -16,23 +16,6 @@
 	-I$(top_builddir)/shell				\
 	$(EVOLUTION_ADDRESSBOOK_CFLAGS)
 
-CORBA_COMPOSER_SOURCE_H	=			\
-	Evolution-Composer.h
-CORBA_COMPOSER_SOURCE_C =			\
-	Evolution-Composer-common.c		\
-	Evolution-Composer-skels.c		\
-	Evolution-Composer-stubs.c
-CORBA_COMPOSER_IDL = $(srcdir)/../../../composer/Evolution-Composer.idl
-
-$(CORBA_COMPOSER_SOURCE_H): $(CORBA_COMPOSER_IDL)
-	$(ORBIT_IDL) -I $(srcdir) $(IDL_INCLUDES) $(CORBA_COMPOSER_IDL)
-
-$(CORBA_COMPOSER_SOURCE_C): $(CORBA_COMPOSER_SOURCE_H)
-
-CORBA_SOURCE_H = $(CORBA_COMPOSER_SOURCE_H)
-CORBA_SOURCE_C = $(CORBA_COMPOSER_SOURCE_C)
-CORBA_SOURCE = $(CORBA_SOURCE_H) $(CORBA_SOURCE_C)
-
 noinst_LTLIBRARIES =				\
 	libeabwidgets.la
 
@@ -44,7 +27,6 @@
 	eab-popup.h
 
 libeabwidgets_la_SOURCES =			\
-	$(CORBA_SOURCE)				\
 	$(MARSHAL_GENERATED)			\
 	eab-config.c				\
 	eab-contact-display.c			\
@@ -82,7 +64,7 @@
 MARSHAL_GENERATED = eab-marshal.c eab-marshal.h
 @EVO_MARSHAL_RULE@
 
-BUILT_SOURCES = $(CORBA_SOURCE) $(MARSHAL_GENERATED)
+BUILT_SOURCES = $(MARSHAL_GENERATED)
 CLEANFILES = $(BUILT_SOURCES)
 
 dist-hook:

Modified: trunk/addressbook/gui/widgets/eab-gui-util.c
==============================================================================
--- trunk/addressbook/gui/widgets/eab-gui-util.c	(original)
+++ trunk/addressbook/gui/widgets/eab-gui-util.c	Wed Apr  2 19:37:22 2008
@@ -39,6 +39,7 @@
 #include <e-util/e-icon-factory.h>
 #include "eab-contact-merging.h"
 #include <gnome.h>
+#include <composer/e-msg-composer.h>
 
 /* we link to camel for decoding quoted printable email addresses */
 #include <camel/camel-mime-utils.h>
@@ -766,174 +767,76 @@
 	addressbook_load (dest, got_book_cb, process);
 }
 
-#include <Evolution-Composer.h>
-
-#define COMPOSER_OAFID "OAFIID:GNOME_Evolution_Mail_Composer:" BASE_VERSION
-
 typedef struct {
 	EContact *contact;
 	int email_num; /* if the contact is a person (not a list), the email address to use */
 } ContactAndEmailNum;
 
 static void
-eab_send_to_contact_and_email_num_list (GList *c)
+eab_send_to_contact_and_email_num_list (GList *contact_list)
 {
-	GNOME_Evolution_Composer composer_server;
-	CORBA_Environment ev;
-	GNOME_Evolution_Composer_RecipientList *to_list, *cc_list, *bcc_list;
-	CORBA_char *subject;
-	int to_i, bcc_i;
-	GList *iter;
-	gint to_length = 0, bcc_length = 0;
+	EMsgComposer *composer;
+	EComposerHeaderTable *table;
+	GPtrArray *to_array;
+	GPtrArray *bcc_array;
+
+	union {
+		gpointer *pdata;
+		EDestination **destinations;
+	} convert;
 
-	if (c == NULL)
+	if (contact_list == NULL)
 		return;
 
-	CORBA_exception_init (&ev);
+	composer = e_msg_composer_new ();
+	table = e_msg_composer_get_header_table (composer);
 
-	composer_server = bonobo_activation_activate_from_id (COMPOSER_OAFID, 0, NULL, &ev);
+	to_array = g_ptr_array_new ();
+	bcc_array = g_ptr_array_new ();
 
-	/* Figure out how many addresses of each kind we have. */
-	for (iter = c; iter != NULL; iter = g_list_next (iter)) {
-		ContactAndEmailNum *ce = iter->data;
+	/* Sort contacts into "To" and "Bcc" destinations. */
+	while (contact_list != NULL) {
+		ContactAndEmailNum *ce = contact_list->data;
 		EContact *contact = ce->contact;
-		GList *emails = e_contact_get (contact, E_CONTACT_EMAIL);
-		if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
-			gint len = g_list_length (emails);
-			if (e_contact_get (contact, E_CONTACT_LIST_SHOW_ADDRESSES))
-				to_length += len;
-			else
-				bcc_length += len;
-		} else {
-			if (emails != NULL)
-				++to_length;
-		}
-		g_list_foreach (emails, (GFunc)g_free, NULL);
-		g_list_free (emails);
-	}
+		EDestination *destination;
 
-	/* Now I have to make a CORBA sequences that represents a recipient list with
-	   the right number of entries, for the contacts. */
-	to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	to_list->_maximum = to_length;
-	to_list->_length = to_length;
-	if (to_length > 0) {
-		to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (to_length);
-	}
-
-	cc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	cc_list->_maximum = cc_list->_length = 0;
+		destination = e_destination_new ();
+		e_destination_set_contact (destination, contact, 0);
 
-	bcc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	bcc_list->_maximum = bcc_length;
-	bcc_list->_length = bcc_length;
-	if (bcc_length > 0) {
-		bcc_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (bcc_length);
-	}
-
-	to_i = 0;
-	bcc_i = 0;
-	while (c != NULL) {
-		ContactAndEmailNum *ce = c->data;
-		EContact *contact = ce->contact;
-		int nth = ce->email_num;
-		char *name, *addr;
-		gboolean is_list, is_hidden;
-		GNOME_Evolution_Composer_Recipient *recipient;
-		GList *emails = e_contact_get (contact, E_CONTACT_EMAIL);
-		GList *iterator;
-
-		if (emails != NULL) {
-			is_list = e_contact_get (contact, E_CONTACT_IS_LIST) != NULL;
-			is_hidden = is_list && !e_contact_get (contact, E_CONTACT_LIST_SHOW_ADDRESSES);
-
-			if (is_list) {
-				for (iterator = emails; iterator; iterator = iterator->next) {
-
-					if (is_hidden) {
-						recipient = &(bcc_list->_buffer[bcc_i]);
-						++bcc_i;
-					} else {
-						recipient = &(to_list->_buffer[to_i]);
-						++to_i;
-					}
-
-					name = NULL;
-					addr = NULL;
-					if (iterator && iterator->data) {
-						/* XXX we should probably try to get the name from the attribute parameter here.. */
-						addr = g_strdup ((char*)iterator->data);
-					}
-
-					recipient->name    = CORBA_string_dup (name ? name : "");
-					recipient->address = CORBA_string_dup (addr ? addr : "");
-
-					g_free (name);
-					g_free (addr);
-				}
-			}
-			else {
-				EContactName *contact_name = e_contact_get (contact, E_CONTACT_NAME);
-				int length = g_list_length (emails);
-
-				if (is_hidden) {
-					recipient = &(bcc_list->_buffer[bcc_i]);
-					++bcc_i;
-				} else {
-					recipient = &(to_list->_buffer[to_i]);
-					++to_i;
-				}
-
-				if (nth >= length)
-					nth = 0;
-
-				if (contact_name) {
-					name = e_contact_name_to_string (contact_name);
-					e_contact_name_free (contact_name);
-				}
-				else
-					name = NULL;
-
-				addr = g_strdup (g_list_nth_data (emails, nth));
-
-
-				recipient->name    = CORBA_string_dup (name ? name : "");
-				recipient->address = CORBA_string_dup (addr ? addr : "");
-
-				g_free (name);
-				g_free (addr);
-			}
-
-			g_list_foreach (emails, (GFunc)g_free, NULL);
-			g_list_free (emails);
-		}
-
-		c = c->next;
-	}
-
-	subject = CORBA_string_dup ("");
-
-	GNOME_Evolution_Composer_setHeaders (composer_server, "", to_list, cc_list, bcc_list, subject, &ev);
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_printerr ("gui/e-meeting-edit.c: I couldn't set the composer headers via CORBA! Aagh.\n");
-		CORBA_exception_free (&ev);
-		return;
-	}
-
-	CORBA_free (to_list);
-	CORBA_free (cc_list);
-	CORBA_free (bcc_list);
-	CORBA_free (subject);
-
-	GNOME_Evolution_Composer_show (composer_server, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_printerr ("gui/e-meeting-edit.c: I couldn't show the composer via CORBA! Aagh.\n");
-		CORBA_exception_free (&ev);
-		return;
-	}
+		if (e_destination_is_evolution_list (destination)) {
+			if (e_destination_list_show_addresses (destination))
+				g_ptr_array_add (to_array, destination);
+			else
+				g_ptr_array_add (bcc_array, destination);
+		} else
+			g_ptr_array_add (to_array, destination);
+
+		contact_list = g_list_next (contact_list);
+	}
+
+	/* Add sentinels to each array. */
+	g_ptr_array_add (to_array, NULL);
+	g_ptr_array_add (bcc_array, NULL);
+
+	/* XXX Acrobatics like this make me question whether NULL-terminated
+	 *     arrays are really the best argument type for passing a list of
+	 *     destinations to the header table. */
+
+	/* Add "To" destinations. */
+	convert.pdata = to_array->pdata;
+	e_composer_header_table_set_destinations_to (
+		table, convert.destinations);
+	g_ptr_array_free (to_array, FALSE);
+	e_destination_freev (convert.destinations);
+
+	/* Add "Bcc" destinations. */
+	convert.pdata = bcc_array->pdata;
+	e_composer_header_table_set_destinations_bcc (
+		table, convert.destinations);
+	g_ptr_array_free (bcc_array, FALSE);
+	e_destination_freev (convert.destinations);
 
-	CORBA_exception_free (&ev);
+	gtk_widget_show (GTK_WIDGET (composer));
 }
 
 static const char *
@@ -958,75 +861,48 @@
 static void
 eab_send_contact_list_as_attachment (GList *contacts)
 {
-	GNOME_Evolution_Composer composer_server;
-	CORBA_Environment ev;
-	CORBA_char *content_type, *filename, *description;
-	GNOME_Evolution_Composer_AttachmentData *attach_data;
-	CORBA_boolean show_inline;
-	char *tempstr;
-	GNOME_Evolution_Composer_RecipientList *to_list, *cc_list, *bcc_list;
-	CORBA_char *subject;
+	EMsgComposer *composer;
+	EComposerHeaderTable *table;
+	CamelMimePart *attachment;
+	gchar *data;
 
 	if (contacts == NULL)
 		return;
 
-	CORBA_exception_init (&ev);
-
-	composer_server = bonobo_activation_activate_from_id (COMPOSER_OAFID, 0, NULL, &ev);
-
-
+	composer = e_msg_composer_new ();
+	table = e_msg_composer_get_header_table (composer);
 
-	content_type = CORBA_string_dup ("text/x-vcard");
-	filename = CORBA_string_dup ("");
+	attachment = camel_mime_part_new ();
+	data = eab_contact_list_to_string (contacts);
 
-	if (contacts->next) {
-		description = CORBA_string_dup (_("Multiple vCards"));
-	} else {
-		char *file_as = e_contact_get (E_CONTACT (contacts->data), E_CONTACT_FILE_AS);
-		tempstr = g_strdup_printf (_("vCard for %s"), file_as);
-		description = CORBA_string_dup (tempstr);
-		g_free (tempstr);
-		g_free (file_as);
-	}
+	camel_mime_part_set_content (
+		attachment, data, strlen (data), "text/x-vcard");
 
-	show_inline = FALSE;
+	if (contacts->next != NULL)
+		camel_mime_part_set_description (
+			attachment, _("Multiple vCards"));
+	else {
+		EContact *contact = contacts->data;
+		const gchar *file_as;
+		gchar *description;
 
-	tempstr = eab_contact_list_to_string (contacts);
-	attach_data = GNOME_Evolution_Composer_AttachmentData__alloc();
-	attach_data->_maximum = attach_data->_length = strlen (tempstr);
-	attach_data->_buffer = CORBA_sequence_CORBA_char_allocbuf (attach_data->_length);
-	memcpy (attach_data->_buffer, tempstr, attach_data->_length);
-	g_free (tempstr);
-
-	GNOME_Evolution_Composer_attachData (composer_server,
-					     content_type, filename, description,
-					     show_inline, attach_data,
-					     &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_printerr ("gui/e-meeting-edit.c: I couldn't attach data to the composer via CORBA! Aagh.\n");
-		CORBA_exception_free (&ev);
-		return;
+		file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
+		description = g_strdup_printf (_("vCard for %s"), file_as);
+		camel_mime_part_set_description (attachment, description);
+		g_free (description);
 	}
 
-	CORBA_free (content_type);
-	CORBA_free (filename);
-	CORBA_free (description);
-	CORBA_free (attach_data);
-
-	to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	to_list->_maximum = to_list->_length = 0;
-
-	cc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	cc_list->_maximum = cc_list->_length = 0;
+	camel_mime_part_set_disposition (attachment, "attachment");
 
-	bcc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	bcc_list->_maximum = bcc_list->_length = 0;
+	e_msg_composer_attach (composer, attachment);
+	camel_object_unref (attachment);
 
-	if (!contacts || contacts->next) {
-		subject = CORBA_string_dup (_("Contact information"));
-	} else {
+	if (contacts->next != NULL)
+		e_composer_header_table_set_subject (
+			table, _("Contact information"));
+	else {
 		EContact *contact = contacts->data;
+		gchar *tempstr;
 		const gchar *tempstr2;
 		gchar *tempfree = NULL;
 
@@ -1052,27 +928,14 @@
 			tempstr = g_strdup_printf (_("Contact information"));
 		else
 			tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2);
-		subject = CORBA_string_dup (tempstr);
-		g_free (tempstr);
-		g_free (tempfree);
-	}
 
-	GNOME_Evolution_Composer_setHeaders (composer_server, "", to_list, cc_list, bcc_list, subject, &ev);
+		e_composer_header_table_set_subject (table, tempstr);
 
-	CORBA_free (to_list);
-	CORBA_free (cc_list);
-	CORBA_free (bcc_list);
-	CORBA_free (subject);
-
-	GNOME_Evolution_Composer_show (composer_server, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_printerr ("gui/e-meeting-edit.c: I couldn't show the composer via CORBA! Aagh.\n");
-		CORBA_exception_free (&ev);
-		return;
+		g_free (tempstr);
+		g_free (tempfree);
 	}
 
-	CORBA_exception_free (&ev);
+	gtk_widget_show (GTK_WIDGET (composer));
 }
 
 void

Modified: trunk/calendar/gui/Makefile.am
==============================================================================
--- trunk/calendar/gui/Makefile.am	(original)
+++ trunk/calendar/gui/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -5,7 +5,6 @@
 ## CORBA stuff
 
 IDLS =								\
-	$(top_srcdir)/composer/Evolution-Composer.idl		\
 	$(top_srcdir)/calendar/idl/evolution-calendar.idl
 
 CALENDAR_IDL_GENERATED_H =		\
@@ -21,22 +20,7 @@
                 $(top_srcdir)/calendar/idl/evolution-calendar.idl
 $(CALENDAR_IDL_GENERATED_C): $(CALENDAR_IDL_GENERATED_H)
 
-# Message composer IDL files
-
-COMPOSER_IDL_GENERATED_H = \
-        Evolution-Composer.h
-COMPOSER_IDL_GENERATED_C =             			\
-        Evolution-Composer-common.c       		\
-        Evolution-Composer-skels.c        		\
-        Evolution-Composer-stubs.c
-COMPOSER_IDL_GENERATED = $(COMPOSER_IDL_GENERATED_C) $(COMPOSER_IDL_GENERATED_H)
-
-$(COMPOSER_IDL_GENERATED_H): $(IDLS)
-	$(ORBIT_IDL) -I $(srcdir) $(IDL_INCLUDES)   \
-                $(srcdir)/../../composer/Evolution-Composer.idl
-$(COMPOSER_IDL_GENERATED_C): $(COMPOSER_IDL_GENERATED_H)
-
-IDL_GENERATED = $(CALENDAR_IDL_GENERATED) $(COMPOSER_IDL_GENERATED)
+IDL_GENERATED = $(CALENDAR_IDL_GENERATED)
 
 # The marshallers
 MARSHAL_GENERATED = e-calendar-marshal.c e-calendar-marshal.h

Modified: trunk/calendar/gui/itip-utils.c
==============================================================================
--- trunk/calendar/gui/itip-utils.c	(original)
+++ trunk/calendar/gui/itip-utils.c	Wed Apr  2 19:37:22 2008
@@ -24,15 +24,11 @@
 #include <config.h>
 #endif
 
-#include <bonobo/bonobo-exception.h>
-#include <bonobo/bonobo-object.h>
-#include <bonobo/bonobo-moniker-util.h>
 #include <glib/gi18n.h>
 #include <libedataserver/e-time-utils.h>
 #include <gtk/gtkmessagedialog.h>
 #include <gtk/gtkwidget.h>
 #include <libical/ical.h>
-#include <Evolution-Composer.h>
 #include <e-util/e-dialog-utils.h>
 #include <libecal/e-cal-time-util.h>
 #include <libecal/e-cal-util.h>
@@ -41,7 +37,9 @@
 #include "itip-utils.h"
 #include <time.h>
 
-#define GNOME_EVOLUTION_COMPOSER_OAFIID "OAFIID:GNOME_Evolution_Mail_Composer:" BASE_VERSION
+#include <composer/e-msg-composer.h>
+#include <mail/em-composer-utils.h>
+#include <camel/camel-mime-filter-tohtml.h>
 
 static gchar *itip_methods[] = {
 	"PUBLISH",
@@ -408,36 +406,28 @@
 	return FALSE;
 }
 
-static CORBA_char *
+static gchar *
 comp_from (ECalComponentItipMethod method, ECalComponent *comp)
 {
 	ECalComponentOrganizer organizer;
 	ECalComponentAttendee *attendee;
 	GSList *attendees;
-	CORBA_char *str;
+	gchar *from;
 	char *sender = NULL;
 
 	switch (method) {
 	case E_CAL_COMPONENT_METHOD_PUBLISH:
-		return CORBA_string_dup ("");
+		return NULL;
 
 	case E_CAL_COMPONENT_METHOD_REQUEST:
-		sender = itip_get_comp_attendee (comp, NULL);
-		if (sender) {
-			str = CORBA_string_dup (sender);
-			g_free (sender);
-			return str;
-		}
+		return itip_get_comp_attendee (comp, NULL);
 
 	case E_CAL_COMPONENT_METHOD_REPLY:
 		sender = itip_get_comp_attendee (comp, NULL);
-		if (sender) {
-			str = CORBA_string_dup (sender);
-			g_free (sender);
-			return str;
-		}
+		if (sender != NULL)
+			return sender;
 		if (!e_cal_component_has_attendees (comp))
-			return CORBA_string_dup ("");
+			return NULL;
 
 	case E_CAL_COMPONENT_METHOD_CANCEL:
 
@@ -449,32 +439,40 @@
 				  _("An organizer must be set."));
 			return NULL;
 		}
-		return CORBA_string_dup (itip_strip_mailto (organizer.value));
+		return g_strdup (itip_strip_mailto (organizer.value));
 
 
 	default:
 		if (!e_cal_component_has_attendees (comp))
-			return CORBA_string_dup ("");
+			return NULL;
 
 		e_cal_component_get_attendee_list (comp, &attendees);
 		attendee = attendees->data;
-		str = CORBA_string_dup (attendee->value ? itip_strip_mailto (attendee->value) : "");
+		if (attendee->value != NULL)
+			from = g_strdup (itip_strip_mailto (attendee->value));
+		else
+			from = NULL;
 		e_cal_component_free_attendee_list (attendees);
 
-		return str;
+		return from;
 	}
 }
 
-static GNOME_Evolution_Composer_RecipientList *
+static EDestination **
 comp_to_list (ECalComponentItipMethod method, ECalComponent *comp, GList *users, gboolean reply_all)
 {
-	GNOME_Evolution_Composer_RecipientList *to_list;
-	GNOME_Evolution_Composer_Recipient *recipient;
 	ECalComponentOrganizer organizer;
 	GSList *attendees, *l;
+	GPtrArray *array = NULL;
+	EDestination *destination;
 	gint len;
  	char *sender = NULL;
 
+	union {
+		gpointer *pdata;
+		EDestination **destinations;
+	} convert;
+
 	switch (method) {
 	case E_CAL_COMPONENT_METHOD_REQUEST:
 	case E_CAL_COMPONENT_METHOD_CANCEL:
@@ -487,11 +485,6 @@
 			return NULL;
 		}
 
-		to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-		to_list->_maximum = len;
-		to_list->_length = 0;
-		to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
-
 		e_cal_component_get_organizer (comp, &organizer);
 		if (organizer.value == NULL) {
 			e_notice (NULL, GTK_MESSAGE_ERROR,
@@ -499,6 +492,8 @@
 			return NULL;
 		}
 
+		array = g_ptr_array_new ();
+
 		sender = itip_get_comp_attendee (comp, NULL);
 
 		for (l = attendees; l != NULL; l = l->next) {
@@ -518,14 +513,12 @@
 					&& !(att->rsvp) && method == E_CAL_COMPONENT_METHOD_REQUEST)
 				continue;
 
-			recipient = &(to_list->_buffer[to_list->_length]);
-			if (att->cn)
-				recipient->name = CORBA_string_dup (att->cn);
-			else
-				recipient->name = CORBA_string_dup ("");
-			recipient->address = CORBA_string_dup (itip_strip_mailto (att->value));
-
-			to_list->_length++;
+			destination = e_destination_new ();
+			if (att->cn != NULL)
+				e_destination_set_name (destination, att->cn);
+			e_destination_set_email (
+				destination, itip_strip_mailto (att->value));
+			g_ptr_array_add (array, destination);
 		}
 		g_free (sender);
 		e_cal_component_free_attendee_list (attendees);
@@ -537,19 +530,10 @@
 			e_cal_component_get_attendee_list (comp, &attendees);
 			len = g_slist_length (attendees);
 
-			if (len <= 0) {
-				to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-				to_list->_maximum = len;
-				to_list->_length = 0;
-				to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
-				e_cal_component_free_attendee_list (attendees);
-				return to_list;
-			}
+			if (len <= 0)
+				return NULL;
 
-			to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-			to_list->_maximum = len;
-			to_list->_length = 0;
-			to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
+			array = g_ptr_array_new ();
 
 			e_cal_component_get_organizer (comp, &organizer);
 			sender = itip_get_comp_attendee (comp, NULL);
@@ -557,39 +541,26 @@
 			for (l = attendees; l != NULL; l = l->next) {
 				ECalComponentAttendee *att = l->data;
 
-
-				recipient = &(to_list->_buffer[to_list->_length]);
-				if (att->cn)
-					recipient->name = CORBA_string_dup (att->cn);
-				else
-					recipient->name = CORBA_string_dup ("");
-				recipient->address = CORBA_string_dup (itip_strip_mailto (att->value));
-
-				to_list->_length++;
+				destination = e_destination_new ();
+				if (att->cn != NULL)
+					e_destination_set_name (destination, att->cn);
+				e_destination_set_email (
+					destination, itip_strip_mailto (att->value));
+				g_ptr_array_add (array, destination);
 			}
 
 			g_free (sender);
 			e_cal_component_free_attendee_list (attendees);
 
 		} else {
+			array = g_ptr_array_new ();
 
-			to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-			to_list->_maximum = 1;
-			to_list->_length = 0;
-			to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (1);
-
-			recipient = &(to_list->_buffer[to_list->_length]);
-
+			destination = e_destination_new ();
 			e_cal_component_get_organizer (comp, &organizer);
-			if (organizer.value) {
-				recipient->name = CORBA_string_dup ("");
-				recipient->address = CORBA_string_dup (itip_strip_mailto (organizer.value));
-				to_list->_length++;
-				return to_list;
-			} else {
-				recipient->address = CORBA_string_dup ("");
-				recipient->name = CORBA_string_dup ("");
-			}
+			if (organizer.value)
+				e_destination_set_email (
+					destination, itip_strip_mailto (organizer.value));
+			g_ptr_array_add (array, destination);
 		}
 		break;
 
@@ -605,20 +576,14 @@
 			return NULL;
 		}
 
-		len = 2;
-
-		to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-		to_list->_maximum = len;
-		to_list->_length = 0;
-		to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
-		recipient = &(to_list->_buffer[0]);
-		to_list->_length++;
+		array = g_ptr_array_new ();
 
+		destination = e_destination_new ();
 		if (organizer.cn != NULL)
-			recipient->name = CORBA_string_dup (organizer.cn);
-		else
-			recipient->name = CORBA_string_dup ("");
-		recipient->address = CORBA_string_dup (itip_strip_mailto (organizer.value));
+			e_destination_set_name (destination, organizer.cn);
+		e_destination_set_email (
+			destination, itip_strip_mailto (organizer.value));
+		g_ptr_array_add (array, destination);
 
 		/* send the status to delegatee to the delegate also*/
 		e_cal_component_get_attendee_list (comp, &attendees);
@@ -632,10 +597,10 @@
 				if (!(att->delfrom && *att->delfrom))
 					break;
 
-				recipient = &(to_list->_buffer[to_list->_length]);
-				recipient->name = CORBA_string_dup ("");
-				recipient->address = CORBA_string_dup (itip_strip_mailto (att->delfrom));
-				to_list->_length++;
+				destination = e_destination_new ();
+				e_destination_set_email (
+					destination, itip_strip_mailto (att->delfrom));
+				g_ptr_array_add (array, destination);
 			}
 
 		}
@@ -646,38 +611,37 @@
 		if(users) {
 			GList *list;
 
-			len = g_list_length (users);
-			to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-			to_list->_maximum = len;
-			to_list->_length = 0;
-			to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
+			array = g_ptr_array_new ();
 
 			for (list = users; list != NULL; list = list->next) {
-				recipient = &(to_list->_buffer[to_list->_length]);
-				recipient->name = CORBA_string_dup ("");
-				recipient->address = CORBA_string_dup (list->data);
-				to_list->_length++;
+				destination = e_destination_new ();
+				e_destination_set_email (destination, list->data);
+				g_ptr_array_add (array, destination);
 			}
 
 			break;
 		}
 	default:
-		to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-		to_list->_maximum = to_list->_length = 0;
 		break;
 	}
-	CORBA_sequence_set_release (to_list, TRUE);
 
-	return to_list;
+	if (array == NULL)
+		return NULL;
+
+	convert.pdata = array->pdata;
+	g_ptr_array_add (array, NULL);
+	g_ptr_array_free (array, FALSE);
+
+	return convert.destinations;
 }
 
-static CORBA_char *
+static gchar *
 comp_subject (ECalComponentItipMethod method, ECalComponent *comp)
 {
 	ECalComponentText caltext;
 	const char *description, *prefix = NULL;
 	GSList *alist, *l;
-	CORBA_char *subject;
+	gchar *subject;
 	char *sender;
 	ECalComponentAttendee *a = NULL;
 
@@ -767,54 +731,49 @@
 		break;
 	}
 
-	if (prefix) {
-		subject = CORBA_string_alloc (strlen (description) +
-					      strlen (prefix) + 3);
-		sprintf (subject, "%s: %s", prefix, description);
-	} else
-		subject = CORBA_string_dup (description);
+	if (prefix != NULL)
+		subject = g_strdup_printf ("%s: %s", prefix, description);
+	else
+		subject = g_strdup (description);
 
 	return subject;
 }
 
-static CORBA_char *
+static gchar *
 comp_content_type (ECalComponent *comp, ECalComponentItipMethod method)
 {
-	char tmp[256];
-
-	sprintf (tmp, "text/calendar; name=\"%s\"; charset=utf-8; METHOD=%s",
-		 e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_FREEBUSY ?
-		 "freebusy.ifb" : "calendar.ics", itip_methods[method]);
-
-	return CORBA_string_dup (tmp);
-
+	return g_strdup_printf (
+		"text/calendar; name=\"%s\"; charset=utf-8; METHOD=%s",
+		e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_FREEBUSY ?
+		"freebusy.ifb" : "calendar.ics", itip_methods[method]);
 }
 
-static CORBA_char *
+static const gchar *
 comp_filename (ECalComponent *comp)
 {
-        switch (e_cal_component_get_vtype (comp)) {
-        case E_CAL_COMPONENT_FREEBUSY:
-                return CORBA_string_dup ("freebusy.ifb");
-        default:
-                return CORBA_string_dup ("calendar.ics");
-        }
+	if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_FREEBUSY)
+		return "freebusy.ifb";
+	else
+		return "calendar.ics";
 }
 
-static CORBA_char *
+static gchar *
 comp_description (ECalComponent *comp)
 {
-        CORBA_char *description;
+	gchar *description;
         ECalComponentDateTime dt;
         char *start = NULL, *end = NULL;
 
         switch (e_cal_component_get_vtype (comp)) {
         case E_CAL_COMPONENT_EVENT:
-                return CORBA_string_dup (_("Event information"));
+                description = g_strdup (_("Event information"));
+		break;
         case E_CAL_COMPONENT_TODO:
-                return CORBA_string_dup (_("Task information"));
+                description = g_strdup (_("Task information"));
+		break;
         case E_CAL_COMPONENT_JOURNAL:
-                return CORBA_string_dup (_("Memo information"));
+                description = g_strdup (_("Memo information"));
+		break;
         case E_CAL_COMPONENT_FREEBUSY:
                 e_cal_component_get_dtstart (comp, &dt);
                 if (dt.value)
@@ -826,20 +785,21 @@
 			end = get_label (dt.value);
 		e_cal_component_free_datetime (&dt);
 
-                if (start != NULL && end != NULL) {
-                        char *tmp;
-                        tmp = g_strdup_printf (_("Free/Busy information (%s to %s)"), start, end);
-                        description = CORBA_string_dup (tmp);
-                        g_free (tmp);
-                } else {
-                        description = CORBA_string_dup (_("Free/Busy information"));
-                }
+                if (start != NULL && end != NULL)
+			description = g_strdup_printf (
+				_("Free/Busy information (%s to %s)"),
+				start, end);
+                else
+			description = g_strdup (_("Free/Busy information"));
                 g_free (start);
                 g_free (end);
-                return description;
+		break;
         default:
-                return CORBA_string_dup (_("iCalendar information"));
+                description = g_strdup (_("iCalendar information"));
+		break;
         }
+
+	return description;
 }
 
 static gboolean
@@ -1161,84 +1121,64 @@
 	return clone;
 }
 
-static gboolean
-append_cal_attachments (GNOME_Evolution_Composer composer_server, ECalComponent
-		*comp, GSList *attach_list)
+static void
+append_cal_attachments (EMsgComposer *composer,
+                        ECalComponent *comp,
+                        GSList *attach_list)
 {
-	CORBA_char *content_type = NULL, *filename = NULL, *description = NULL;
-	CORBA_Environment ev;
-	GNOME_Evolution_Composer_AttachmentData *attach_data = NULL;
 	struct CalMimeAttach *mime_attach;
 	GSList *l;
-	gboolean retval = TRUE;
-
-	CORBA_exception_init (&ev);
 
 	for (l = attach_list; l ; l = l->next) {
+		CamelMimePart *attachment;
+
 		mime_attach = (struct CalMimeAttach *) l->data;
 
-		filename = CORBA_string_dup (mime_attach->filename ? mime_attach->filename : "");
-		content_type = CORBA_string_dup	(mime_attach->content_type);
-		description = CORBA_string_dup (mime_attach->description);
-
-		attach_data = GNOME_Evolution_Composer_AttachmentData__alloc ();
-		attach_data->_length = mime_attach->length;
-		attach_data->_maximum = attach_data->_length;
-		attach_data->_buffer = CORBA_sequence_CORBA_char_allocbuf (attach_data->_length);
-		memcpy (attach_data->_buffer, mime_attach->encoded_data, attach_data->_length);
-
-		GNOME_Evolution_Composer_attachData (composer_server,
-						     content_type, filename, description,
-						     mime_attach->disposition, attach_data,
-						     &ev);
-		if (BONOBO_EX (&ev)) {
-			g_warning ("Unable to add attachments in composer");
-			retval = FALSE;
-		}
+		attachment = camel_mime_part_new ();
+		camel_mime_part_set_content (
+			attachment, mime_attach->encoded_data,
+			mime_attach->length, mime_attach->content_type);
+		if (mime_attach->filename != NULL)
+			camel_mime_part_set_filename (
+				attachment, mime_attach->filename);
+		if (mime_attach->description != NULL)
+			camel_mime_part_set_description (
+				attachment, mime_attach->description);
+		if (mime_attach->disposition)
+			camel_mime_part_set_disposition (
+				attachment, "inline");
+		else
+			camel_mime_part_set_disposition (
+				attachment, "attachment");
+		e_msg_composer_attach (composer, attachment);
+		camel_object_unref (attachment);
 
-		CORBA_exception_free (&ev);
-		if (content_type != NULL)
-			CORBA_free (content_type);
-		if (filename != NULL)
-			CORBA_free (filename);
-		if (description != NULL)
-			CORBA_free (description);
-		if (attach_data != NULL) {
-			CORBA_free (attach_data->_buffer);
-			CORBA_free (attach_data);
-		}
 		g_free (mime_attach->filename);
 		g_free (mime_attach->content_type);
 		g_free (mime_attach->description);
 		g_free (mime_attach->encoded_data);
 	}
-
-	return retval;
 }
 
 gboolean
 itip_send_comp (ECalComponentItipMethod method, ECalComponent *send_comp,
 		ECal *client, icalcomponent *zones, GSList *attachments_list, GList *users)
 {
-	GNOME_Evolution_Composer composer_server;
+	EMsgComposer *composer;
+	EComposerHeaderTable *table;
+	EDestination **destinations;
 	ECalComponent *comp = NULL;
 	icalcomponent *top_level = NULL;
-	GNOME_Evolution_Composer_RecipientList *to_list = NULL;
-	GNOME_Evolution_Composer_RecipientList *cc_list = NULL;
-	GNOME_Evolution_Composer_RecipientList *bcc_list = NULL;
-	CORBA_char *subject = NULL, *body = NULL, *content_type = NULL;
-	CORBA_char *from = NULL, *filename = NULL, *description = NULL;
-	GNOME_Evolution_Composer_AttachmentData *attach_data = NULL;
 	char *ical_string = NULL;
-	CORBA_Environment ev;
+	gchar *from;
+	gchar *content_type;
+	gchar *subject;
 	gboolean retval = FALSE;
 
 	/* check whether backend could handle sending requests/updates */
 	if (method != E_CAL_COMPONENT_METHOD_PUBLISH && e_cal_get_save_schedules (client))
 		return TRUE;
 
-	CORBA_exception_init (&ev);
-
 	/* Give the server a chance to manipulate the comp */
 	if (method != E_CAL_COMPONENT_METHOD_PUBLISH) {
 		if (!comp_server_send (method, send_comp, client, zones, &users))
@@ -1252,46 +1192,30 @@
 		goto cleanup;
 
 	/* Recipients */
-	to_list = comp_to_list (method, comp, users, FALSE);
+	destinations = comp_to_list (method, comp, users, FALSE);
 	if (method != E_CAL_COMPONENT_METHOD_PUBLISH) {
-		if (to_list == NULL || to_list->_length == 0) {
+		if (destinations == NULL) {
 			/* We sent them all via the server */
 			retval = TRUE;
 			goto cleanup;
-		} else if (to_list == NULL || to_list->_length == 0) {
-			/* if we don't have recipients, return */
-			retval = FALSE;
-			goto cleanup;
 		}
 	}
 
-	cc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	cc_list->_maximum = cc_list->_length = 0;
-	bcc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	bcc_list->_maximum = bcc_list->_length = 0;
-
 	/* Subject information */
 	subject = comp_subject (method, comp);
 
 	/* From address */
 	from = comp_from (method, comp);
 
-	/* Obtain an object reference for the Composer. */
-	composer_server = bonobo_activation_activate_from_id (GNOME_EVOLUTION_COMPOSER_OAFIID, 0, NULL, &ev);
-	if (BONOBO_EX (&ev)) {
-		g_warning ("Could not activate composer: %s", bonobo_exception_get_text (&ev));
-		CORBA_exception_free (&ev);
-		return FALSE;
-	}
-
-	/* Set recipients, subject */
-	GNOME_Evolution_Composer_setHeaders (composer_server, from, to_list, cc_list, bcc_list, subject, &ev);
-	if (BONOBO_EX (&ev)) {
-		g_warning ("Unable to set composer headers while sending iTip message: %s",
-			   bonobo_exception_get_text (&ev));
-		goto cleanup;
-	}
+	composer = e_msg_composer_new ();
+	table = e_msg_composer_get_header_table (composer);
+	em_composer_utils_setup_default_callbacks (composer);
+
+	e_composer_header_table_set_subject (table, subject);
+	e_composer_header_table_set_account_name (table, from);
+	e_composer_header_table_set_destinations_to (table, destinations);
 
+	e_destination_freev (destinations);
 
 	/* Content type */
 	content_type = comp_content_type (comp, method);
@@ -1300,62 +1224,46 @@
 	ical_string = icalcomponent_as_ical_string (top_level);
 
 	if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_EVENT) {
-		GNOME_Evolution_Composer_setBody (composer_server, ical_string, content_type, &ev);
+		e_msg_composer_set_body (composer, ical_string, content_type);
 	} else {
-		GNOME_Evolution_Composer_setMultipartType (composer_server, GNOME_Evolution_Composer_MIXED, &ev);
-		if (BONOBO_EX (&ev)) {
-			g_warning ("Unable to set multipart type while sending iTip message");
-			goto cleanup;
-		}
+		CamelMimePart *attachment;
+		const gchar *filename;
+		gchar *description;
+		gchar *body;
 
 		filename = comp_filename (comp);
 		description = comp_description (comp);
 
-		GNOME_Evolution_Composer_setBody (composer_server, description, "text/plain", &ev);
-		if (BONOBO_EX (&ev)) {
-			g_warning ("Unable to set body text while sending iTip message");
-			goto cleanup;
-		}
+		body = camel_text_to_html (
+			body, CAMEL_MIME_FILTER_TOHTML_PRE, 0);
+		e_msg_composer_set_body_text (composer, body, -1);
+		g_free (body);
+
+		attachment = camel_mime_part_new ();
+		camel_mime_part_set_content (
+			attachment, ical_string,
+			strlen (ical_string), content_type);
+		if (filename != NULL && *filename != '\0')
+			camel_mime_part_set_filename (attachment, filename);
+		if (description != NULL && *description != '\0')
+			camel_mime_part_set_description (attachment, description);
+		camel_mime_part_set_disposition (attachment, "inline");
+		e_msg_composer_attach (composer, attachment);
+		camel_object_unref (attachment);
 
-		attach_data = GNOME_Evolution_Composer_AttachmentData__alloc ();
-		attach_data->_length = strlen (ical_string);
-		attach_data->_maximum = attach_data->_length;
-		attach_data->_buffer = CORBA_sequence_CORBA_char_allocbuf (attach_data->_length);
-		memcpy (attach_data->_buffer, ical_string, attach_data->_length);
-
-		GNOME_Evolution_Composer_attachData (composer_server,
-						     content_type, filename, description,
-						     TRUE, attach_data,
-						     &ev);
+		g_free (description);
 	}
 
-	if (BONOBO_EX (&ev)) {
-		g_warning ("Unable to place iTip message in composer");
-		goto cleanup;
-	}
+	append_cal_attachments (composer, comp, attachments_list);
 
-	if (attachments_list) {
-		if (append_cal_attachments (composer_server, comp, attachments_list))
-			retval = TRUE;
-	}
+	if ((method == E_CAL_COMPONENT_METHOD_PUBLISH) && !users)
+		gtk_widget_show (GTK_WIDGET (composer));
+	else
+		e_msg_composer_send (composer);
 
-	if ((method == E_CAL_COMPONENT_METHOD_PUBLISH) && !users) {
-		GNOME_Evolution_Composer_show (composer_server, &ev);
-		if (BONOBO_EX (&ev))
-			g_warning ("Unable to show the composer while sending iTip message");
-		else
-			retval = TRUE;
-	} else {
-		GNOME_Evolution_Composer_send (composer_server, &ev);
-		if (BONOBO_EX (&ev))
-			g_warning ("Unable to send iTip message");
-		else
-			retval = TRUE;
-	}
+	retval = TRUE;
 
  cleanup:
-	CORBA_exception_free (&ev);
-
 	if (comp != NULL)
 		g_object_unref (comp);
 	if (top_level != NULL)
@@ -1366,66 +1274,40 @@
 		g_list_free (users);
 	}
 
-	if (to_list != NULL)
-		CORBA_free (to_list);
-	if (cc_list != NULL)
-		CORBA_free (cc_list);
-	if (bcc_list != NULL)
-		CORBA_free (bcc_list);
-
-	if (from != NULL)
-		CORBA_free (from);
-	if (subject != NULL)
-		CORBA_free (subject);
-	if (body != NULL)
-		CORBA_free (body);
-	if (content_type != NULL)
-		CORBA_free (content_type);
-	if (filename != NULL)
-		CORBA_free (filename);
-	if (description != NULL)
-		CORBA_free (description);
-	if (attach_data != NULL) {
-		CORBA_free (attach_data->_buffer);
-		CORBA_free (attach_data);
-	}
+	g_free (from);
+	g_free (content_type);
+	g_free (subject);
 	g_free (ical_string);
 
 	return retval;
 }
 
 gboolean
-reply_to_calendar_comp (ECalComponentItipMethod method, ECalComponent *send_comp,
-		ECal *client, gboolean reply_all, icalcomponent *zones, GSList *attachments_list)
-{
-	GNOME_Evolution_Composer composer_server;
+reply_to_calendar_comp (ECalComponentItipMethod method,
+                        ECalComponent *send_comp,
+                        ECal *client,
+                        gboolean reply_all,
+                        icalcomponent *zones,
+                        GSList *attachments_list)
+{
+	EMsgComposer *composer;
+	EComposerHeaderTable *table;
+	EDestination **destinations;
 	ECalComponent *comp = NULL;
 	icalcomponent *top_level = NULL;
 	GList *users = NULL;
-	GNOME_Evolution_Composer_RecipientList *to_list = NULL;
-	GNOME_Evolution_Composer_RecipientList *cc_list = NULL;
-	GNOME_Evolution_Composer_RecipientList *bcc_list = NULL;
-	CORBA_char *subject = NULL, *content_type = NULL;
-	char tmp [256];
-	CORBA_char *from = NULL;
+	gchar *from;
+	gchar *subject;
 	char *ical_string = NULL;
-	CORBA_Environment ev;
 	gboolean retval = FALSE;
 
-	CORBA_exception_init (&ev);
-
 	/* Tidy up the comp */
 	comp = comp_compliant (method, send_comp, client, zones);
 	if (comp == NULL)
 		goto cleanup;
 
 	/* Recipients */
-	to_list = comp_to_list (method, comp, users, reply_all);
-
-	cc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	cc_list->_maximum = cc_list->_length = 0;
-	bcc_list = GNOME_Evolution_Composer_RecipientList__alloc ();
-	bcc_list->_maximum = bcc_list->_length = 0;
+	destinations = comp_to_list (method, comp, users, reply_all);
 
 	/* Subject information */
 	subject = comp_subject (method, comp);
@@ -1433,26 +1315,15 @@
 	/* From address */
 	from = comp_from (method, comp);
 
-	/* Obtain an object reference for the Composer. */
-	composer_server = bonobo_activation_activate_from_id (GNOME_EVOLUTION_COMPOSER_OAFIID, 0, NULL, &ev);
-	if (BONOBO_EX (&ev)) {
-		g_warning ("Could not activate composer: %s", bonobo_exception_get_text (&ev));
-		CORBA_exception_free (&ev);
-		return FALSE;
-	}
-
-	/* Set recipients, subject */
-	GNOME_Evolution_Composer_setHeaders (composer_server, from, to_list, cc_list, bcc_list, subject, &ev);
-	if (BONOBO_EX (&ev)) {
-		g_warning ("Unable to set composer headers while sending iTip message: %s",
-			   bonobo_exception_get_text (&ev));
-		goto cleanup;
-	}
+	composer = e_msg_composer_new ();
+	table = e_msg_composer_get_header_table (composer);
+	em_composer_utils_setup_default_callbacks (composer);
+
+	e_composer_header_table_set_subject (table, subject);
+	e_composer_header_table_set_account_name (table, from);
+	e_composer_header_table_set_destinations_to (table, destinations);
 
-
-	/* Content type */
-	sprintf (tmp, "text/plain");
-	content_type = CORBA_string_dup (tmp);
+	e_destination_freev (destinations);
 
 	top_level = comp_toplevel_with_zones (method, comp, client, zones);
 	ical_string = icalcomponent_as_ical_string (top_level);
@@ -1518,7 +1389,6 @@
 			time = g_strdup (ctime (&start));
 		}
 
-		e_cal_component_free_datetime (&dtstart);
 
 		body = g_string_new ("<br><br><hr><br><b>______ Original Appointment ______ </b><br><br><table>");
 
@@ -1550,25 +1420,15 @@
 		g_string_append (body, html_description);
 		g_free (html_description);
 
-		GNOME_Evolution_Composer_setBody (composer_server, body->str, "text/html", &ev);
+		e_msg_composer_set_body_text (composer, body->str, -1);
 		g_string_free (body, TRUE);
-
-                if (BONOBO_EX (&ev)) {
-                        g_warning ("Unable to set body text while sending iTip message");
-                        goto cleanup;
-                }
-
 	}
 
+	gtk_widget_show (GTK_WIDGET (composer));
 
-	GNOME_Evolution_Composer_show (composer_server, &ev);
-	if (BONOBO_EX (&ev))
-		g_warning ("Unable to show the composer while sending iTip message");
-	else
-		retval = TRUE;
+	retval = TRUE;
 
  cleanup:
-	CORBA_exception_free (&ev);
 
 	if (comp != NULL)
 		g_object_unref (comp);
@@ -1580,19 +1440,8 @@
 		g_list_free (users);
 	}
 
-	if (to_list != NULL)
-		CORBA_free (to_list);
-	if (cc_list != NULL)
-		CORBA_free (cc_list);
-	if (bcc_list != NULL)
-		CORBA_free (bcc_list);
-
-	if (from != NULL)
-		CORBA_free (from);
-	if (subject != NULL)
-		CORBA_free (subject);
-	if (content_type != NULL)
-		CORBA_free (content_type);
+	g_free (from);
+	g_free (subject);
 	g_free (ical_string);
 	return retval;
 }

Modified: trunk/composer/Makefile.am
==============================================================================
--- trunk/composer/Makefile.am	(original)
+++ trunk/composer/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -1,40 +1,9 @@
-## CORBA stuff
-
-IDLS =				\
-	Evolution-Composer.idl	\
-	Composer.idl
-
-IDL_GENERATED =			\
-	Composer.h		\
-	Composer-common.c	\
-	Composer-skels.c	\
-	Composer-stubs.c
-
-HTML_EDITOR_GENERATED =		\
-	Editor.h		\
-	Editor-common.c	\
-	Editor-skels.c	\
-	Editor-stubs.c
-
-$(IDL_GENERATED): $(IDLS)
-	$(ORBIT_IDL) -I $(srcdir) -I $(datadir)/idl $(IDL_INCLUDES) \
-		$(srcdir)/Composer.idl
-
-Editor-commmon.c: $(GTKHTML_DATADIR)/Editor.idl
-
-$(HTML_EDITOR_GENERATED): $(GTKHTML_DATADIR)/Editor.idl
-	$(ORBIT_IDL) -I $(srcdir) $(IDL_INCLUDES) -I $(GTKHTML_DATADIR)/gtkhtml $(GTKHTML_DATADIR)/Editor.idl
-
-##
-
 error_DATA = mail-composer.error
 errordir = $(privdatadir)/errors
 
 # provides error rule
 @EVO_PLUGIN_RULE@
 
-idl_DATA = $(IDLS)
-
 noinst_LTLIBRARIES = libcomposer.la
 
 INCLUDES =								\
@@ -58,31 +27,36 @@
 libcomposer_la_SOURCES = 			\
 	$(IDL_GENERATED)			\
 	$(HTML_EDITOR_GENERATED)		\
+	e-composer-actions.c			\
+	e-composer-actions.h			\
+	e-composer-autosave.c			\
+	e-composer-autosave.h			\
 	e-composer-common.h			\
 	e-composer-header.c			\
 	e-composer-header.h			\
+	e-composer-header-table.c		\
+	e-composer-header-table.h		\
 	e-composer-from-header.c		\
 	e-composer-from-header.h		\
 	e-composer-name-header.c		\
 	e-composer-name-header.h		\
 	e-composer-post-header.c		\
 	e-composer-post-header.h		\
+	e-composer-private.c			\
+	e-composer-private.h			\
 	e-composer-text-header.c		\
 	e-composer-text-header.h		\
-	e-msg-composer-hdrs.c			\
-	e-msg-composer-hdrs.h			\
-	e-msg-composer-select-file.c		\
-	e-msg-composer-select-file.h		\
 	e-msg-composer.c			\
 	e-msg-composer.h			\
-	evolution-composer.c			\
-	evolution-composer.h			\
-	listener.c				\
-	listener.h
+	gconf-bridge.c				\
+	gconf-bridge.h
+
+uidir = $(evolutionuidir)
+ui_DATA = evolution-composer.ui
 
 EXTRA_DIST =					\
+	$(ui_DATA)				\
 	mail-composer.error.xml			\
-	$(IDLS)					\
 	ChangeLog.pre-1-4
 
 BUILT_SOURCES = $(IDL_GENERATED) $(HTML_EDITOR_GENERATED) $(error_DATA)

Modified: trunk/composer/e-composer-common.h
==============================================================================
--- trunk/composer/e-composer-common.h	(original)
+++ trunk/composer/e-composer-common.h	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_COMPOSER_COMMON
 #define E_COMPOSER_COMMON
 

Modified: trunk/composer/e-composer-from-header.c
==============================================================================
--- trunk/composer/e-composer-from-header.c	(original)
+++ trunk/composer/e-composer-from-header.c	Wed Apr  2 19:37:22 2008
@@ -1,10 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-composer-from-header.h"
 
 /* Convenience macro */
 #define E_COMPOSER_FROM_HEADER_GET_COMBO_BOX(header) \
 	(E_ACCOUNT_COMBO_BOX (E_COMPOSER_HEADER (header)->input_widget))
 
+enum {
+	REFRESHED,
+	LAST_SIGNAL
+};
+
 static gpointer parent_class;
+static guint signal_ids[LAST_SIGNAL];
 
 static void
 composer_from_header_changed_cb (EAccountComboBox *combo_box,
@@ -14,9 +39,24 @@
 }
 
 static void
+composer_from_header_refreshed_cb (EAccountComboBox *combo_box,
+                                   EComposerFromHeader *header)
+{
+	g_signal_emit (header, signal_ids[REFRESHED], 0);
+}
+
+static void
 composer_from_header_class_init (EComposerFromHeaderClass *class)
 {
 	parent_class = g_type_class_peek_parent (class);
+
+	signal_ids[REFRESHED] = g_signal_new (
+		"refreshed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		0, NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
 }
 
 static void
@@ -28,8 +68,10 @@
 	g_signal_connect (
 		widget, "changed",
 		G_CALLBACK (composer_from_header_changed_cb), header);
+	g_signal_connect (
+		widget, "refreshed",
+		G_CALLBACK (composer_from_header_refreshed_cb), header);
 	E_COMPOSER_HEADER (header)->input_widget = widget;
-	gtk_widget_show (widget);
 }
 
 GType
@@ -67,6 +109,17 @@
 		"button", FALSE, NULL);
 }
 
+EAccountList *
+e_composer_from_header_get_account_list (EComposerFromHeader *header)
+{
+	EAccountComboBox *combo_box;
+
+	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
+
+	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
+	return e_account_combo_box_get_account_list (combo_box);
+}
+
 void
 e_composer_from_header_set_account_list (EComposerFromHeader *header,
                                          EAccountList *account_list)
@@ -124,22 +177,3 @@
 	combo_box = E_COMPOSER_FROM_HEADER_GET_COMBO_BOX (header);
 	return e_account_combo_box_set_active_name (combo_box, account_name);
 }
-
-CamelInternetAddress *
-e_composer_from_header_get_active_address (EComposerFromHeader *header)
-{
-	CamelInternetAddress *address;
-	EAccount *account;
-
-	g_return_val_if_fail (E_IS_COMPOSER_FROM_HEADER (header), NULL);
-
-	account = e_composer_from_header_get_active (header);
-	if (account == NULL)
-		return NULL;
-
-	address = camel_internet_address_new ();
-	camel_internet_address_add (
-		address, account->id->name, account->id->address);
-
-	return address;
-}

Modified: trunk/composer/e-composer-from-header.h
==============================================================================
--- trunk/composer/e-composer-from-header.h	(original)
+++ trunk/composer/e-composer-from-header.h	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_COMPOSER_FROM_HEADER_H
 #define E_COMPOSER_FROM_HEADER_H
 
@@ -5,7 +24,6 @@
 
 #include <libedataserver/e-account.h>
 #include <libedataserver/e-account-list.h>
-#include <camel/camel-internet-address.h>
 
 #include "e-account-combo-box.h"
 #include "e-composer-header.h"
@@ -44,6 +62,8 @@
 
 GType		e_composer_from_header_get_type	(void);
 EComposerHeader * e_composer_from_header_new	(const gchar *label);
+EAccountList *	e_composer_from_header_get_account_list
+						(EComposerFromHeader *header);
 void		e_composer_from_header_set_account_list
 						(EComposerFromHeader *header,
 						 EAccountList *account_list);
@@ -57,8 +77,6 @@
 gboolean	e_composer_from_header_set_active_name
 						(EComposerFromHeader *header,
 						 const gchar *account_name);
-CamelInternetAddress * e_composer_from_header_get_active_address
-						(EComposerFromHeader *header);
 
 G_END_DECLS
 

Modified: trunk/composer/e-composer-header.c
==============================================================================
--- trunk/composer/e-composer-header.c	(original)
+++ trunk/composer/e-composer-header.c	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-composer-header.h"
 
 #define E_COMPOSER_HEADER_GET_PRIVATE(obj) \
@@ -8,6 +27,7 @@
 	PROP_0,
 	PROP_BUTTON,
 	PROP_LABEL,
+	PROP_SENSITIVE,
 	PROP_VISIBLE
 };
 
@@ -57,12 +77,8 @@
 			header);
 	} else {
 		widget = gtk_label_new_with_mnemonic (header->priv->label);
-
-		/* The subclass may not have initialized 'input_widget' yet,
-		 * in which case the subclass will have to do this. */
-		if (header->input_widget != NULL)
-			gtk_label_set_mnemonic_widget (
-				GTK_LABEL (widget), header->input_widget);
+		gtk_label_set_mnemonic_widget (
+			GTK_LABEL (widget), header->input_widget);
 	}
 	header->title_widget = g_object_ref_sink (widget);
 
@@ -91,6 +107,12 @@
 			priv->label = g_value_dup_string (value);
 			return;
 
+		case PROP_SENSITIVE:
+			e_composer_header_set_sensitive (
+				E_COMPOSER_HEADER (object),
+				g_value_get_boolean (value));
+			return;
+
 		case PROP_VISIBLE:
 			e_composer_header_set_visible (
 				E_COMPOSER_HEADER (object),
@@ -122,6 +144,12 @@
 				E_COMPOSER_HEADER (object)));
 			return;
 
+		case PROP_SENSITIVE:
+			g_value_set_boolean (
+				value, e_composer_header_get_sensitive (
+				E_COMPOSER_HEADER (object)));
+			return;
+
 		case PROP_VISIBLE:
 			g_value_set_boolean (
 				value, e_composer_header_get_visible (
@@ -189,6 +217,16 @@
 
 	g_object_class_install_property (
 		object_class,
+		PROP_SENSITIVE,
+		g_param_spec_boolean (
+			"sensitive",
+			NULL,
+			NULL,
+			FALSE,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
 		PROP_VISIBLE,
 		g_param_spec_boolean (
 			"visible",
@@ -261,6 +299,32 @@
 }
 
 gboolean
+e_composer_header_get_sensitive (EComposerHeader *header)
+{
+	gboolean sensitive;
+
+	g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE);
+
+	sensitive = GTK_WIDGET_SENSITIVE (header->title_widget);
+	if (GTK_WIDGET_SENSITIVE (header->input_widget) != sensitive)
+		g_warning ("%s: Sensitivity is out of sync", G_STRFUNC);
+
+	return sensitive;
+}
+
+void
+e_composer_header_set_sensitive (EComposerHeader *header,
+                                 gboolean sensitive)
+{
+	g_return_if_fail (E_IS_COMPOSER_HEADER (header));
+
+	gtk_widget_set_sensitive (header->title_widget, sensitive);
+	gtk_widget_set_sensitive (header->input_widget, sensitive);
+
+	g_object_notify (G_OBJECT (header), "sensitive");
+}
+
+gboolean
 e_composer_header_get_visible (EComposerHeader *header)
 {
 	gboolean visible;

Modified: trunk/composer/e-composer-header.h
==============================================================================
--- trunk/composer/e-composer-header.h	(original)
+++ trunk/composer/e-composer-header.h	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_COMPOSER_HEADER_H
 #define E_COMPOSER_HEADER_H
 
@@ -41,6 +60,9 @@
 
 GType		e_composer_header_get_type	(void);
 gchar *		e_composer_header_get_label	(EComposerHeader *header);
+gboolean	e_composer_header_get_sensitive	(EComposerHeader *header);
+void		e_composer_header_set_sensitive (EComposerHeader *header,
+						 gboolean sensitive);
 gboolean	e_composer_header_get_visible	(EComposerHeader *header);
 void		e_composer_header_set_visible	(EComposerHeader *header,
 						 gboolean visible);

Modified: trunk/composer/e-composer-name-header.c
==============================================================================
--- trunk/composer/e-composer-name-header.c	(original)
+++ trunk/composer/e-composer-name-header.c	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-composer-name-header.h"
 
 #include <glib/gi18n.h>
@@ -271,7 +290,7 @@
 
 	g_list_free (list);
 
-	return destinations;
+	return destinations;  /* free with e_destination_freev() */
 }
 
 void

Modified: trunk/composer/e-composer-name-header.h
==============================================================================
--- trunk/composer/e-composer-name-header.h	(original)
+++ trunk/composer/e-composer-name-header.h	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_COMPOSER_NAME_HEADER_H
 #define E_COMPOSER_NAME_HEADER_H
 

Modified: trunk/composer/e-composer-post-header.c
==============================================================================
--- trunk/composer/e-composer-post-header.c	(original)
+++ trunk/composer/e-composer-post-header.c	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-composer-post-header.h"
 
 #include <string.h>

Modified: trunk/composer/e-composer-post-header.h
==============================================================================
--- trunk/composer/e-composer-post-header.h	(original)
+++ trunk/composer/e-composer-post-header.h	Wed Apr  2 19:37:22 2008
@@ -1,8 +1,25 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_COMPOSER_POST_HEADER_H
 #define E_COMPOSER_POST_HEADER_H
 
-#include "e-composer-common.h"
-
 #include <libedataserver/e-account.h>
 
 #include "e-composer-text-header.h"

Added: trunk/composer/e-composer-private.c
==============================================================================
--- (empty file)
+++ trunk/composer/e-composer-private.c	Wed Apr  2 19:37:22 2008
@@ -0,0 +1,290 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "e-composer-private.h"
+
+static void
+composer_setup_charset_menu (EMsgComposer *composer)
+{
+	GtkUIManager *manager;
+	const gchar *path;
+	GList *list;
+	guint merge_id;
+
+	manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (composer));
+	list = gtk_action_group_list_actions (composer->priv->charset_actions);
+	path = "/main-menu/edit-menu/pre-spell-check/charset-menu";
+	merge_id = gtk_ui_manager_new_merge_id (manager);
+
+	while (list != NULL) {
+		GtkAction *action = list->data;
+
+		gtk_ui_manager_add_ui (
+			manager, merge_id, path,
+			gtk_action_get_name (action),
+			gtk_action_get_name (action),
+			GTK_UI_MANAGER_AUTO, FALSE);
+
+		list = g_list_delete_link (list, list);
+	}
+}
+
+void
+e_composer_private_init (EMsgComposer *composer)
+{
+	EMsgComposerPrivate *priv = composer->priv;
+
+	GtkhtmlEditor *editor;
+	GtkUIManager *manager;
+	GtkWidget *widget;
+	GtkWidget *expander;
+	GtkWidget *container;
+	gchar *filename;
+	GError *error = NULL;
+
+	editor = GTKHTML_EDITOR (composer);
+	manager = gtkhtml_editor_get_ui_manager (editor);
+
+	priv->charset_actions = gtk_action_group_new ("charset");
+	priv->composer_actions = gtk_action_group_new ("composer");
+
+	priv->extra_hdr_names = g_ptr_array_new ();
+	priv->extra_hdr_values = g_ptr_array_new ();
+
+	priv->gconf_bridge_binding_ids = g_array_new (
+		FALSE, FALSE, sizeof (guint));
+
+	priv->inline_images = g_hash_table_new_full (
+		g_str_hash, g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) NULL);
+
+	priv->inline_images_by_url = g_hash_table_new_full (
+		g_str_hash, g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) camel_object_unref);
+
+	priv->charset = e_composer_get_default_charset ();
+
+	e_composer_actions_init (composer);
+
+	filename = e_composer_find_data_file ("evolution-composer.ui");
+	gtk_ui_manager_add_ui_from_file (manager, filename, &error);
+	composer_setup_charset_menu (composer);
+	gtk_ui_manager_ensure_update (manager);
+	g_free (filename);
+
+	if (error != NULL) {
+		/* Henceforth, bad things start happening. */
+		g_critical ("%s", error->message);
+		g_clear_error (&error);
+	}
+
+	/* Construct the header table. */
+
+	widget = e_composer_header_table_new ();
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+	gtk_box_pack_start (GTK_BOX (editor->vbox), widget, FALSE, FALSE, 0);
+	gtk_box_reorder_child (GTK_BOX (editor->vbox), widget, 2);
+	priv->header_table = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	/* Construct attachment widgets.
+	 * XXX Move this stuff into a new custom widget. */
+
+	widget = gtk_expander_new (NULL);
+	gtk_expander_set_expanded (GTK_EXPANDER (widget), FALSE);
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+	gtk_box_pack_start (GTK_BOX (editor->vbox), widget, FALSE, FALSE, 0);
+	priv->attachment_expander = g_object_ref (widget);
+	gtk_widget_show (widget);
+	expander = widget;
+
+	widget = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (
+		GTK_SCROLLED_WINDOW (widget),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (
+		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+	gtk_container_add (GTK_CONTAINER (expander), widget);
+	priv->attachment_scrolled_window = g_object_ref (widget);
+	gtk_widget_show (widget);
+	container = widget;
+
+	widget = e_attachment_bar_new (NULL);
+	GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	priv->attachment_bar = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_hbox_new (FALSE, 0);
+	gtk_expander_set_label_widget (GTK_EXPANDER (expander), widget);
+	gtk_widget_show (widget);
+	container = widget;
+
+	widget = gtk_label_new_with_mnemonic (_("Show _Attachment Bar"));
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 6);
+	priv->attachment_expander_label = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_image_new_from_icon_name (
+		"mail-attachment", GTK_ICON_SIZE_MENU);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_widget_set_size_request (widget, 100, -1);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	priv->attachment_expander_icon = g_object_ref (widget);
+	gtk_widget_hide (widget);
+
+	widget = gtk_label_new (NULL);
+	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 6);
+	priv->attachment_expander_num = g_object_ref (widget);
+	gtk_widget_show (widget);
+}
+
+void
+e_composer_private_dispose (EMsgComposer *composer)
+{
+	GConfBridge *bridge;
+	GArray *array;
+	guint binding_id;
+
+	bridge = gconf_bridge_get ();
+	array = composer->priv->gconf_bridge_binding_ids;
+
+	while (array->len > 0) {
+		binding_id = g_array_index (array, guint, 0);
+		gconf_bridge_unbind (bridge, binding_id);
+		g_array_remove_index_fast (array, 0);
+	}
+
+	if (composer->priv->header_table != NULL) {
+		g_object_unref (composer->priv->header_table);
+		composer->priv->header_table = NULL;
+	}
+
+	if (composer->priv->charset_actions != NULL) {
+		g_object_unref (composer->priv->charset_actions);
+		composer->priv->charset_actions = NULL;
+	}
+
+	if (composer->priv->composer_actions != NULL) {
+		g_object_unref (composer->priv->composer_actions);
+		composer->priv->composer_actions = NULL;
+	}
+
+	g_hash_table_remove_all (composer->priv->inline_images);
+	g_hash_table_remove_all (composer->priv->inline_images_by_url);
+
+	if (composer->priv->redirect != NULL) {
+		camel_object_unref (composer->priv->redirect);
+		composer->priv->redirect = NULL;
+	}
+}
+
+void
+e_composer_private_finalize (EMsgComposer *composer)
+{
+	GPtrArray *array;
+
+	array = composer->priv->extra_hdr_names;
+	g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+	g_ptr_array_free (array, TRUE);
+
+	array = composer->priv->extra_hdr_values;
+	g_ptr_array_foreach (array, (GFunc) g_free, NULL);
+	g_ptr_array_free (array, TRUE);
+
+	g_free (composer->priv->charset);
+	g_free (composer->priv->mime_type);
+	g_free (composer->priv->mime_body);
+
+	g_hash_table_destroy (composer->priv->inline_images);
+	g_hash_table_destroy (composer->priv->inline_images_by_url);
+}
+
+gchar *
+e_composer_find_data_file (const gchar *basename)
+{
+	gchar *filename;
+
+	g_return_val_if_fail (basename != NULL, NULL);
+
+	/* Support running directly from the source tree. */
+	filename = g_build_filename (".", basename, NULL);
+	if (g_file_test (filename, G_FILE_TEST_EXISTS))
+		return filename;
+	g_free (filename);
+
+	/* XXX This is kinda broken. */
+	filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL);
+	if (g_file_test (filename, G_FILE_TEST_EXISTS))
+		return filename;
+	g_free (filename);
+
+	g_critical ("Could not locate '%s'", basename);
+
+	return NULL;
+}
+
+gchar *
+e_composer_get_default_charset (void)
+{
+	GConfClient *client;
+	gchar *charset;
+	GError *error = NULL;
+
+	client = gconf_client_get_default ();
+
+	charset = gconf_client_get_string (
+		client, COMPOSER_GCONF_CHARSET_KEY, &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
+	}
+
+	/* See what charset the mailer is using.
+	 * XXX We should not have to know where this lives in GConf.
+	 *     Need a mail_config_get_default_charset() that does this. */
+	if (!charset || charset[0] == '\0') {
+		g_free (charset);
+		charset = gconf_client_get_string (
+			client, MAIL_GCONF_CHARSET_KEY, NULL);
+		if (charset != NULL && *charset == '\0') {
+			g_free (charset);
+			charset = NULL;
+		} else if (error != NULL) {
+			g_warning ("%s", error->message);
+			g_clear_error (&error);
+		}
+	}
+
+	g_object_unref (client);
+
+	if (charset == NULL)
+		charset = g_strdup (e_iconv_locale_charset ());
+
+	if (charset == NULL)
+		charset = g_strdup ("us-ascii");
+
+	return charset;
+}
+

Modified: trunk/composer/e-composer-text-header.c
==============================================================================
--- trunk/composer/e-composer-text-header.c	(original)
+++ trunk/composer/e-composer-text-header.c	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-composer-text-header.h"
 
 /* Convenience macro */

Modified: trunk/composer/e-composer-text-header.h
==============================================================================
--- trunk/composer/e-composer-text-header.h	(original)
+++ trunk/composer/e-composer-text-header.h	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_COMPOSER_TEXT_HEADER_H
 #define E_COMPOSER_TEXT_HEADER_H
 

Modified: trunk/composer/e-msg-composer.c
==============================================================================
--- trunk/composer/e-msg-composer.c	(original)
+++ trunk/composer/e-msg-composer.c	Wed Apr  2 19:37:22 2008
@@ -30,7 +30,7 @@
 
    TODO
 
-   - Somehow users should be able to see if any file(s) are attached even when
+   - Somehow users should be able to see if any file (s) are attached even when
      the attachment bar is not shown.
 
    Should use EventSources to keep track of global changes made to configuration
@@ -43,45 +43,30 @@
 
 #define SMIME_SUPPORTED 1
 
-#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <unistd.h>
-#include <errno.h>
-#include <ctype.h>
 
 #include <glib.h>
-#include <glib/gstdio.h>
 
 #include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
 
 #include <gconf/gconf.h>
 #include <gconf/gconf-client.h>
 
-#include <libgnome/gnome-exec.h>
-#include <libgnome/gnome-help.h>
 #include <libgnome/gnome-url.h>
-#include <glib/gi18n.h>
-#include <libgnomeui/gnome-uidefs.h>
-#include <libgnomeui/gnome-window-icon.h>
-
-#include <bonobo/bonobo-exception.h>
-#include <bonobo/bonobo-moniker-util.h>
-#include <bonobo/bonobo-stream-memory.h>
-#include <bonobo/bonobo-ui-util.h>
-#include <bonobo/bonobo-widget.h>
-
 #include <libgnomevfs/gnome-vfs.h>
 
 #include <glade/glade.h>
 
-#include <libedataserver/e-iconv.h>
-
 #include "e-util/e-dialog-utils.h"
-#include "e-util/e-signature-list.h"
 #include "misc/e-charset-picker.h"
 #include "misc/e-expander.h"
 #include "e-util/e-error.h"
@@ -119,113 +104,53 @@
 #include "e-msg-composer.h"
 #include "e-attachment.h"
 #include "e-attachment-bar.h"
-#include "e-msg-composer-hdrs.h"
-#include "e-msg-composer-select-file.h"
+#include "e-composer-autosave.h"
+#include "e-composer-private.h"
+#include "e-composer-header-table.h"
 
 #include "evolution-shell-component-utils.h"
 #include <e-util/e-icon-factory.h>
 
-#include "Editor.h"
-#include "listener.h"
-
 #ifdef HAVE_XFREE
 #include <X11/XF86keysym.h>
 #endif
 
-#define GNOME_GTKHTML_EDITOR_CONTROL_ID "OAFIID:GNOME_GtkHTML_Editor:" GTKHTML_API_VERSION
-
-#define COMPOSER_CURRENT_FOLDER_KEY "/apps/evolution/mail/composer/current_folder"
-
 #define d(x)
 
-typedef struct _EMsgComposerPrivate EMsgComposerPrivate;
-
-struct _EMsgComposer {
-	BonoboWindow parent;
-
-	EMsgComposerPrivate *priv;
-};
-
-struct _EMsgComposerClass {
-	BonoboWindowClass parent_class;
-
-	void (* send) (EMsgComposer *composer);
-	void (* save_draft) (EMsgComposer *composer, int quit);
-};
-
-
-struct _EMsgComposerPrivate {
-
-
-/* Main UIComponent */
-	BonoboUIComponent *uic;
-
-	/* UIComponent for the non-control GtkEntries */
-	BonoboUIComponent *entry_uic;
-
-	GtkWidget *hdrs;
-	GPtrArray *extra_hdr_names, *extra_hdr_values;
-
-	GtkWidget *focused_entry;
-
-	GtkWidget *eeditor;
-
-	GtkWidget *attachment_bar;
-	GtkWidget *attachment_scrolled_window;
-	GtkWidget *attachment_expander;
-	GtkWidget *attachment_expander_label;
-	GtkWidget *attachment_expander_icon;
-	GtkWidget *attachment_expander_num;
-
-	GtkWidget *address_dialog;
-
-	Bonobo_PersistFile       persist_file_interface;
-	Bonobo_PersistStream     persist_stream_interface;
-	GNOME_GtkHTML_Editor_Engine  eeditor_engine;
-	BonoboObject            *eeditor_listener;
-	GHashTable              *inline_images, *inline_images_by_url;
-	GList                   *current_images;
-
-	char *mime_type, *mime_body, *charset;
-
-	char *autosave_file;
-	int   autosave_fd;
-	guint32 enable_autosave        : 1;
-
-	guint32 attachment_bar_visible : 1;
-	guint32 send_html              : 1;
-	guint32 is_alternative         : 1;
-	guint32 pgp_sign               : 1;
-	guint32 pgp_encrypt            : 1;
-	guint32 smime_sign             : 1;
-	guint32 smime_encrypt          : 1;
-	guint32 view_from              : 1;
-	guint32 view_replyto           : 1;
-	guint32 view_to                : 1;
-	guint32 view_postto            : 1;
-	guint32 view_bcc               : 1;
-	guint32 view_cc                : 1;
-	guint32 view_subject           : 1;
-	guint32 request_receipt        : 1;
-	guint32 set_priority	       : 1;
-	guint32 has_changed            : 1;
-	guint32 autosaved              : 1;
-
-	guint32 mode_post              : 1;
-
-	guint32 in_signature_insert    : 1;
-
-	CamelMimeMessage *redirect;
-
-	guint notify_id;
-
-	gboolean send_invoked;
-	EMMenu *menu;
-
-	GtkWidget *saveas;	/* saveas async file requester */
-	GtkWidget *load;	/* same for load - not used */
-
-};
+#define E_MSG_COMPOSER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MSG_COMPOSER, EMsgComposerPrivate))
+
+#define E_MSG_COMPOSER_VISIBLE_MASK_SENDER \
+	(E_MSG_COMPOSER_VISIBLE_FROM | \
+	 E_MSG_COMPOSER_VISIBLE_REPLYTO)
+
+#define E_MSG_COMPOSER_VISIBLE_MASK_BASIC \
+	(E_MSG_COMPOSER_VISIBLE_MASK_SENDER | \
+	 E_MSG_COMPOSER_VISIBLE_SUBJECT)
+
+#define E_MSG_COMPOSER_VISIBLE_MASK_RECIPIENTS \
+	(E_MSG_COMPOSER_VISIBLE_TO | \
+	 E_MSG_COMPOSER_VISIBLE_CC | \
+	 E_MSG_COMPOSER_VISIBLE_BCC)
+
+#define E_MSG_COMPOSER_VISIBLE_MASK_MAIL \
+	(E_MSG_COMPOSER_VISIBLE_MASK_BASIC | \
+	 E_MSG_COMPOSER_VISIBLE_MASK_RECIPIENTS)
+
+#define E_MSG_COMPOSER_VISIBLE_MASK_POST \
+	(E_MSG_COMPOSER_VISIBLE_MASK_BASIC | \
+	 E_MSG_COMPOSER_VISIBLE_POSTTO)
+
+typedef enum {
+	E_MSG_COMPOSER_VISIBLE_FROM       = (1 << 0),
+	E_MSG_COMPOSER_VISIBLE_REPLYTO    = (1 << 1),
+	E_MSG_COMPOSER_VISIBLE_TO         = (1 << 2),
+	E_MSG_COMPOSER_VISIBLE_CC         = (1 << 3),
+	E_MSG_COMPOSER_VISIBLE_BCC        = (1 << 4),
+	E_MSG_COMPOSER_VISIBLE_POSTTO     = (1 << 5),
+	E_MSG_COMPOSER_VISIBLE_SUBJECT    = (1 << 7)
+} EMsgComposerHeaderVisibleFlags;
 
 enum {
 	SEND,
@@ -233,77 +158,66 @@
 	LAST_SIGNAL
 };
 
-static guint signals[LAST_SIGNAL] = { 0 };
-
 enum {
 	DND_TYPE_MESSAGE_RFC822,
 	DND_TYPE_X_UID_LIST,
 	DND_TYPE_TEXT_URI_LIST,
 	DND_TYPE_NETSCAPE_URL,
 	DND_TYPE_TEXT_VCARD,
-	DND_TYPE_TEXT_CALENDAR,
+	DND_TYPE_TEXT_CALENDAR
 };
 
 static GtkTargetEntry drop_types[] = {
 	{ "message/rfc822", 0, DND_TYPE_MESSAGE_RFC822 },
-	{ "x-uid-list", 0, DND_TYPE_X_UID_LIST },
-	{ "text/uri-list", 0, DND_TYPE_TEXT_URI_LIST },
-	{ "_NETSCAPE_URL", 0, DND_TYPE_NETSCAPE_URL },
-	{ "text/x-vcard", 0, DND_TYPE_TEXT_VCARD },
-	{ "text/calendar", 0, DND_TYPE_TEXT_CALENDAR },
+	{ "x-uid-list",     0, DND_TYPE_X_UID_LIST },
+	{ "text/uri-list",  0, DND_TYPE_TEXT_URI_LIST },
+	{ "_NETSCAPE_URL",  0, DND_TYPE_NETSCAPE_URL },
+	{ "text/x-vcard",   0, DND_TYPE_TEXT_VCARD },
+	{ "text/calendar",  0, DND_TYPE_TEXT_CALENDAR }
 };
 
-#define num_drop_types (sizeof (drop_types) / sizeof (drop_types[0]))
-
 static struct {
-	char *target;
+	gchar *target;
 	GdkAtom atom;
 	guint32 actions;
 } drag_info[] = {
 	{ "message/rfc822", NULL, GDK_ACTION_COPY },
-	{ "x-uid-list", NULL, GDK_ACTION_ASK|GDK_ACTION_MOVE|GDK_ACTION_COPY },
-	{ "text/uri-list", NULL, GDK_ACTION_COPY },
-	{ "_NETSCAPE_URL", NULL, GDK_ACTION_COPY },
-	{ "text/x-vcard", NULL, GDK_ACTION_COPY },
-	{ "text/calendar", NULL, GDK_ACTION_COPY },
+	{ "x-uid-list",     NULL, GDK_ACTION_ASK |
+                                  GDK_ACTION_MOVE |
+                                  GDK_ACTION_COPY },
+	{ "text/uri-list",  NULL, GDK_ACTION_COPY },
+	{ "_NETSCAPE_URL",  NULL, GDK_ACTION_COPY },
+	{ "text/x-vcard",   NULL, GDK_ACTION_COPY },
+	{ "text/calendar",  NULL, GDK_ACTION_COPY }
 };
 
-static const char *emc_draft_format_names[] = { "pgp-sign", "pgp-encrypt", "smime-sign", "smime-encrypt" };
-
-
-/* The parent class.  */
-static BonoboWindowClass *parent_class = NULL;
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
 
 /* All the composer windows open, for bookkeeping purposes.  */
 static GSList *all_composers = NULL;
 
-
 /* local prototypes */
-static GList *add_recipients (GList *list, const char *recips);
+static GList *add_recipients (GList *list, const gchar *recips);
 
-static void handle_mailto (EMsgComposer *composer, const char *mailto);
-static void handle_uri    (EMsgComposer *composer, const char *uri, gboolean html_dnd);
+static void handle_mailto (EMsgComposer *composer, const gchar *mailto);
+static void handle_uri    (EMsgComposer *composer, const gchar *uri, gboolean html_dnd);
 
-/* used by e_msg_composer_add_message_attachments() */
+/* used by e_msg_composer_add_message_attachments () */
 static void add_attachments_from_multipart (EMsgComposer *composer, CamelMultipart *multipart,
-					    gboolean just_inlines, int depth);
+					    gboolean just_inlines, gint depth);
+
+/* used by e_msg_composer_new_with_message () */
+static void handle_multipart (EMsgComposer *composer, CamelMultipart *multipart, gint depth);
+static void handle_multipart_alternative (EMsgComposer *composer, CamelMultipart *multipart, gint depth);
+static void handle_multipart_encrypted (EMsgComposer *composer, CamelMimePart *multipart, gint depth);
+static void handle_multipart_signed (EMsgComposer *composer, CamelMultipart *multipart, gint depth);
 
-/* used by e_msg_composer_new_with_message() */
-static void handle_multipart (EMsgComposer *composer, CamelMultipart *multipart, int depth);
-static void handle_multipart_alternative (EMsgComposer *composer, CamelMultipart *multipart, int depth);
-static void handle_multipart_encrypted (EMsgComposer *composer, CamelMimePart *multipart, int depth);
-static void handle_multipart_signed (EMsgComposer *composer, CamelMultipart *multipart, int depth);
-
-static void set_editor_signature (EMsgComposer *composer);
-
-/* used by e_msg_composer for showing the help menu item */
-static void e_msg_composer_show_help (EMsgComposer *composer);
-
 static EDestination**
-destination_list_to_vector_sized (GList *list, int n)
+destination_list_to_vector_sized (GList *list, gint n)
 {
 	EDestination **destv;
-	int i = 0;
+	gint i = 0;
 
 	if (n == -1)
 		n = g_list_length (list);
@@ -329,43 +243,14 @@
 	return destination_list_to_vector_sized (list, -1);
 }
 
-static GByteArray *
-get_text (Bonobo_PersistStream persist, char *format)
-{
-	BonoboStream *stream;
-	BonoboStreamMem *stream_mem;
-	CORBA_Environment ev;
-	GByteArray *text;
-
-	CORBA_exception_init (&ev);
-
-	stream = bonobo_stream_mem_create (NULL, 0, FALSE, TRUE);
-	Bonobo_PersistStream_save (persist, (Bonobo_Stream)bonobo_object_corba_objref (BONOBO_OBJECT (stream)),
-				   format, &ev);
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		g_warning ("Exception getting mail '%s'",
-			   bonobo_exception_get_text (&ev));
-		return NULL;
-	}
-
-	CORBA_exception_free (&ev);
-
-	stream_mem = BONOBO_STREAM_MEM (stream);
-	text = g_byte_array_new ();
-	g_byte_array_append (text, (const guint8 *)stream_mem->buffer, stream_mem->pos);
-	bonobo_object_unref (BONOBO_OBJECT (stream));
-
-	return text;
-}
-
 #define LINE_LEN 72
 
 static CamelTransferEncoding
-best_encoding (GByteArray *buf, const char *charset)
+best_encoding (GByteArray *buf, const gchar *charset)
 {
-	char *in, *out, outbuf[256], *ch;
-	size_t inlen, outlen;
-	int status, count = 0;
+	gchar *in, *out, outbuf[256], *ch;
+	gsize inlen, outlen;
+	gint status, count = 0;
 	iconv_t cd;
 
 	if (!charset)
@@ -375,20 +260,20 @@
 	if (cd == (iconv_t) -1)
 		return -1;
 
-	in = (char*)buf->data;
+	in = (gchar *) buf->data;
 	inlen = buf->len;
 	do {
 		out = outbuf;
 		outlen = sizeof (outbuf);
-		status = e_iconv (cd, (const char **) &in, &inlen, &out, &outlen);
+		status = e_iconv (cd, (const gchar **) &in, &inlen, &out, &outlen);
 		for (ch = out - 1; ch >= outbuf; ch--) {
-			if ((unsigned char)*ch > 127)
+			if ((guchar) *ch > 127)
 				count++;
 		}
-	} while (status == (size_t) -1 && errno == E2BIG);
+	} while (status == (gsize) -1 && errno == E2BIG);
 	e_iconv_close (cd);
 
-	if (status == (size_t) -1 || status > 0)
+	if (status == (gsize) -1 || status > 0)
 		return -1;
 
 	if (count == 0)
@@ -399,37 +284,10 @@
 		return CAMEL_TRANSFER_ENCODING_BASE64;
 }
 
-static char *
-composer_get_default_charset_setting (void)
-{
-	GConfClient *gconf;
-	const char *locale;
-	char *charset;
-
-	gconf = gconf_client_get_default ();
-	charset = gconf_client_get_string (gconf, "/apps/evolution/mail/composer/charset", NULL);
-
-	if (!charset || charset[0] == '\0') {
-		g_free (charset);
-		charset = gconf_client_get_string (gconf, "/apps/evolution/mail/format/charset", NULL);
-		if (charset && charset[0] == '\0') {
-			g_free (charset);
-			charset = NULL;
-		}
-	}
-
-	g_object_unref (gconf);
-
-	if (!charset && (locale = e_iconv_locale_charset ()))
-		charset = g_strdup (locale);
-
-	return charset ? charset : g_strdup ("us-ascii");
-}
-
-static char *
-best_charset (GByteArray *buf, const char *default_charset, CamelTransferEncoding *encoding)
+static gchar *
+best_charset (GByteArray *buf, const gchar *default_charset, CamelTransferEncoding *encoding)
 {
-	char *charset;
+	gchar *charset;
 
 	/* First try US-ASCII */
 	*encoding = best_encoding (buf, "US-ASCII");
@@ -442,7 +300,7 @@
 		return g_strdup (default_charset);
 
 	/* Now try the user's default charset from the mail config */
-	charset = composer_get_default_charset_setting ();
+	charset = e_composer_get_default_charset ();
 	*encoding = best_encoding (buf, charset);
 	if (*encoding != -1)
 		return charset;
@@ -496,20 +354,191 @@
 	g_hash_table_destroy (added);
 }
 
-/* This functions builds a CamelMimeMessage for the message that the user has
+/* These functions builds a CamelMimeMessage for the message that the user has
  * composed in `composer'.
  */
+
+static void
+set_recipients_from_destv (CamelMimeMessage *msg,
+			   EDestination **to_destv,
+			   EDestination **cc_destv,
+			   EDestination **bcc_destv,
+			   gboolean redirect)
+{
+	CamelInternetAddress *to_addr;
+	CamelInternetAddress *cc_addr;
+	CamelInternetAddress *bcc_addr;
+	CamelInternetAddress *target;
+	const gchar *text_addr, *header;
+	gboolean seen_hidden_list = FALSE;
+	gint i;
+
+	to_addr  = camel_internet_address_new ();
+	cc_addr  = camel_internet_address_new ();
+	bcc_addr = camel_internet_address_new ();
+
+	for (i = 0; to_destv != NULL && to_destv[i] != NULL; ++i) {
+		text_addr = e_destination_get_address (to_destv[i]);
+
+		if (text_addr && *text_addr) {
+			target = to_addr;
+			if (e_destination_is_evolution_list (to_destv[i])
+			    && !e_destination_list_show_addresses (to_destv[i])) {
+				target = bcc_addr;
+				seen_hidden_list = TRUE;
+			}
+
+			camel_address_decode (CAMEL_ADDRESS (target), text_addr);
+		}
+	}
+
+	for (i = 0; cc_destv != NULL && cc_destv[i] != NULL; ++i) {
+		text_addr = e_destination_get_address (cc_destv[i]);
+		if (text_addr && *text_addr) {
+			target = cc_addr;
+			if (e_destination_is_evolution_list (cc_destv[i])
+			    && !e_destination_list_show_addresses (cc_destv[i])) {
+				target = bcc_addr;
+				seen_hidden_list = TRUE;
+			}
+
+			camel_address_decode (CAMEL_ADDRESS (target), text_addr);
+		}
+	}
+
+	for (i = 0; bcc_destv != NULL && bcc_destv[i] != NULL; ++i) {
+		text_addr = e_destination_get_address (bcc_destv[i]);
+		if (text_addr && *text_addr) {
+			camel_address_decode (CAMEL_ADDRESS (bcc_addr), text_addr);
+		}
+	}
+
+	header = redirect ? CAMEL_RECIPIENT_TYPE_RESENT_TO : CAMEL_RECIPIENT_TYPE_TO;
+	if (camel_address_length (CAMEL_ADDRESS (to_addr)) > 0) {
+		camel_mime_message_set_recipients (msg, header, to_addr);
+	} else if (seen_hidden_list) {
+		camel_medium_set_header (CAMEL_MEDIUM (msg), header, "Undisclosed-Recipient:;");
+	}
+
+	header = redirect ? CAMEL_RECIPIENT_TYPE_RESENT_CC : CAMEL_RECIPIENT_TYPE_CC;
+	if (camel_address_length (CAMEL_ADDRESS (cc_addr)) > 0) {
+		camel_mime_message_set_recipients (msg, header, cc_addr);
+	}
+
+	header = redirect ? CAMEL_RECIPIENT_TYPE_RESENT_BCC : CAMEL_RECIPIENT_TYPE_BCC;
+	if (camel_address_length (CAMEL_ADDRESS (bcc_addr)) > 0) {
+		camel_mime_message_set_recipients (msg, header, bcc_addr);
+	}
+
+	camel_object_unref (to_addr);
+	camel_object_unref (cc_addr);
+	camel_object_unref (bcc_addr);
+}
+
+static void
+build_message_headers (EMsgComposer *composer,
+                       CamelMimeMessage *msg,
+                       gboolean redirect)
+{
+	EComposerHeaderTable *table;
+	EAccount *account;
+	const gchar *subject;
+	const gchar *reply_to;
+
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg));
+
+	table = e_msg_composer_get_header_table (composer);
+
+	/* Subject: */
+	subject = e_composer_header_table_get_subject (table);
+	camel_mime_message_set_subject (msg, subject);
+
+	/* From: / Resent-From: */
+	account = e_composer_header_table_get_account (table);
+	if (account != NULL) {
+		CamelInternetAddress *addr;
+		const gchar *name = account->id->name;
+		const gchar *address = account->id->address;
+
+		addr = camel_internet_address_new ();
+		camel_internet_address_add (addr, name, address);
+
+		if (redirect) {
+			gchar *value;
+
+			value = camel_address_encode (CAMEL_ADDRESS (addr));
+			camel_medium_set_header (
+				CAMEL_MEDIUM (msg), "Resent-From", value);
+			g_free (value);
+		} else
+			camel_mime_message_set_from (msg, addr);
+
+		camel_object_unref (addr);
+	}
+
+	/* Reply-To: */
+	reply_to = e_composer_header_table_get_reply_to (table);
+	if (reply_to != NULL && *reply_to != '\0') {
+		CamelInternetAddress *addr;
+
+		addr = camel_internet_address_new ();
+
+		if (camel_address_unformat (CAMEL_ADDRESS (addr), reply_to) > 0)
+			camel_mime_message_set_reply_to (msg, addr);
+
+		camel_object_unref (addr);
+	}
+
+	/* To:, Cc:, Bcc: */
+	if (e_composer_header_table_get_header_visible (table, E_COMPOSER_HEADER_TO) ||
+	    e_composer_header_table_get_header_visible (table, E_COMPOSER_HEADER_CC) ||
+	    e_composer_header_table_get_header_visible (table, E_COMPOSER_HEADER_BCC)) {
+		EDestination **to, **cc, **bcc;
+
+		to = e_composer_header_table_get_destinations_to (table);
+		cc = e_composer_header_table_get_destinations_cc (table);
+		bcc = e_composer_header_table_get_destinations_bcc (table);
+
+		set_recipients_from_destv (msg, to, cc, bcc, redirect);
+
+		e_destination_freev (to);
+		e_destination_freev (cc);
+		e_destination_freev (bcc);
+	}
+
+	/* X-Evolution-PostTo: */
+	if (e_composer_header_table_get_header_visible (table, E_COMPOSER_HEADER_POST_TO)) {
+		CamelMedium *medium = CAMEL_MEDIUM (msg);
+		const gchar *name = "X-Evolution-PostTo";
+		GList *list, *iter;
+
+		camel_medium_remove_header (medium, name);
+
+		list = e_composer_header_table_get_post_to (table);
+		for (iter = list; iter != NULL; iter = iter->next) {
+			gchar *folder = iter->data;
+			camel_medium_add_header (medium, name, folder);
+			g_free (folder);
+		}
+		g_list_free (list);
+	}
+}
+
 static CamelMimeMessage *
-build_message (EMsgComposer *composer, gboolean save_html_object_data)
+build_message (EMsgComposer *composer,
+               gboolean html_content,
+               gboolean save_html_object_data)
 {
+	GtkhtmlEditor *editor;
 	EMsgComposerPrivate *p = composer->priv;
 
-	EAttachmentBar *attachment_bar =
-		E_ATTACHMENT_BAR (p->attachment_bar);
-	EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (p->hdrs);
+	EAttachmentBar *attachment_bar;
+	EComposerHeaderTable *table;
+	GtkToggleAction *action;
 	CamelDataWrapper *plain, *html, *current;
 	CamelTransferEncoding plain_encoding;
-	const char *iconv_charset = NULL;
+	const gchar *iconv_charset = NULL;
 	GPtrArray *recipients = NULL;
 	CamelMultipart *body = NULL;
 	CamelContentType *type;
@@ -519,23 +548,29 @@
 	CamelException ex;
 	GByteArray *data;
 	EAccount *account;
-	char *charset;
-	int i;
+	gchar *charset;
+	gboolean pgp_sign;
+	gboolean pgp_encrypt;
+	gboolean smime_sign;
+	gboolean smime_encrypt;
+	gint i;
 
-	account = e_msg_composer_hdrs_get_from_account (hdrs);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-	if (p->persist_stream_interface == CORBA_OBJECT_NIL)
-		return NULL;
+	editor = GTKHTML_EDITOR (composer);
+	table = e_msg_composer_get_header_table (composer);
+	account = e_composer_header_table_get_account (table);
+	attachment_bar = E_ATTACHMENT_BAR (p->attachment_bar);
 
 	/* evil kludgy hack for Redirect */
 	if (p->redirect) {
-		e_msg_composer_hdrs_to_redirect (hdrs, p->redirect);
+		build_message_headers (composer, p->redirect, TRUE);
 		camel_object_ref (p->redirect);
 		return p->redirect;
 	}
 
 	new = camel_mime_message_new ();
-	e_msg_composer_hdrs_to_message (hdrs, new);
+	build_message_headers (composer, new, FALSE);
 	for (i = 0; i < p->extra_hdr_names->len; i++) {
 		camel_medium_add_header (CAMEL_MEDIUM (new),
 					 p->extra_hdr_names->pdata[i],
@@ -543,22 +578,27 @@
 	}
 
 	/* Message Disposition Notification */
-	if (p->request_receipt) {
-		char *mdn_address = account->id->reply_to;
+	action = GTK_TOGGLE_ACTION (ACTION (REQUEST_READ_RECEIPT));
+	if (gtk_toggle_action_get_active (action)) {
+		gchar *mdn_address = account->id->reply_to;
 		if (!mdn_address || !*mdn_address)
 			mdn_address = account->id->address;
 
-		camel_medium_add_header (CAMEL_MEDIUM (new), "Disposition-Notification-To", mdn_address);
+		camel_medium_add_header (
+			CAMEL_MEDIUM (new),
+			"Disposition-Notification-To", mdn_address);
 	}
 
 	/* Message Priority */
-	if (p->set_priority)
-		camel_medium_add_header (CAMEL_MEDIUM (new), "X-Priority", "1");
+	action = GTK_TOGGLE_ACTION (ACTION (PRIORITIZE_MESSAGE));
+	if (gtk_toggle_action_get_active (action))
+		camel_medium_add_header (
+			CAMEL_MEDIUM (new), "X-Priority", "1");
 
 	if (p->mime_body) {
 		plain_encoding = CAMEL_TRANSFER_ENCODING_7BIT;
 		for (i = 0; p->mime_body[i]; i++) {
-			if ((unsigned char) p->mime_body[i] > 127) {
+			if ((guchar) p->mime_body[i] > 127) {
 				plain_encoding = CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE;
 				break;
 			}
@@ -567,12 +607,13 @@
 		g_byte_array_append (data, (const guint8 *)p->mime_body, strlen (p->mime_body));
 		type = camel_content_type_decode (p->mime_type);
 	} else {
-		data = get_text (p->persist_stream_interface, "text/plain");
-		if (!data) {
-			/* The component has probably died */
-			camel_object_unref (CAMEL_OBJECT (new));
-			return NULL;
-		}
+		gchar *text;
+		gsize length;
+
+		data = g_byte_array_new ();
+		text = gtkhtml_editor_get_text_plain (editor, &length);
+		g_byte_array_append (data, (guint8 *) text, (guint) length);
+		g_free (text);
 
 		/* FIXME: we may want to do better than this... */
 
@@ -608,26 +649,22 @@
 	camel_data_wrapper_set_mime_type_field (plain, type);
 	camel_content_type_unref (type);
 
-	if (p->send_html) {
-		CORBA_Environment ev;
+	if (html_content) {
+		gchar *text;
+		gsize length;
+
 		clear_current_images (composer);
 
-		if (save_html_object_data) {
-			CORBA_exception_init (&ev);
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "save-data-on", &ev);
-		}
-		data = get_text (p->persist_stream_interface, "text/html");
-		if (save_html_object_data) {
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "save-data-off", &ev);
-			CORBA_exception_free (&ev);
-		}
+		if (save_html_object_data)
+			gtkhtml_editor_run_command (editor, "save-data-on");
 
-		if (!data) {
-			/* The component has probably died */
-			camel_object_unref (new);
-			camel_object_unref (plain);
-			return NULL;
-		}
+		data = g_byte_array_new ();
+		text = gtkhtml_editor_get_text_html (editor, &length);
+		g_byte_array_append (data, (guint8 *) text, (guint) length);
+		g_free (text);
+
+		if (save_html_object_data)
+			gtkhtml_editor_run_command (editor, "save-data-off");
 
 		html = camel_data_wrapper_new ();
 
@@ -716,31 +753,45 @@
 
 	camel_exception_init (&ex);
 
-	/* Setup working recipient list if we're encrypting */
-	if (p->pgp_encrypt
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+	pgp_sign = gtk_toggle_action_get_active (action);
+
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT));
+	pgp_encrypt = gtk_toggle_action_get_active (action);
+
 #if defined (HAVE_NSS) && defined (SMIME_SUPPORTED)
-	    || p->smime_encrypt
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
+	smime_sign = gtk_toggle_action_get_active (action);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
+	smime_encrypt = gtk_toggle_action_get_active (action);
+#else
+	smime_sign = FALSE;
+	smime_encrypt = FALSE;
 #endif
-		) {
-		int j;
-		const char *types[] = { CAMEL_RECIPIENT_TYPE_TO, CAMEL_RECIPIENT_TYPE_CC, CAMEL_RECIPIENT_TYPE_BCC };
 
-		recipients = g_ptr_array_new();
-		for (i=0; i < sizeof(types)/sizeof(types[0]); i++) {
+	/* Setup working recipient list if we're encrypting */
+	if (pgp_encrypt || smime_encrypt) {
+		gint j;
+		const gchar *types[] = { CAMEL_RECIPIENT_TYPE_TO, CAMEL_RECIPIENT_TYPE_CC, CAMEL_RECIPIENT_TYPE_BCC };
+
+		recipients = g_ptr_array_new ();
+		for (i = 0; i < G_N_ELEMENTS (types); i++) {
 			const CamelInternetAddress *addr;
-			const char *address;
+			const gchar *address;
 
-			addr = camel_mime_message_get_recipients(new, types[i]);
-			for (j=0;camel_internet_address_get(addr, j, NULL, &address); j++)
-				g_ptr_array_add(recipients, g_strdup (address));
+			addr = camel_mime_message_get_recipients (new, types[i]);
+			for (j=0;camel_internet_address_get (addr, j, NULL, &address); j++)
+				g_ptr_array_add (recipients, g_strdup (address));
 
 		}
 	}
 
-	if (p->pgp_sign || p->pgp_encrypt) {
-		const char *pgp_userid;
+	if (pgp_sign || pgp_encrypt) {
+		const gchar *pgp_userid;
 		CamelInternetAddress *from = NULL;
 		CamelCipherContext *cipher;
+		EAccount *account;
 
 		part = camel_mime_part_new ();
 		camel_medium_set_content_object (CAMEL_MEDIUM (part), current);
@@ -748,45 +799,47 @@
 			camel_mime_part_set_encoding (part, plain_encoding);
 		camel_object_unref (current);
 
+		account = e_composer_header_table_get_account (table);
+
 		if (account && account->pgp_key && *account->pgp_key) {
 			pgp_userid = account->pgp_key;
 		} else {
-			from = e_msg_composer_hdrs_get_from(hdrs);
-			camel_internet_address_get(from, 0, NULL, &pgp_userid);
+			from = e_msg_composer_get_from (composer);
+			camel_internet_address_get (from, 0, NULL, &pgp_userid);
 		}
 
-		if (p->pgp_sign) {
-			CamelMimePart *npart = camel_mime_part_new();
+		if (pgp_sign) {
+			CamelMimePart *npart = camel_mime_part_new ();
 
-			cipher = mail_crypto_get_pgp_cipher_context(account);
-			camel_cipher_sign(cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
-			camel_object_unref(cipher);
+			cipher = mail_crypto_get_pgp_cipher_context (account);
+			camel_cipher_sign (cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
+			camel_object_unref (cipher);
 
-			if (camel_exception_is_set(&ex)) {
-				camel_object_unref(npart);
+			if (camel_exception_is_set (&ex)) {
+				camel_object_unref (npart);
 				goto exception;
 			}
 
-			camel_object_unref(part);
+			camel_object_unref (part);
 			part = npart;
 		}
 
-		if (p->pgp_encrypt) {
-			CamelMimePart *npart = camel_mime_part_new();
+		if (pgp_encrypt) {
+			CamelMimePart *npart = camel_mime_part_new ();
 
 			/* check to see if we should encrypt to self, NB gets removed immediately after use */
 			if (account && account->pgp_encrypt_to_self && pgp_userid)
 				g_ptr_array_add (recipients, g_strdup (pgp_userid));
 
 			cipher = mail_crypto_get_pgp_cipher_context (account);
-			camel_cipher_encrypt(cipher, pgp_userid, recipients, part, npart, &ex);
+			camel_cipher_encrypt (cipher, pgp_userid, recipients, part, npart, &ex);
 			camel_object_unref (cipher);
 
 			if (account && account->pgp_encrypt_to_self && pgp_userid)
-				g_ptr_array_set_size(recipients, recipients->len - 1);
+				g_ptr_array_set_size (recipients, recipients->len - 1);
 
 			if (camel_exception_is_set (&ex)) {
-				camel_object_unref(npart);
+				camel_object_unref (npart);
 				goto exception;
 			}
 
@@ -803,84 +856,84 @@
 	}
 
 #if defined (HAVE_NSS) && defined (SMIME_SUPPORTED)
-	if (p->smime_sign || p->smime_encrypt) {
+	if (smime_sign || smime_encrypt) {
 		CamelInternetAddress *from = NULL;
 		CamelCipherContext *cipher;
 
-		part = camel_mime_part_new();
-		camel_medium_set_content_object((CamelMedium *)part, current);
+		part = camel_mime_part_new ();
+		camel_medium_set_content_object ((CamelMedium *)part, current);
 		if (current == plain)
-			camel_mime_part_set_encoding(part, plain_encoding);
-		camel_object_unref(current);
+			camel_mime_part_set_encoding (part, plain_encoding);
+		camel_object_unref (current);
 
-		if (p->smime_sign
+		if (smime_sign
 		    && (account == NULL || account->smime_sign_key == NULL || account->smime_sign_key[0] == 0)) {
 			camel_exception_set (&ex, CAMEL_EXCEPTION_SYSTEM,
 					     _("Cannot sign outgoing message: No signing certificate set for this account"));
 			goto exception;
 		}
 
-		if (p->smime_encrypt
+		if (smime_encrypt
 		    && (account == NULL || account->smime_sign_key == NULL || account->smime_sign_key[0] == 0)) {
 			camel_exception_set (&ex, CAMEL_EXCEPTION_SYSTEM,
 					     _("Cannot encrypt outgoing message: No encryption certificate set for this account"));
 			goto exception;
 		}
 
-		if (p->smime_sign) {
-			CamelMimePart *npart = camel_mime_part_new();
+		if (smime_sign) {
+			CamelMimePart *npart = camel_mime_part_new ();
 
-			cipher = camel_smime_context_new(session);
+			cipher = camel_smime_context_new (session);
 
 			/* if we're also encrypting, envelope-sign rather than clear-sign */
-			if (p->smime_encrypt) {
-				camel_smime_context_set_sign_mode((CamelSMIMEContext *)cipher, CAMEL_SMIME_SIGN_ENVELOPED);
-				camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
+			if (smime_encrypt) {
+				camel_smime_context_set_sign_mode ((CamelSMIMEContext *)cipher, CAMEL_SMIME_SIGN_ENVELOPED);
+				camel_smime_context_set_encrypt_key ((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
 			} else if (account && account->smime_encrypt_key && *account->smime_encrypt_key) {
-				camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
+				camel_smime_context_set_encrypt_key ((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
 			}
 
-			camel_cipher_sign(cipher, account->smime_sign_key, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
-			camel_object_unref(cipher);
+			camel_cipher_sign (cipher, account->smime_sign_key, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex);
+			camel_object_unref (cipher);
 
-			if (camel_exception_is_set(&ex)) {
-				camel_object_unref(npart);
+			if (camel_exception_is_set (&ex)) {
+				camel_object_unref (npart);
 				goto exception;
 			}
 
-			camel_object_unref(part);
+			camel_object_unref (part);
 			part = npart;
 		}
 
-		if (p->smime_encrypt) {
+		if (smime_encrypt) {
 			/* check to see if we should encrypt to self, NB removed after use */
 			if (account->smime_encrypt_to_self)
-				g_ptr_array_add(recipients, g_strdup (account->smime_encrypt_key));
+				g_ptr_array_add (recipients, g_strdup (account->smime_encrypt_key));
 
-			cipher = camel_smime_context_new(session);
-			camel_smime_context_set_encrypt_key((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
+			cipher = camel_smime_context_new (session);
+			camel_smime_context_set_encrypt_key ((CamelSMIMEContext *)cipher, TRUE, account->smime_encrypt_key);
 
-			camel_cipher_encrypt(cipher, NULL, recipients, part, (CamelMimePart *)new, &ex);
-			camel_object_unref(cipher);
+			camel_cipher_encrypt (cipher, NULL, recipients, part, (CamelMimePart *)new, &ex);
+			camel_object_unref (cipher);
 
-			if (camel_exception_is_set(&ex))
+			if (camel_exception_is_set (&ex))
 				goto exception;
 
 			if (account->smime_encrypt_to_self)
-				g_ptr_array_set_size(recipients, recipients->len - 1);
+				g_ptr_array_set_size (recipients, recipients->len - 1);
 		}
 
 		if (from)
-			camel_object_unref(from);
+			camel_object_unref (from);
 
 		/* we replaced the message directly, we don't want to do reparenting foo */
-		if (p->smime_encrypt) {
-			camel_object_unref(part);
+		if (smime_encrypt) {
+			camel_object_unref (part);
 			goto skip_content;
 		} else {
-			current = camel_medium_get_content_object((CamelMedium *)part);
-			camel_object_ref(current);
-			camel_object_unref(part);
+			current = camel_medium_get_content_object ((CamelMedium *)part);
+			camel_object_ref (current);
+			camel_object_unref (part);
 		}
 	}
 #endif /* HAVE_NSS */
@@ -895,13 +948,14 @@
 #endif
 	if (recipients) {
 		for (i=0; i<recipients->len; i++)
-			g_free(recipients->pdata[i]);
-		g_ptr_array_free(recipients, TRUE);
+			g_free (recipients->pdata[i]);
+		g_ptr_array_free (recipients, TRUE);
 	}
 
 	/* Attach whether this message was written in HTML */
-	camel_medium_set_header (CAMEL_MEDIUM (new), "X-Evolution-Format",
-				 p->send_html ? "text/html" : "text/plain");
+	camel_medium_set_header (
+		CAMEL_MEDIUM (new), "X-Evolution-Format",
+		html_content ? "text/html" : "text/plain");
 
 	return new;
 
@@ -913,39 +967,145 @@
 	camel_object_unref (new);
 
 	if (ex.id != CAMEL_EXCEPTION_USER_CANCEL) {
-		e_error_run((GtkWindow *)composer, "mail-composer:no-build-message",
-			    camel_exception_get_description(&ex), NULL);
+		e_error_run ((GtkWindow *)composer, "mail-composer:no-build-message",
+			    camel_exception_get_description (&ex), NULL);
 	}
 
 	camel_exception_clear (&ex);
 
 	if (recipients) {
 		for (i=0; i<recipients->len; i++)
-			g_free(recipients->pdata[i]);
-		g_ptr_array_free(recipients, TRUE);
+			g_free (recipients->pdata[i]);
+		g_ptr_array_free (recipients, TRUE);
 	}
 
 	return NULL;
 }
 
+/* Attachment Bar */
+
+static void
+emcab_add (EPopup *ep, EPopupItem *item, gpointer data)
+{
+	GtkWidget *widget = data;
+	GtkWidget *composer;
+
+	composer = gtk_widget_get_toplevel (widget);
+	gtk_action_activate (ACTION (ATTACH));
+}
+
+static void
+emcab_properties (EPopup *ep, EPopupItem *item, gpointer data)
+{
+	EAttachmentBar *attachment_bar = data;
+
+	e_attachment_bar_edit_selected (attachment_bar);
+}
+
+static void
+emcab_remove (EPopup *ep, EPopupItem *item, gpointer data)
+{
+	EAttachmentBar *attachment_bar = data;
+
+	e_attachment_bar_remove_selected (attachment_bar);
+}
+
+static void
+emcab_popup_position (GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data)
+{
+	GtkWidget *widget = user_data;
+	GnomeIconList *icon_list = user_data;
+	GList *selection;
+	GnomeCanvasPixbuf *image;
+
+	gdk_window_get_origin (widget->window, x, y);
+
+	selection = gnome_icon_list_get_selection (icon_list);
+	if (selection == NULL)
+		return;
+
+	image = gnome_icon_list_get_icon_pixbuf_item (
+		icon_list, GPOINTER_TO_INT(selection->data));
+	if (image == NULL)
+		return;
+
+	/* Put menu to the center of icon. */
+	*x += (int)(image->item.x1 + image->item.x2) / 2;
+	*y += (int)(image->item.y1 + image->item.y2) / 2;
+}
+
+static void
+emcab_popups_free (EPopup *ep, GSList *list, gpointer data)
+{
+	g_slist_free (list);
+}
+
+/* Popup menu handling.  */
+static EPopupItem emcab_popups[] = {
+	{ E_POPUP_ITEM, "10.attach", N_("_Remove"), emcab_remove, NULL, GTK_STOCK_REMOVE, EM_POPUP_ATTACHMENTS_MANY },
+	{ E_POPUP_ITEM, "20.attach", N_("_Properties"), emcab_properties, NULL, GTK_STOCK_PROPERTIES, EM_POPUP_ATTACHMENTS_ONE },
+	{ E_POPUP_BAR, "30.attach.00", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MANY|EM_POPUP_ATTACHMENTS_ONE },
+	{ E_POPUP_ITEM, "30.attach.01", N_("_Add attachment..."), emcab_add, NULL, GTK_STOCK_ADD, 0 },
+};
+
+/* if id != -1, then use it as an index for target of the popup */
+
+static void
+emcab_popup (EAttachmentBar *bar, GdkEventButton *event, int id)
+{
+	GSList *attachments = NULL, *menus = NULL;
+	int i;
+	EMPopup *emp;
+	EMPopupTargetAttachments *t;
+	GtkMenu *menu;
+
+	attachments = e_attachment_bar_get_attachment (bar, id);
+
+	for (i=0;i<sizeof (emcab_popups)/sizeof (emcab_popups[0]);i++)
+		menus = g_slist_prepend (menus, &emcab_popups[i]);
+
+	/** @HookPoint-EMPopup: Composer Attachment Bar Context Menu
+	 * @Id: org.gnome.evolution.mail.composer.attachmentbar.popup
+	 * @Class: org.gnome.evolution.mail.popup:1.0
+	 * @Target: EMPopupTargetAttachments
+	 *
+	 * This is the context menu on the composer attachment bar.
+	 */
+	emp = em_popup_new ("org.gnome.evolution.mail.composer.attachmentbar.popup");
+	e_popup_add_items ((EPopup *)emp, menus, NULL, emcab_popups_free, bar);
+	t = em_popup_target_new_attachments (emp, attachments);
+	t->target.widget = (GtkWidget *)bar;
+	menu = e_popup_create_menu_once ((EPopup *)emp, (EPopupTarget *)t, 0);
+
+	if (event == NULL)
+		gtk_menu_popup (menu, NULL, NULL, emcab_popup_position, bar, 0, gtk_get_current_event_time ());
+	else
+		gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time);
+}
+
+/* Signatures */
 
-static char *
-get_file_content (EMsgComposer *composer, const char *file_name, gboolean want_html, guint flags, gboolean warn)
+static gchar *
+get_file_content (EMsgComposer *composer,
+                  const gchar *filename,
+                  gboolean want_html,
+                  guint flags,
+                  gboolean warn)
 {
 	CamelStreamFilter *filtered_stream;
 	CamelStreamMem *memstream;
 	CamelMimeFilter *html, *charenc;
 	CamelStream *stream;
 	GByteArray *buffer;
-	char *charset;
-	char *content;
-	int fd;
+	gchar *charset;
+	gchar *content;
+	gint fd;
 
-	fd = g_open (file_name, O_RDONLY, 0);
+	fd = g_open (filename, O_RDONLY, 0);
 	if (fd == -1) {
 		if (warn)
-			e_error_run((GtkWindow *)composer, "mail-composer:no-sig-file",
-				    file_name, g_strerror(errno), NULL);
+			e_error_run ((GtkWindow *)composer, "mail-composer:no-sig-file",
+				    filename, g_strerror (errno), NULL);
 		return g_strdup ("");
 	}
 
@@ -983,7 +1143,7 @@
 		camel_object_unref (stream);
 
 		charset = composer && composer->priv->charset ? composer->priv->charset : NULL;
-		charset = charset ? g_strdup (charset) : composer_get_default_charset_setting ();
+		charset = charset ? g_strdup (charset) : e_composer_get_default_charset ();
 		if ((charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8"))) {
 			camel_stream_filter_add (filtered_stream, charenc);
 			camel_object_unref (charenc);
@@ -1007,8 +1167,8 @@
 	return content;
 }
 
-char *
-e_msg_composer_get_sig_file_content (const char *sigfile, gboolean in_html)
+gchar *
+e_msg_composer_get_sig_file_content (const gchar *sigfile, gboolean in_html)
 {
 	if (!sigfile || !*sigfile) {
 		return NULL;
@@ -1022,147 +1182,22 @@
 				 FALSE);
 }
 
-static void
-prepare_engine (EMsgComposer *composer)
+static gchar *
+encode_signature_name (const gchar *name)
 {
-	CORBA_Environment ev;
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	/* printf ("prepare_engine\n"); */
+	const gchar *s;
+	gchar *ename, *e;
+	gint len = 0;
 
-	CORBA_exception_init (&ev);
-	p->eeditor_engine = (GNOME_GtkHTML_Editor_Engine) Bonobo_Unknown_queryInterface
-		(bonobo_widget_get_objref (BONOBO_WIDGET (p->eeditor)), "IDL:GNOME/GtkHTML/Editor/Engine:1.0", &ev);
-	if ((p->eeditor_engine != CORBA_OBJECT_NIL) && (ev._major == CORBA_NO_EXCEPTION)) {
-
-		/* printf ("trying set listener\n"); */
-		p->eeditor_listener = BONOBO_OBJECT (listener_new (composer));
-		if (p->eeditor_listener != NULL)
-			GNOME_GtkHTML_Editor_Engine__set_listener (p->eeditor_engine,
-								   (GNOME_GtkHTML_Editor_Listener)
-								   bonobo_object_dup_ref
-								   (bonobo_object_corba_objref (p->eeditor_listener),
-								    &ev),
-								   &ev);
-
-		if ((ev._major != CORBA_NO_EXCEPTION) || (p->eeditor_listener == NULL)) {
-			CORBA_Environment err_ev;
-
-			CORBA_exception_init (&err_ev);
-
-			Bonobo_Unknown_unref (p->eeditor_engine, &err_ev);
-			CORBA_Object_release (p->eeditor_engine, &err_ev);
-
-			CORBA_exception_free (&err_ev);
-
-			p->eeditor_engine = CORBA_OBJECT_NIL;
-			g_warning ("Can't establish Editor Listener\n");
-		} else {
-			gchar *path;
-			GConfClient *gconf = gconf_client_get_default ();
-
-			path = gconf_client_get_string (gconf, COMPOSER_CURRENT_FOLDER_KEY, NULL);
-			g_object_unref (gconf);
-
-			/* change it only if we have set path before */
-			if (path && *path)
-				e_msg_composer_set_attach_path (composer, path);
-			g_free (path);
-		}
-	} else {
-		p->eeditor_engine = CORBA_OBJECT_NIL;
-		g_warning ("Can't get Editor Engine\n");
+	s = name;
+	while (*s) {
+		len ++;
+		if (*s == '"' || *s == '.' || *s == '=')
+			len ++;
+		s ++;
 	}
 
-	CORBA_exception_free (&ev);
-}
-
-/**
- * e_msg_composer_set_attach_path
- * Attach path is used to be preset when choosing files. This function ensures same path
- * in editor and in composer.
- * @param composer Composer.
- * @param path Path to be used. Should not be NULL.
- **/
-void
-e_msg_composer_set_attach_path (EMsgComposer *composer, const gchar *path)
-{
-	GConfClient *gconf;
-	GError *error = NULL;
-
-	g_return_if_fail (composer != NULL);
-	g_return_if_fail (path != NULL);
-
-	gconf = gconf_client_get_default ();
-	gconf_client_set_string (gconf, COMPOSER_CURRENT_FOLDER_KEY, path, &error);
-	g_object_unref (gconf);
-
-	if (error) {
-		g_warning ("Could not write current_folder setting: %s", error->message);
-		g_error_free (error);
-	}
-
-	if (composer->priv->eeditor_engine) {
-		CORBA_Environment ev;
-
-		CORBA_exception_init (&ev);
-	
-		GNOME_GtkHTML_Editor_Engine_setFilePath (composer->priv->eeditor_engine, path, &ev);
-
-		CORBA_exception_free (&ev);
-	}
-
-	/* do this as last thing here, so we can do e_msg_composer_set_attach_path (composer, e_msg_composer_get_attach_path (composer)) */
-	g_object_set_data_full ((GObject *) composer, "attach_path", g_strdup (path), g_free);
-}
-
-/**
- * e_msg_composer_get_attach_path
- * Last path, if any, used to select file.
- * @param composer Composer.
- * @return Last used path, or NULL when not set yet.
- **/
-const gchar *
-e_msg_composer_get_attach_path (EMsgComposer *composer)
-{
-	g_return_val_if_fail (composer != NULL, g_object_get_data ((GObject *) composer, "attach_path"));
-
-	if (composer->priv->eeditor_engine) {
-		char *str;
-		CORBA_Environment ev;
-
-		CORBA_exception_init (&ev);
-
-		str = GNOME_GtkHTML_Editor_Engine_getFilePath (composer->priv->eeditor_engine, &ev);
-		if (ev._major == CORBA_NO_EXCEPTION && str)
-			e_msg_composer_set_attach_path (composer, str);
-		if (str)
-			CORBA_free (str);
-
-		CORBA_exception_free (&ev);
-	}
-
-	return g_object_get_data ((GObject *) composer, "attach_path");
-}
-
-static char *
-encode_signature_name (const char *name)
-{
-	const char *s;
-	char *ename, *e;
-	int len = 0;
-
-	s = name;
-	while (*s) {
-		len ++;
-		if (*s == '"' || *s == '.' || *s == '=')
-			len ++;
-		s ++;
-	}
-
-	ename = g_new (gchar, len + 1);
+	ename = g_new (gchar, len + 1);
 
 	s = name;
 	e = ename;
@@ -1192,12 +1227,12 @@
 	return ename;
 }
 
-static char *
-decode_signature_name (const char *name)
+static gchar *
+decode_signature_name (const gchar *name)
 {
-	const char *s;
-	char *dname, *d;
-	int len = 0;
+	const gchar *s;
+	gchar *dname, *d;
+	gint len = 0;
 
 	s = name;
 	while (*s) {
@@ -1239,16 +1274,16 @@
 
 #define CONVERT_SPACES CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES
 
-static char *
+static gchar *
 get_signature_html (EMsgComposer *composer)
 {
-	EMsgComposerHdrs *hdrs;
-	char *text = NULL, *html = NULL;
+	EComposerHeaderTable *table;
+	gchar *text = NULL, *html = NULL;
 	ESignature *signature;
 	gboolean format_html;
 
-	hdrs = E_MSG_COMPOSER_HDRS (composer->priv->hdrs);
-	signature = e_msg_composer_hdrs_get_signature (hdrs);
+	table = e_msg_composer_get_header_table (composer);
+	signature = e_composer_header_table_get_signature (table);
 
 	if (!signature)
 		return NULL;
@@ -1266,11 +1301,11 @@
 		}
 	} else {
 		EAccountIdentity *id;
-		char *organization;
-		char *address;
-		char *name;
+		gchar *organization;
+		gchar *address;
+		gchar *name;
 
-		id = e_msg_composer_hdrs_get_from_account (hdrs)->id;
+		id = e_composer_header_table_get_account (table)->id;
 		address = id->address ? camel_text_to_html (id->address, CONVERT_SPACES, 0) : NULL;
 		name = id->name ? camel_text_to_html (id->name, CONVERT_SPACES, 0) : NULL;
 		organization = id->organization ? camel_text_to_html (id->organization, CONVERT_SPACES, 0) : NULL;
@@ -1292,7 +1327,7 @@
 
 	/* printf ("text: %s\n", text); */
 	if (text) {
-		char *encoded_uid = NULL;
+		gchar *encoded_uid = NULL;
 
 		if (signature)
 			encoded_uid = encode_signature_name (signature->uid);
@@ -1308,7 +1343,7 @@
 					"</TD></TR></TABLE>",
 				        encoded_uid ? encoded_uid : "",
 					format_html ? "" : "<PRE>\n",
-					format_html || (!strncmp ("-- \n", text, 4) || strstr(text, "\n-- \n")) ? "" : "-- \n",
+					format_html || (!strncmp ("-- \n", text, 4) || strstr (text, "\n-- \n")) ? "" : "-- \n",
 					text,
 					format_html ? "" : "</PRE>\n");
 		g_free (text);
@@ -1320,22 +1355,16 @@
 }
 
 static void
-set_editor_text(EMsgComposer *composer, const char *text, ssize_t len, int set_signature, int pad_signature)
+set_editor_text (EMsgComposer *composer,
+                 const gchar *text,
+                 gboolean set_signature)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	Bonobo_PersistStream persist;
-	BonoboStream *stream;
-	CORBA_Environment ev;
-	Bonobo_Unknown object;
 	gboolean reply_signature_on_top;
-	char *body = NULL, *html = NULL;
+	gchar *body = NULL, *html = NULL;
 	GConfClient *gconf;
 
-	g_return_if_fail (p->persist_stream_interface != CORBA_OBJECT_NIL);
-
-	persist = p->persist_stream_interface;
-
-	CORBA_exception_init (&ev);
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (text != NULL);
 
 	gconf = gconf_client_get_default ();
 
@@ -1353,12 +1382,12 @@
 
 	 */
 
-	reply_signature_on_top = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/top_signature", NULL);
+	reply_signature_on_top = gconf_client_get_bool (gconf, COMPOSER_GCONF_TOP_SIGNATURE_KEY, NULL);
 
 	g_object_unref (gconf);
 
 	if (set_signature && reply_signature_on_top) {
-		char *tmp = NULL;
+		gchar *tmp = NULL;
 		tmp = get_signature_html (composer);
 		if (tmp) {
 			/* Minimizing the damage. Make it just a part of the body instead of a signature */
@@ -1379,26 +1408,10 @@
 					"<TABLE WIDTH=\"100%%\" CELLSPACING=\"0\" CELLPADDING=\"0\"><TR><TD> </TD></TR></TABLE>%s", text);
 		}
 	} else {
-		body = g_strdup(text);
-	}
-
-	if (body) {
-		len = strlen (body);
-	}
-
-	stream = bonobo_stream_mem_create (body, len, TRUE, FALSE);
-	object = bonobo_object_corba_objref (BONOBO_OBJECT (stream));
-	Bonobo_PersistStream_load (persist, (Bonobo_Stream) object, "text/html", &ev);
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		/* FIXME. Some error message. */
-		bonobo_object_unref (BONOBO_OBJECT (stream));
-		CORBA_exception_free (&ev);
-		return;
+		body = g_strdup (text);
 	}
 
-	CORBA_exception_free (&ev);
-
-	bonobo_object_unref (BONOBO_OBJECT (stream));
+	gtkhtml_editor_set_text_html (GTKHTML_EDITOR (composer), body, -1);
 
 	if (set_signature && !reply_signature_on_top)
 		e_msg_composer_show_sig_file (composer);
@@ -1406,168 +1419,8 @@
 
 /* Commands.  */
 
-static void
-show_attachments (EMsgComposer *composer,
-		  gboolean show)
-{
-	EMsgComposerPrivate *p = composer->priv;
-
-	e_expander_set_expanded (E_EXPANDER (p->attachment_expander), show);
-	if (show)
-		gtk_label_set_text_with_mnemonic (GTK_LABEL (composer->priv->attachment_expander_label),
-		_("Hide _Attachment Bar"));
-	else
-		gtk_label_set_text_with_mnemonic (GTK_LABEL (composer->priv->attachment_expander_label),
-		_("Show _Attachment Bar"));
-}
-
-static void
-save (EMsgComposer *composer, const char *filename)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
-	int fd;
-
-	/* check to see if we already have the file and that we can create it */
-	if ((fd = g_open (filename, O_RDONLY | O_CREAT | O_EXCL, 0777)) == -1) {
-		int resp, errnosav = errno;
-		struct stat st;
-
-		if (g_stat (filename, &st) == 0 && S_ISREG (st.st_mode)) {
-			resp = e_error_run((GtkWindow *)composer, E_ERROR_ASK_FILE_EXISTS_OVERWRITE, filename, NULL);
-			if (resp != GTK_RESPONSE_OK)
-				return;
-		} else {
-			e_error_run((GtkWindow *)composer, E_ERROR_NO_SAVE_FILE, filename, g_strerror(errnosav));
-			return;
-		}
-	} else
-		close (fd);
-
-	CORBA_exception_init (&ev);
-
-	Bonobo_PersistFile_save (p->persist_file_interface, filename, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		e_error_run((GtkWindow *)composer, E_ERROR_NO_SAVE_FILE,
-			    filename, _("Unknown reason"));
-	} else {
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "saved", &ev);
-		e_msg_composer_unset_autosaved (composer);
-	}
-	CORBA_exception_free (&ev);
-}
-
-static void
-saveas_response(EMsgComposer *composer, const char *name)
-{
-	save(composer, name);
-}
-
-static void
-saveas(EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-
-	e_msg_composer_select_file (composer, &p->saveas, saveas_response, _("Save as..."), TRUE);
-}
-
-static void
-load (EMsgComposer *composer, const char *file_name)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
-
-	Bonobo_PersistFile_load (p->persist_file_interface, file_name, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION)
-		e_error_run((GtkWindow *)composer, E_ERROR_NO_LOAD_FILE,
-			    file_name, _("Unknown reason"), NULL);
-
-	CORBA_exception_free (&ev);
-}
-
-#define AUTOSAVE_SEED ".evolution-composer.autosave-XXXXXX"
-#define AUTOSAVE_INTERVAL 60000
-
-typedef struct _AutosaveManager AutosaveManager;
-struct _AutosaveManager {
-	GHashTable *table;
-	guint id;
-	gboolean ask;
-};
-
-static AutosaveManager *am = NULL;
-static void autosave_manager_start (AutosaveManager *am);
-static void autosave_manager_stop (AutosaveManager *am);
-
-static gboolean
-autosave_save_draft (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CamelMimeMessage *message;
-	CamelStream *stream;
-	char *file;
-	int fd, camelfd;
-	gboolean success = TRUE;
-
-	if (!e_msg_composer_is_dirty (composer))
-		return TRUE;
-
-	fd = p->autosave_fd;
-	file = p->autosave_file;
-
-	if (fd == -1) {
-		/* This code is odd, the fd is opened elsewhere but a failure is ignored */
-		e_error_run((GtkWindow *)composer, "mail-composer:no-autosave",
-			    file, _("Could not open file"), NULL);
-		return FALSE;
-	}
-
-	message = e_msg_composer_get_message_draft (composer);
-
-	if (message == NULL) {
-		e_error_run((GtkWindow *)composer, "mail-composer:no-autosave",
-			    file, _("Unable to retrieve message from editor"), NULL);
-		return FALSE;
-	}
-
-	if (lseek (fd, (off_t)0, SEEK_SET) == -1
-	    || ftruncate (fd, (off_t)0) == -1
-	    || (camelfd = dup(fd)) == -1) {
-		camel_object_unref (message);
-		e_error_run((GtkWindow *)composer, "mail-composer:no-autosave",
-			    file, g_strerror(errno), NULL);
-		return FALSE;
-	}
-
-	/* this does an lseek so we don't have to */
-	stream = camel_stream_fs_new_with_fd (camelfd);
-	if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream) == -1
-	    || camel_stream_close (CAMEL_STREAM (stream)) == -1) {
-		e_error_run((GtkWindow *)composer, "mail-composer:no-autosave",
-			    file, g_strerror(errno), NULL);
-		success = FALSE;
-	} else {
-		CORBA_Environment ev;
-		CORBA_exception_init (&ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "saved", &ev);
-		CORBA_exception_free (&ev);
-		e_msg_composer_unset_changed (composer);
-		e_msg_composer_set_autosaved (composer);
-	}
-
-	camel_object_unref (stream);
-
-	camel_object_unref (message);
-
-	return success;
-}
-
 static EMsgComposer *
-autosave_load_draft (const char *filename)
+autosave_load_draft (const gchar *filename)
 {
 	CamelStream *stream;
 	CamelMimeMessage *msg;
@@ -1586,14 +1439,16 @@
 
 	composer = e_msg_composer_new_with_message (msg);
 	if (composer) {
-		if (autosave_save_draft (composer))
+		if (e_composer_autosave_snapshot (composer))
 			g_unlink (filename);
 
-		g_signal_connect (GTK_OBJECT (composer), "send",
-				  G_CALLBACK (em_utils_composer_send_cb), NULL);
-
-		g_signal_connect (GTK_OBJECT (composer), "save-draft",
-				  G_CALLBACK (em_utils_composer_save_draft_cb), NULL);
+		g_signal_connect (
+			composer, "send",
+			G_CALLBACK (em_utils_composer_send_cb), NULL);
+
+		g_signal_connect (
+			composer, "save-draft",
+			G_CALLBACK (em_utils_composer_save_draft_cb), NULL);
 
 		gtk_widget_show (GTK_WIDGET (composer));
 	}
@@ -1601,4600 +1456,3076 @@
 	return composer;
 }
 
-static gboolean
-autosave_is_owned (AutosaveManager *am, const char *file)
-{
-	return g_hash_table_lookup (am->table, file) != NULL;
-}
+/* Miscellaneous callbacks.  */
 
-static void
-autosave_manager_query_load_orphans (AutosaveManager *am, GtkWindow *parent)
+static gint
+attachment_bar_button_press_event_cb (EAttachmentBar *attachment_bar,
+                                      GdkEventButton *event)
 {
-	GDir *dir;
-	const char *dname;
-	GSList *match = NULL;
-	gint len = strlen (AUTOSAVE_SEED);
-	gint load = FALSE;
-	const gchar *dirname;
+	GnomeIconList *icon_list;
+	gint icon_number;
 
-	dirname = e_get_user_data_dir ();
-	dir = g_dir_open (dirname, 0, NULL);
-	if (!dir) {
-		return;
-	}
+	if (event->button != 3)
+		return FALSE;
 
-	while ((dname = g_dir_read_name (dir))) {
-		if ((!strncmp (dname, AUTOSAVE_SEED, len - 6))
-		    && (strlen (dname) == len)
-		    && (!autosave_is_owned (am, dname))) {
-			gchar *filename;
-			struct stat st;
-
-			filename = g_build_filename (dirname, dname, NULL);
-
-			/*
-			 * check if the file has any length,  It is a valid case if it doesn't
-			 * so we simply don't ask then.
-			 */
-			if (g_stat (filename, &st) == -1 || st.st_size == 0) {
-				g_unlink (filename);
-				g_free (filename);
-				continue;
-			}
-			match = g_slist_prepend (match, filename);
-		}
+	icon_list = GNOME_ICON_LIST (attachment_bar);
+	icon_number = gnome_icon_list_get_icon_at (
+		icon_list, event->x, event->y);
+	if (icon_number >= 0) {
+		gnome_icon_list_unselect_all (icon_list);
+		gnome_icon_list_select_icon (icon_list, icon_number);
 	}
 
-	g_dir_close (dir);
-
-	if (match != NULL)
-		load = e_error_run(parent, "mail-composer:recover-autosave", NULL) == GTK_RESPONSE_YES;
-
-	while (match != NULL) {
-		GSList *next = match->next;
-		char *filename = match->data;
-		EMsgComposer *composer;
-
-		if (load) {
-			/* FIXME: composer is never used */
-			composer = autosave_load_draft (filename);
-		} else {
-			g_unlink (filename);
-		}
+	emcab_popup (attachment_bar, event, icon_number);
 
-		g_free (filename);
-		g_slist_free_1 (match);
-		match = next;
-	}
+	return TRUE;
 }
 
 static void
-autosave_run_foreach_cb (gpointer key, gpointer value, gpointer data)
+attachment_bar_changed_cb (EAttachmentBar *attachment_bar,
+                           EMsgComposer *composer)
 {
-	EMsgComposer *composer = E_MSG_COMPOSER (value);
-	EMsgComposerPrivate *p = composer->priv;
+	GtkhtmlEditor *editor;
+	GtkWidget *widget;
+	guint attachment_num;
 
-	if (p->enable_autosave)
-		autosave_save_draft (composer);
-}
+	editor = GTKHTML_EDITOR (composer);
+	attachment_num = e_attachment_bar_get_num_attachments (attachment_bar);
 
-static gint
-autosave_run (gpointer data)
-{
-	AutosaveManager *am = data;
+	if (attachment_num > 0) {
+		gchar *markup;
 
-	g_hash_table_foreach (am->table, (GHFunc)autosave_run_foreach_cb, am);
+		markup = g_strdup_printf (
+			"<b>%d</b> %s", attachment_num, ngettext (
+			"Attachment", "Attachments", attachment_num));
+		widget = composer->priv->attachment_expander_num;
+		gtk_label_set_markup (GTK_LABEL (widget), markup);
+		g_free (markup);
 
-	autosave_manager_stop (am);
-	autosave_manager_start (am);
+		gtk_widget_show (composer->priv->attachment_expander_icon);
 
-	return FALSE;
+		widget = composer->priv->attachment_expander;
+		gtk_expander_set_expanded (GTK_EXPANDER (widget), TRUE);
+	} else {
+		widget = composer->priv->attachment_expander_num;
+		gtk_label_set_text (GTK_LABEL (widget), "");
+
+		gtk_widget_hide (composer->priv->attachment_expander_icon);
+
+		widget = composer->priv->attachment_expander;
+		gtk_expander_set_expanded (GTK_EXPANDER (widget), FALSE);
+	}
+
+	/* Mark the editor as changed so it prompts about unsaved
+	   changes on close. */
+	gtkhtml_editor_set_changed (editor, TRUE);
 }
 
-static gboolean
-autosave_init_file (EMsgComposer *composer)
+static gint
+attachment_bar_key_press_event_cb (EAttachmentBar *attachment_bar,
+                                   GdkEventKey *event)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	if (p->autosave_file == NULL) {
-		p->autosave_file = g_build_filename (
-			e_get_user_data_dir (), AUTOSAVE_SEED, NULL);
-		p->autosave_fd = g_mkstemp (p->autosave_file);
+	if (event->keyval == GDK_Delete) {
+		e_attachment_bar_remove_selected (attachment_bar);
 		return TRUE;
 	}
+
 	return FALSE;
 }
 
-static void
-autosave_manager_start (AutosaveManager *am)
+static gboolean
+attachment_bar_popup_menu_cb (EAttachmentBar *attachment_bar)
 {
-	if (am->id == 0)
-		am->id = g_timeout_add (AUTOSAVE_INTERVAL, autosave_run, am);
-}
+	emcab_popup (attachment_bar, NULL, -1);
 
-static void
-autosave_manager_stop (AutosaveManager *am)
-{
-	if (am->id) {
-		g_source_remove (am->id);
-		am->id = 0;
-	}
+	return TRUE;
 }
 
-static AutosaveManager *
-autosave_manager_new (void)
+static void
+attachment_expander_notify_cb (GtkExpander *expander,
+                               GParamSpec *pspec,
+                               EMsgComposer *composer)
 {
-	AutosaveManager *am;
-	GHashTable *table;
+	GtkLabel *label;
+	const gchar *text;
 
-	table = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) NULL);
+	label = GTK_LABEL (composer->priv->attachment_expander_label);
 
-	am = g_new (AutosaveManager, 1);
-	am->table = table;
-	am->id = 0;
-	am->ask = TRUE;
+	/* Update the expander label */
+	if (gtk_expander_get_expanded (expander))
+		text = _("Hide _Attachment Bar");
+	else
+		text = _("Show _Attachment Bar");
 
-	return am;
+	gtk_label_set_text_with_mnemonic (label, text);
 }
 
 static void
-autosave_manager_register (AutosaveManager *am, EMsgComposer *composer)
+msg_composer_subject_changed_cb (EMsgComposer *composer)
 {
-	char *key;
-	EMsgComposerPrivate *p = composer->priv;
+	EComposerHeaderTable *table;
+	const gchar *subject;
 
-	g_return_if_fail (composer != NULL);
+	table = e_msg_composer_get_header_table (composer);
+	subject = e_composer_header_table_get_subject (table);
 
-	if (autosave_init_file (composer)) {
-		key = g_path_get_basename (p->autosave_file);
-		g_hash_table_insert (am->table, key, composer);
-		if (am->ask) {
-			/* keep recursion out of our bedrooms. */
-			am->ask = FALSE;
-			autosave_manager_query_load_orphans (am, (GtkWindow *)composer);
-			am->ask = TRUE;
-		}
-	}
-	autosave_manager_start (am);
+	if (subject == NULL || *subject == '\0')
+		subject = _("Compose Message");
+
+	gtk_window_set_title (GTK_WINDOW (composer), subject);
 }
 
+enum {
+	UPDATE_AUTO_CC,
+	UPDATE_AUTO_BCC,
+};
+
 static void
-autosave_manager_unregister (AutosaveManager *am, EMsgComposer *composer)
+update_auto_recipients (EComposerHeaderTable *table,
+                        gint mode,
+                        const gchar *auto_addrs)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	gchar *key;
+	EDestination *dest, **destv = NULL;
+	CamelInternetAddress *iaddr;
+	GList *list = NULL;
+	guint length;
+	gint i;
 
-	if (!p->autosave_file)
-		return;
+	if (auto_addrs) {
+		iaddr = camel_internet_address_new ();
+		if (camel_address_decode (CAMEL_ADDRESS (iaddr), auto_addrs) != -1) {
+			for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
+				const gchar *name, *addr;
 
-	key = g_path_get_basename (p->autosave_file);
-	g_hash_table_remove (am->table, key);
-	g_free (key);
-
-	/* only remove the file if we can successfully save it */
-	/* FIXME this test could probably be more efficient */
-	if (autosave_save_draft (composer)) {
-		/* Close before unlinking necessary on Win32 */
-		close (p->autosave_fd);
-		g_unlink (p->autosave_file);
-	} else {
-		close (p->autosave_fd);
-	}
-	g_free (p->autosave_file);
-	p->autosave_file = NULL;
+				if (!camel_internet_address_get (iaddr, i, &name, &addr))
+					continue;
 
-	if (g_hash_table_size (am->table) == 0)
-		autosave_manager_stop (am);
-}
+				dest = e_destination_new ();
+				e_destination_set_auto_recipient (dest, TRUE);
 
-static void
-menu_file_save_draft_cb (BonoboUIComponent *uic, void *data, const char *path)
-{
-	g_signal_emit (data, signals[SAVE_DRAFT], 0, FALSE);
-	e_msg_composer_unset_changed (E_MSG_COMPOSER (data));
-	e_msg_composer_unset_autosaved (E_MSG_COMPOSER (data));
-}
+				if (name)
+					e_destination_set_name (dest, name);
 
-/* Exit dialog.  (Displays a "Save composition to 'Drafts' before exiting?" warning before actually exiting.)  */
+				if (addr)
+					e_destination_set_email (dest, addr);
 
-static void
-do_exit (EMsgComposer *composer)
-{
-	const char *subject;
-	int button;
-	EMsgComposerPrivate *p = composer->priv;
+				list = g_list_prepend (list, dest);
+			}
+		}
 
-	if (!e_msg_composer_is_dirty (composer) && !e_msg_composer_is_autosaved (composer)) {
-		gtk_widget_destroy (GTK_WIDGET (composer));
-		return;
+		camel_object_unref (iaddr);
+	}
+
+	switch (mode) {
+	case UPDATE_AUTO_CC:
+		destv = e_composer_header_table_get_destinations_cc (table);
+		break;
+	case UPDATE_AUTO_BCC:
+		destv = e_composer_header_table_get_destinations_bcc (table);
+		break;
+	default:
+		g_return_if_reached ();
 	}
 
-	gdk_window_raise (GTK_WIDGET (composer)->window);
+	if (destv) {
+		for (i = 0; destv[i]; i++) {
+			if (!e_destination_is_auto_recipient (destv[i])) {
+				dest = e_destination_copy (destv[i]);
+				list = g_list_prepend (list, dest);
+			}
+		}
 
-	subject = e_msg_composer_hdrs_get_subject (E_MSG_COMPOSER_HDRS (p->hdrs));
+		e_destination_freev (destv);
+	}
 
-	button = e_error_run((GtkWindow *)composer, "mail-composer:exit-unsaved",
-			     subject && subject[0] ? subject : _("Untitled Message"), NULL);
+	list = g_list_reverse (list);
 
-	switch (button) {
-	case GTK_RESPONSE_YES:
-		/* Save */
-		g_signal_emit (GTK_OBJECT (composer), signals[SAVE_DRAFT], 0, TRUE);
-		e_msg_composer_unset_changed (composer);
-		e_msg_composer_unset_autosaved (composer);
-		gtk_widget_destroy (GTK_WIDGET (composer));
-		break;
-	case GTK_RESPONSE_NO:
-		/* Don't save */
-		gtk_widget_destroy (GTK_WIDGET (composer));
+	length = g_list_length (list);
+	destv = destination_list_to_vector_sized (list, length);
+
+	g_list_free (list);
+
+	switch (mode) {
+	case UPDATE_AUTO_CC:
+		e_composer_header_table_set_destinations_cc (table, destv);
 		break;
-	case GTK_RESPONSE_CANCEL:
+	case UPDATE_AUTO_BCC:
+		e_composer_header_table_set_destinations_bcc (table, destv);
 		break;
+	default:
+		g_return_if_reached ();
 	}
-}
 
-/* Menu callbacks.  */
-static void
-file_open_response(EMsgComposer *composer, const char *name)
-{
-	load (composer, name);
+	e_destination_freev (destv);
 }
 
 static void
-menu_file_open_cb (BonoboUIComponent *uic,
-		   void *data,
-		   const char *path)
+msg_composer_account_changed_cb (EMsgComposer *composer)
 {
-	EMsgComposer *composer = E_MSG_COMPOSER(data);
 	EMsgComposerPrivate *p = composer->priv;
+	EComposerHeaderTable *table;
+	GtkToggleAction *action;
+	ESignature *signature;
+	EAccount *account;
+	gboolean active;
+	const gchar *cc_addrs = NULL;
+	const gchar *bcc_addrs = NULL;
+	const gchar *uid;
 
-	/* NB: This function is never used anymore */
+	table = e_msg_composer_get_header_table (composer);
+	account = e_composer_header_table_get_account (table);
 
-	e_msg_composer_select_file(composer, &p->load, file_open_response, _("Open File"), FALSE);
-}
+	if (account == NULL)
+		goto exit;
 
-static void
-menu_file_save_cb (BonoboUIComponent *uic,
-		   void *data,
-		   const char *path)
-{
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_char *file_name;
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+	active = account->pgp_always_sign &&
+		(!account->pgp_no_imip_sign || p->mime_type == NULL ||
+		g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) != 0);
+	gtk_toggle_action_set_active (action, active);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
+	active = account->smime_sign_default;
+	gtk_toggle_action_set_active (action, active);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
+	active = account->smime_encrypt_default;
+	gtk_toggle_action_set_active (action, active);
+
+	if (account->always_cc)
+		cc_addrs = account->cc_addrs;
+	if (account->always_bcc)
+		bcc_addrs = account->bcc_addrs;
 
-	file_name = Bonobo_PersistFile_getCurrentFile (p->persist_file_interface, &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		saveas (composer);
-	} else {
-		save (composer, file_name);
-		CORBA_free (file_name);
-	}
-      	CORBA_exception_free (&ev);
-}
+	uid = account->id->sig_uid;
+	signature = uid ? mail_config_get_signature_by_uid (uid) : NULL;
+	e_composer_header_table_set_signature (table, signature);
 
-static void
-menu_file_save_as_cb (BonoboUIComponent *uic,
-		      void *data,
-		      const char *path)
-{
-	saveas (E_MSG_COMPOSER(data));
-}
+exit:
+	update_auto_recipients (table, UPDATE_AUTO_CC, cc_addrs);
+	update_auto_recipients (table, UPDATE_AUTO_BCC, bcc_addrs);
 
-static void
-menu_file_send_cb (BonoboUIComponent *uic,
-		   void *data,
-		   const char *path)
-{
-	g_signal_emit (GTK_OBJECT (data), signals[SEND], 0);
+	e_msg_composer_show_sig_file (composer);
 }
 
 static void
-menu_file_close_cb (BonoboUIComponent *uic,
-		    void *data,
-		    const char *path)
+msg_composer_attach_message (EMsgComposer *composer,
+                             CamelMimeMessage *msg)
 {
-	EMsgComposer *composer;
+	CamelMimePart *mime_part;
+	GString *description;
+	const gchar *subject;
+	EMsgComposerPrivate *p = composer->priv;
 
-	composer = E_MSG_COMPOSER (data);
-	do_exit (composer);
-}
+	mime_part = camel_mime_part_new ();
+	camel_mime_part_set_disposition (mime_part, "inline");
+	subject = camel_mime_message_get_subject (msg);
+
+	description = g_string_new (_("Attached message"));
+	if (subject != NULL)
+		g_string_append_printf (description, " - %s", subject);
+	camel_mime_part_set_description (mime_part, description->str);
+	g_string_free (description, TRUE);
+
+	camel_medium_set_content_object (
+		(CamelMedium *) mime_part, (CamelDataWrapper *) msg);
+	camel_mime_part_set_content_type (mime_part, "message/rfc822");
 
-/* this is the callback for the help menu */
-static void
-menu_help_cb (BonoboUIComponent *uic,
-	      void *data,
-	      const char *path)
-{
-	EMsgComposer *composer = (EMsgComposer *) data;
+	e_attachment_bar_attach_mime_part (
+		E_ATTACHMENT_BAR (p->attachment_bar), mime_part);
 
-	e_msg_composer_show_help (composer);
+	camel_object_unref (mime_part);
 }
 
-
 static void
-add_to_bar (EMsgComposer *composer, GSList *names, int is_inline)
+msg_composer_update_preferences (GConfClient *client,
+                                 guint cnxn_id,
+                                 GConfEntry *entry,
+                                 EMsgComposer *composer)
 {
-	EMsgComposerPrivate *p = composer->priv;
+	GtkhtmlEditor *editor;
+	gboolean enable;
+	GError *error = NULL;
 
-	while (names) {
-		CamelURL *url;
+	editor = GTKHTML_EDITOR (composer);
 
-		if (!(url = camel_url_new (names->data, NULL)))
-			continue;
+	enable = gconf_client_get_bool (
+		client, COMPOSER_GCONF_INLINE_SPELLING_KEY, &error);
+	if (error == NULL)
+		gtkhtml_editor_set_inline_spelling (editor, enable);
+	else {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
+	}
 
-		if (!g_ascii_strcasecmp (url->protocol, "file")) {
-			e_attachment_bar_attach((EAttachmentBar *)p->attachment_bar, url->path, is_inline ? "inline" : "attachment");
-		} else {
-			e_attachment_bar_attach_remote_file ((EAttachmentBar *)p->attachment_bar, names->data, is_inline ? "inline" : "attachment");
-		}
+	enable = gconf_client_get_bool (
+		client, COMPOSER_GCONF_MAGIC_LINKS_KEY, &error);
+	if (error == NULL)
+		gtkhtml_editor_set_magic_links (editor, enable);
+	else {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
+	}
 
-		camel_url_free (url);
-		names = names->next;
+	enable = gconf_client_get_bool (
+		client, COMPOSER_GCONF_MAGIC_SMILEYS_KEY, &error);
+	if (error == NULL)
+		gtkhtml_editor_set_magic_smileys (editor, enable);
+	else {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
 	}
 }
 
-static void
-menu_file_add_attachment_cb (BonoboUIComponent *uic,
-			     void *data,
-			     const char *path)
-{
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-	EMsgComposerPrivate *p = composer->priv;
-	EMsgComposer *toplevel = E_MSG_COMPOSER (gtk_widget_get_toplevel (GTK_WIDGET (p->attachment_bar)));
-	GtkWidget **attachment_selector = e_attachment_bar_get_selector(E_ATTACHMENT_BAR(p->attachment_bar));
-
-	e_msg_composer_select_file_attachments (toplevel, attachment_selector, add_to_bar);
-}
+struct _drop_data {
+	EMsgComposer *composer;
 
-static void
-menu_edit_cut_cb (BonoboUIComponent *uic, void *data, const char *path)
-{
-	EMsgComposer *composer = data;
-	EMsgComposerPrivate *p = composer->priv;
+	GdkDragContext *context;
+	/* Only selection->data and selection->length are valid */
+	GtkSelectionData *selection;
 
-	g_return_if_fail (p->focused_entry != NULL);
+	guint32 action;
+	guint info;
+	guint time;
 
-	if (GTK_IS_ENTRY (p->focused_entry)) {
-		gtk_editable_cut_clipboard (GTK_EDITABLE (p->focused_entry));
-	} else {
-		/* happy happy joy joy, an EEntry. */
-		g_return_if_reached ();
-	}
-}
+	unsigned int move:1;
+	unsigned int moved:1;
+	unsigned int aborted:1;
+};
 
-static void
-menu_edit_copy_cb (BonoboUIComponent *uic, void *data, const char *path)
+int
+e_msg_composer_get_remote_download_count (EMsgComposer *composer)
 {
-	EMsgComposer *composer = data;
-	EMsgComposerPrivate *p = composer->priv;
+	EAttachmentBar *attachment_bar;
 
-	g_return_if_fail (p->focused_entry != NULL);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), 0);
 
-	if (GTK_IS_ENTRY (p->focused_entry)) {
-		gtk_editable_copy_clipboard (GTK_EDITABLE (p->focused_entry));
-	} else {
-		/* happy happy joy joy, an EEntry. */
-		g_return_if_reached ();
-	}
+	attachment_bar = E_ATTACHMENT_BAR (composer->priv->attachment_bar);
+	return e_attachment_bar_get_download_count (attachment_bar);
 }
 
 static void
-menu_edit_paste_cb (BonoboUIComponent *uic, void *data, const char *path)
+drop_action (EMsgComposer *composer,
+             GdkDragContext *context,
+             guint32 action,
+             GtkSelectionData *selection,
+             guint info,
+             guint time,
+             gboolean html_dnd)
 {
-	EMsgComposer *composer = data;
+	char *tmp, *str, **urls;
+	CamelMimePart *mime_part;
+	CamelStream *stream;
+	CamelMimeMessage *msg;
+	char *content_type;
+	int i, success = FALSE, delete = FALSE;
 	EMsgComposerPrivate *p = composer->priv;
 
-	g_return_if_fail (p->focused_entry != NULL);
-
-	if (GTK_IS_ENTRY (p->focused_entry)) {
-		gtk_editable_paste_clipboard (GTK_EDITABLE (p->focused_entry));
-	} else {
-		/* happy happy joy joy, an EEntry. */
-		g_return_if_reached ();
-	}
-}
+	switch (info) {
+	case DND_TYPE_MESSAGE_RFC822:
+		d (printf ("dropping a message/rfc822\n"));
+		/* write the message (s) out to a CamelStream so we can use it */
+		stream = camel_stream_mem_new ();
+		camel_stream_write (stream, (const gchar *)selection->data, selection->length);
+		camel_stream_reset (stream);
 
-static void
-menu_send_options_cb (BonoboUIComponent *component, void *data, const char *path)
-{
-	EMEvent *e = em_event_peek();
-	EMEventTargetComposer  *target;
-	EMsgComposer *composer = data;
+		msg = camel_mime_message_new ();
+		if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)msg, stream) != -1) {
+			msg_composer_attach_message (composer, msg);
+			success = TRUE;
+			delete = action == GDK_ACTION_MOVE;
+		}
 
-	target = em_event_target_new_composer (e, composer, EM_EVENT_COMPOSER_SEND_OPTION);
-	e_msg_composer_set_send_options (composer, FALSE);
-	e_event_emit((EEvent *)e, "composer.selectsendoption", (EEventTarget *)target);
-	if (!composer->priv->send_invoked) {
-		e_error_run ((GtkWindow *)composer, "mail-composer:send-options-support", NULL);
-	}
-}
+		camel_object_unref (msg);
+		camel_object_unref (stream);
+		break;
+	case DND_TYPE_NETSCAPE_URL:
+		d (printf ("dropping a _NETSCAPE_URL\n"));
+		tmp = g_strndup ((const gchar *) selection->data, selection->length);
+		urls = g_strsplit (tmp, "\n", 2);
+		g_free (tmp);
 
-static void
-menu_edit_select_all_cb (BonoboUIComponent *uic, void *data, const char *path)
-{
-	EMsgComposer *composer = data;
-	EMsgComposerPrivate *p = composer->priv;
+		/* _NETSCAPE_URL is represented as "URI\nTITLE" */
+		handle_uri (composer, urls[0], html_dnd);
 
-	g_return_if_fail (p->focused_entry != NULL);
+		g_strfreev (urls);
+		success = TRUE;
+		break;
+	case DND_TYPE_TEXT_URI_LIST:
+		d (printf ("dropping a text/uri-list\n"));
+		tmp = g_strndup ((const gchar *) selection->data, selection->length);
+		urls = g_strsplit (tmp, "\n", 0);
+		g_free (tmp);
 
-	if (GTK_IS_ENTRY (p->focused_entry)) {
-		gtk_editable_set_position (GTK_EDITABLE (p->focused_entry), -1);
-		gtk_editable_select_region (GTK_EDITABLE (p->focused_entry), 0, -1);
-	} else {
-		/* happy happy joy joy, an EEntry. */
-		g_return_if_reached ();
-	}
-}
+		for (i = 0; urls[i] != NULL; i++) {
+			str = g_strstrip (urls[i]);
+			if (str[0] == '#' || str[0] == '\0')
+				continue;
 
-static void
-menu_edit_delete_all_cb (BonoboUIComponent *uic, void *data, const char *path)
-{
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
+			handle_uri (composer, str, html_dnd);
+		}
 
-	CORBA_exception_init (&ev);
+		g_strfreev (urls);
+		success = TRUE;
+		break;
+	case DND_TYPE_TEXT_VCARD:
+	case DND_TYPE_TEXT_CALENDAR:
+		content_type = gdk_atom_name (selection->type);
+		d (printf ("dropping a %s\n", content_type));
 
-	GNOME_GtkHTML_Editor_Engine_undoBegin (p->eeditor_engine, "Delete all but signature", "Undelete all", &ev);
-	GNOME_GtkHTML_Editor_Engine_freeze (p->eeditor_engine, &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "disable-selection", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "text-default-color", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "bold-off", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "underline-off", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "strikeout-off", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "select-all", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "delete", &ev);
-	GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "signature", "0", &ev);
-	GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "orig", "0", &ev);
-	e_msg_composer_show_sig_file (composer);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "style-normal", &ev);
-	GNOME_GtkHTML_Editor_Engine_thaw (p->eeditor_engine, &ev);
-	GNOME_GtkHTML_Editor_Engine_undoEnd (p->eeditor_engine, &ev);
+		mime_part = camel_mime_part_new ();
+		camel_mime_part_set_content (mime_part, (const gchar *)selection->data, selection->length, content_type);
+		camel_mime_part_set_disposition (mime_part, "inline");
 
-	CORBA_exception_free (&ev);
-	/* printf ("delete all\n"); */
-}
+		e_attachment_bar_attach_mime_part (E_ATTACHMENT_BAR (p->attachment_bar), mime_part);
 
-static void
-menu_format_html_cb (BonoboUIComponent           *component,
-		     const char                  *path,
-		     Bonobo_UIComponent_EventType type,
-		     const char                  *state,
-		     gpointer                     user_data)
+		camel_object_unref (mime_part);
+		g_free (content_type);
 
-{
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+		success = TRUE;
+		break;
+	case DND_TYPE_X_UID_LIST: {
+		GPtrArray *uids;
+		char *inptr, *inend;
+		CamelFolder *folder;
+		CamelException ex = CAMEL_EXCEPTION_INITIALISER;
 
-	e_msg_composer_set_send_html (E_MSG_COMPOSER (user_data), atoi (state));
-}
+		/* NB: This all runs synchronously, could be very slow/hang/block the ui */
 
-static void
-menu_security_pgp_sign_cb (BonoboUIComponent           *component,
-			   const char                  *path,
-			   Bonobo_UIComponent_EventType type,
-			   const char                  *state,
-			   gpointer                     composer)
+		uids = g_ptr_array_new ();
 
-{
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+		inptr = (char*)selection->data;
+		inend = (char*)(selection->data + selection->length);
+		while (inptr < inend) {
+			char *start = inptr;
 
-	e_msg_composer_set_pgp_sign (E_MSG_COMPOSER (composer), atoi (state));
-}
+			while (inptr < inend && *inptr)
+				inptr++;
 
-static void
-menu_security_pgp_encrypt_cb (BonoboUIComponent           *component,
-			      const char                  *path,
-			      Bonobo_UIComponent_EventType type,
-			      const char                  *state,
-			      gpointer                     composer)
+			if (start > (char *)selection->data)
+				g_ptr_array_add (uids, g_strndup (start, inptr-start));
 
-{
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+			inptr++;
+		}
 
-	e_msg_composer_set_pgp_encrypt (E_MSG_COMPOSER (composer), atoi (state));
-}
+		if (uids->len > 0) {
+			folder = mail_tool_uri_to_folder ((const gchar *)selection->data, 0, &ex);
+			if (folder) {
+				if (uids->len == 1) {
+					msg = camel_folder_get_message (folder, uids->pdata[0], &ex);
+					if (msg == NULL)
+						goto fail;
+					msg_composer_attach_message (composer, msg);
+				} else {
+					CamelMultipart *mp = camel_multipart_new ();
+					char *desc;
 
-static void
-menu_security_smime_sign_cb (BonoboUIComponent           *component,
-			     const char                  *path,
-			     Bonobo_UIComponent_EventType type,
-			     const char                  *state,
-			     gpointer                     composer)
+					camel_data_wrapper_set_mime_type ((CamelDataWrapper *)mp, "multipart/digest");
+					camel_multipart_set_boundary (mp, NULL);
+					for (i=0;i<uids->len;i++) {
+						msg = camel_folder_get_message (folder, uids->pdata[i], &ex);
+						if (msg) {
+							mime_part = camel_mime_part_new ();
+							camel_mime_part_set_disposition (mime_part, "inline");
+							camel_medium_set_content_object ((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
+							camel_mime_part_set_content_type (mime_part, "message/rfc822");
+							camel_multipart_add_part (mp, mime_part);
+							camel_object_unref (mime_part);
+							camel_object_unref (msg);
+						} else {
+							camel_object_unref (mp);
+							goto fail;
+						}
+					}
+					mime_part = camel_mime_part_new ();
+					camel_medium_set_content_object ((CamelMedium *)mime_part, (CamelDataWrapper *)mp);
+					/* translators, this count will always be >1 */
+					desc = g_strdup_printf (ngettext ("Attached message", "%d attached messages", uids->len), uids->len);
+					camel_mime_part_set_description (mime_part, desc);
+					g_free (desc);
+					e_attachment_bar_attach_mime_part (E_ATTACHMENT_BAR(p->attachment_bar), mime_part);
+					camel_object_unref (mime_part);
+					camel_object_unref (mp);
+				}
+				success = TRUE;
+				delete = action == GDK_ACTION_MOVE;
+			fail:
+				if (camel_exception_is_set (&ex)) {
+					char *name;
 
-{
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+					camel_object_get (folder, NULL, CAMEL_FOLDER_NAME, &name, NULL);
+					e_error_run ((GtkWindow *)composer, "mail-composer:attach-nomessages",
+						    name?name:(char *)selection->data, camel_exception_get_description (&ex), NULL);
+					camel_object_free (folder, CAMEL_FOLDER_NAME, name);
+				}
+				camel_object_unref (folder);
+			} else {
+				e_error_run ((GtkWindow *)composer, "mail-composer:attach-nomessages",
+					    (const gchar*)selection->data, camel_exception_get_description (&ex), NULL);
+			}
 
-	e_msg_composer_set_smime_sign (E_MSG_COMPOSER (composer), atoi (state));
-}
+			camel_exception_clear (&ex);
+		}
 
-static void
-menu_security_smime_encrypt_cb (BonoboUIComponent           *component,
-				const char                  *path,
-				Bonobo_UIComponent_EventType type,
-				const char                  *state,
-				gpointer                     composer)
+		g_ptr_array_free (uids, TRUE);
 
-{
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+		break; }
+	default:
+		d (printf ("dropping an unknown\n"));
+		break;
+	}
 
-	e_msg_composer_set_smime_encrypt (E_MSG_COMPOSER (composer), atoi (state));
+	gtk_drag_finish (context, success, delete, time);
 }
 
-
 static void
-menu_view_from_cb (BonoboUIComponent           *component,
-		   const char                  *path,
-		   Bonobo_UIComponent_EventType type,
-		   const char                  *state,
-		   gpointer                     user_data)
+drop_popup_copy (EPopup *ep, EPopupItem *item, gpointer data)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	struct _drop_data *m = data;
 
-	e_msg_composer_set_view_from (E_MSG_COMPOSER (user_data), atoi (state));
+	drop_action (
+		m->composer, m->context, GDK_ACTION_COPY,
+		m->selection, m->info, m->time, FALSE);
 }
 
 static void
-menu_view_replyto_cb (BonoboUIComponent           *component,
-		      const char                  *path,
-		      Bonobo_UIComponent_EventType type,
-		      const char                  *state,
-		      gpointer                     user_data)
+drop_popup_move (EPopup *ep, EPopupItem *item, gpointer data)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	struct _drop_data *m = data;
 
-	e_msg_composer_set_view_replyto (E_MSG_COMPOSER (user_data), atoi (state));
+	drop_action (
+		m->composer, m->context, GDK_ACTION_MOVE,
+		m->selection, m->info, m->time, FALSE);
 }
 
 static void
-menu_view_to_cb (BonoboUIComponent           *component,
-		      const char                  *path,
-		      Bonobo_UIComponent_EventType type,
-		      const char                  *state,
-		      gpointer                     user_data)
+drop_popup_cancel (EPopup *ep, EPopupItem *item, gpointer data)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	struct _drop_data *m = data;
 
-	e_msg_composer_set_view_to (E_MSG_COMPOSER (user_data), atoi (state));
+	gtk_drag_finish (m->context, FALSE, FALSE, m->time);
 }
 
+static EPopupItem drop_popup_menu[] = {
+	{ E_POPUP_ITEM, "00.emc.02", N_("_Copy"), drop_popup_copy, NULL, "mail-copy", 0 },
+	{ E_POPUP_ITEM, "00.emc.03", N_("_Move"), drop_popup_move, NULL, "mail-move", 0 },
+	{ E_POPUP_BAR, "10.emc" },
+	{ E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), drop_popup_cancel, NULL, NULL, 0 },
+};
+
 static void
-menu_view_postto_cb (BonoboUIComponent           *component,
-		      const char                  *path,
-		      Bonobo_UIComponent_EventType type,
-		      const char                  *state,
-		      gpointer                     user_data)
+drop_popup_free (EPopup *ep, GSList *items, gpointer data)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	struct _drop_data *m = data;
+
+	g_slist_free (items);
 
-	e_msg_composer_set_view_postto (E_MSG_COMPOSER (user_data), atoi (state));
+	g_object_unref (m->context);
+	g_object_unref (m->composer);
+	g_free (m->selection->data);
+	g_free (m->selection);
+	g_free (m);
 }
 
 static void
-menu_view_cc_cb (BonoboUIComponent           *component,
-		 const char                  *path,
-		 Bonobo_UIComponent_EventType type,
-		 const char                  *state,
-		 gpointer                     user_data)
+msg_composer_notify_header_cb (EMsgComposer *composer)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	GtkhtmlEditor *editor;
 
-	e_msg_composer_set_view_cc (E_MSG_COMPOSER (user_data), atoi (state));
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, TRUE);
 }
 
-static void
-menu_view_bcc_cb (BonoboUIComponent           *component,
-		  const char                  *path,
-		  Bonobo_UIComponent_EventType type,
-		  const char                  *state,
-		  gpointer                     user_data)
+static GObject *
+msg_composer_constructor (GType type,
+                          guint n_construct_properties,
+                          GObjectConstructParam *construct_properties)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	GObject *object;
+	EMsgComposer *composer;
+	GtkToggleAction *action;
+	GConfClient *client;
+	GArray *array;
+	gboolean active;
+	guint binding_id;
+
+	/* Chain up to parent's constructor() method. */
+	object = G_OBJECT_CLASS (parent_class)->constructor (
+		type, n_construct_properties, construct_properties);
+
+	composer = E_MSG_COMPOSER (object);
+	client = gconf_client_get_default ();
+	array = composer->priv->gconf_bridge_binding_ids;
+
+	/* Restore Persistent State */
+
+	binding_id = gconf_bridge_bind_property (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_CURRENT_FOLDER_KEY,
+		G_OBJECT (composer), "current-folder");
+	g_array_append_val (array, binding_id);
+
+	binding_id = gconf_bridge_bind_property (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_VIEW_BCC_KEY,
+		G_OBJECT (ACTION (VIEW_BCC)), "active");
+	g_array_append_val (array, binding_id);
+
+	binding_id = gconf_bridge_bind_property (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_VIEW_CC_KEY,
+		G_OBJECT (ACTION (VIEW_CC)), "active");
+	g_array_append_val (array, binding_id);
+
+	binding_id = gconf_bridge_bind_property (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_VIEW_FROM_KEY,
+		G_OBJECT (ACTION (VIEW_FROM)), "active");
+	g_array_append_val (array, binding_id);
+
+	binding_id = gconf_bridge_bind_property (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_VIEW_POST_TO_KEY,
+		G_OBJECT (ACTION (VIEW_POST_TO)), "active");
+	g_array_append_val (array, binding_id);
+
+	binding_id = gconf_bridge_bind_property (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_VIEW_REPLY_TO_KEY,
+		G_OBJECT (ACTION (VIEW_REPLY_TO)), "active");
+	g_array_append_val (array, binding_id);
+
+	binding_id = gconf_bridge_bind_window (
+		gconf_bridge_get (),
+		COMPOSER_GCONF_WINDOW_PREFIX,
+		GTK_WINDOW (composer), TRUE, FALSE);
+	g_array_append_val (array, binding_id);
+
+	/* Honor User Preferences */
+
+	active = gconf_client_get_bool (
+		client, COMPOSER_GCONF_SEND_HTML_KEY, NULL);
+	gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (composer), active);
+
+	action = GTK_TOGGLE_ACTION (ACTION (REQUEST_READ_RECEIPT));
+	active = gconf_client_get_bool (
+		client, COMPOSER_GCONF_REQUEST_RECEIPT_KEY, NULL);
+	gtk_toggle_action_set_active (action, active);
+
+	gconf_client_add_dir (
+		client, COMPOSER_GCONF_PREFIX,
+		GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+	composer->priv->notify_id = gconf_client_notify_add (
+		client, COMPOSER_GCONF_PREFIX, (GConfClientNotifyFunc)
+		msg_composer_update_preferences, composer, NULL, NULL);
+	msg_composer_update_preferences (client, 0, NULL, composer);
 
-	e_msg_composer_set_view_bcc (E_MSG_COMPOSER (user_data), atoi (state));
+	g_object_unref (client);
+
+	return object;
 }
 
 static void
-menu_insert_receipt_cb (BonoboUIComponent           *component,
-			const char                  *path,
-			Bonobo_UIComponent_EventType type,
-			const char                  *state,
-			gpointer                     user_data)
+msg_composer_dispose (GObject *object)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	EMsgComposer *composer = E_MSG_COMPOSER (object);
+
+	e_composer_autosave_unregister (composer);
+	e_composer_private_dispose (composer);
 
-	e_msg_composer_set_request_receipt (E_MSG_COMPOSER (user_data), atoi (state));
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
-menu_insert_priority_cb (BonoboUIComponent           *component,
-			const char                  *path,
-			Bonobo_UIComponent_EventType type,
-			const char                  *state,
-			gpointer                     user_data)
+msg_composer_finalize (GObject *object)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	EMsgComposer *composer = E_MSG_COMPOSER (object);
 
-	e_msg_composer_set_priority (E_MSG_COMPOSER (user_data), atoi (state));
+	e_composer_private_finalize (composer);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static void
-menu_changed_charset_cb (BonoboUIComponent           *component,
-			 const char                  *path,
-			 Bonobo_UIComponent_EventType type,
-			 const char                  *state,
-			 gpointer                     user_data)
+msg_composer_destroy (GtkObject *object)
 {
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
+	EMsgComposer *composer = E_MSG_COMPOSER (object);
+
+	all_composers = g_slist_remove (all_composers, object);
 
-	if (atoi (state)) {
-		EMsgComposer *composer = E_MSG_COMPOSER (user_data);
-		EMsgComposerPrivate *p = composer->priv;
-		/* Charset menu names are "Charset-%s" where %s is the charset name */
-		g_free (p->charset);
-		p->charset = g_strdup (path + strlen ("Charset-"));
+#if 0 /* GTKHTML-EDITOR */
+	if (composer->priv->menu) {
+		e_menu_update_target ((EMenu *)composer->priv->menu, NULL);
+		g_object_unref (composer->priv->menu);
+		composer->priv->menu = NULL;
 	}
-}
+#endif
 
-
-static BonoboUIVerb verbs [] = {
+	if (composer->priv->address_dialog != NULL) {
+		gtk_widget_destroy (composer->priv->address_dialog);
+		composer->priv->address_dialog = NULL;
+	}
 
-	BONOBO_UI_VERB ("FileOpen", menu_file_open_cb),
-	BONOBO_UI_VERB ("FileSave", menu_file_save_cb),
-	BONOBO_UI_VERB ("FileSaveAs", menu_file_save_as_cb),
-	BONOBO_UI_VERB ("FileSaveDraft", menu_file_save_draft_cb),
-	BONOBO_UI_VERB ("FileClose", menu_file_close_cb),
-	BONOBO_UI_VERB ("Help", menu_help_cb),
-	BONOBO_UI_VERB ("FileAttach", menu_file_add_attachment_cb),
+	if (composer->priv->notify_id) {
+		GConfClient *client;
 
-	BONOBO_UI_VERB ("FileSend", menu_file_send_cb),
+		client = gconf_client_get_default ();
+		gconf_client_notify_remove (client, composer->priv->notify_id);
+		composer->priv->notify_id = 0;
+		g_object_unref (client);
+	}
 
-	BONOBO_UI_VERB ("DeleteAll", menu_edit_delete_all_cb),
-	BONOBO_UI_VERB ("InsertXSendOptions", menu_send_options_cb),
+	/* Chain up to parent's destroy() method. */
+	GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
 
-	BONOBO_UI_VERB_END
-};
+static void
+msg_composer_map (GtkWidget *widget)
+{
+	EComposerHeaderTable *table;
+	GtkWidget *input_widget;
+	const gchar *text;
 
-static EPixmap pixcache [] = {
-	E_PIXMAP ("/commands/DeleteAll", "edit-delete", E_ICON_SIZE_MENU),
-	E_PIXMAP ("/commands/FileAttach", "mail-attachment", E_ICON_SIZE_MENU),
-	E_PIXMAP ("/commands/FileClose", "window-close", E_ICON_SIZE_MENU),
-	E_PIXMAP ("/commands/FileOpen", "document-open", E_ICON_SIZE_MENU),
-	E_PIXMAP ("/commands/FileSave", "document-save", E_ICON_SIZE_MENU),
-	E_PIXMAP ("/commands/FileSaveAs", "document-save-as", E_ICON_SIZE_MENU),
-	E_PIXMAP ("/commands/FileSend", "mail-send", E_ICON_SIZE_MENU),
-
-	E_PIXMAP ("/Toolbar/FileSend", "mail-send", E_ICON_SIZE_LARGE_TOOLBAR),
-	E_PIXMAP ("/Toolbar/FileSaveDraft", "document-save", E_ICON_SIZE_LARGE_TOOLBAR) ,
-	E_PIXMAP ("/Toolbar/FileAttach", "mail-attachment", E_ICON_SIZE_LARGE_TOOLBAR),
+	/* Chain up to parent's map() method. */
+	GTK_WIDGET_CLASS (parent_class)->map (widget);
 
-	E_PIXMAP_END
-};
+	table = e_msg_composer_get_header_table (E_MSG_COMPOSER (widget));
+
+	/* If the 'To' field is empty, focus it. */
+	input_widget =
+		e_composer_header_table_get_header (
+		table, E_COMPOSER_HEADER_TO)->input_widget;
+	text = gtk_entry_get_text (GTK_ENTRY (input_widget));
+	if (text == NULL || *text == '\0') {
+		gtk_widget_grab_focus (input_widget);
+		return;
+	}
+
+	/* If not, check the 'Subject' field. */
+	input_widget =
+		e_composer_header_table_get_header (
+		table, E_COMPOSER_HEADER_SUBJECT)->input_widget;
+	text = gtk_entry_get_text (GTK_ENTRY (input_widget));
+	if (text == NULL || *text == '\0') {
+		gtk_widget_grab_focus (input_widget);
+		return;
+	}
 
+	/* Jump to the editor as a last resort. */
+	gtkhtml_editor_run_command (GTKHTML_EDITOR (widget), "grab-focus");
+}
 
-static void
-setup_ui (EMsgComposer *composer)
+static gint
+msg_composer_delete_event (GtkWidget *widget,
+	                   GdkEventAny *event)
 {
-	EMMenuTargetWidget *target;
-	EMsgComposerPrivate *p = composer->priv;
-	BonoboUIContainer *container;
-	gboolean hide_smime;
-	char *charset;
-	char *xmlfile;
-
-	container = bonobo_window_get_ui_container (BONOBO_WINDOW (composer));
-
-	p->uic = bonobo_ui_component_new_default ();
-	/* FIXME: handle bonobo exceptions */
-	bonobo_ui_component_set_container (p->uic, bonobo_object_corba_objref (BONOBO_OBJECT (container)), NULL);
-
-	bonobo_ui_component_add_verb_list_with_data (p->uic, verbs, composer);
-
-	bonobo_ui_component_freeze (p->uic, NULL);
-
-	xmlfile = g_build_filename (EVOLUTION_UIDIR, "evolution-message-composer.xml", NULL);
-	bonobo_ui_util_set_ui (p->uic, PREFIX,
-			       xmlfile,
-			       "evolution-message-composer", NULL);
-	g_free (xmlfile);
-
-	e_pixmaps_update (p->uic, pixcache);
-
-	/* Populate the Charset Encoding menu and default it to whatever the user
-	   chose as his default charset in the mailer */
-	charset = composer_get_default_charset_setting ();
-	e_charset_picker_bonobo_ui_populate (p->uic, "/menu/Edit/EncodingPlaceholder",
-					     charset,
-					     menu_changed_charset_cb,
-					     composer);
-	g_free (charset);
-
-	/* Format -> HTML */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/FormatHtml",
-		"state", p->send_html ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "FormatHtml",
-		menu_format_html_cb, composer);
-
-	/* View/From */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/ViewFrom",
-		"state", p->view_from ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "ViewFrom",
-		menu_view_from_cb, composer);
-
-	/* View/ReplyTo */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/ViewReplyTo",
-		"state", p->view_replyto ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "ViewReplyTo",
-		menu_view_replyto_cb, composer);
-
-	/* View/To */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/ViewTo",
-		"state", p->view_to ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "ViewTo",
-		menu_view_to_cb, composer);
-
-	/* View/PostTo */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/ViewPostTo",
-		"state", p->view_postto ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "ViewPostTo",
-		menu_view_postto_cb, composer);
-
-	/* View/CC */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/ViewCC",
-		"state", p->view_cc ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "ViewCC",
-		menu_view_cc_cb, composer);
-
-	/* View/BCC */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/ViewBCC",
-		"state", p->view_bcc ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "ViewBCC",
-		menu_view_bcc_cb, composer);
-
-	/* Insert/Request Receipt */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/RequestReceipt",
-		"state", p->request_receipt ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "RequestReceipt",
-		menu_insert_receipt_cb, composer);
-
-	/* Insert/Exchange Send Options */
-/*	bonobo_ui_component_set_prop (
-		p->uic, "/commands/XSendOptions",
-		"state", "1", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "XSendOptions",
-		menu_send_options_cb, composer);*/
-
-	/* Insert/Set Priority*/
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SetPriority",
-		"state", p->set_priority? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (
-		p->uic, "SetPriority",
-		menu_insert_priority_cb, composer);
-
-	/* Security -> PGP Sign */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SecurityPGPSign",
-		"state", p->pgp_sign ? "1" : "0", NULL);
-
-	bonobo_ui_component_add_listener (
-		p->uic, "SecurityPGPSign",
-		menu_security_pgp_sign_cb, composer);
-
-	/* Security -> PGP Encrypt */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SecurityPGPEncrypt",
-		"state", p->pgp_encrypt ? "1" : "0", NULL);
-
-	bonobo_ui_component_add_listener (
-		p->uic, "SecurityPGPEncrypt",
-		menu_security_pgp_encrypt_cb, composer);
+	/* This is needed for the ACTION macro. */
+	EMsgComposer *composer = E_MSG_COMPOSER (widget);
 
-#if defined(HAVE_NSS) && defined(SMIME_SUPPORTED)
-	hide_smime = FALSE;
-#else
-	hide_smime = TRUE;
-#endif
+	gtk_action_activate (ACTION (CLOSE));
 
-	/* Security -> S/MIME Sign */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SecuritySMimeSign",
-		"state", p->smime_sign ? "1" : "0", NULL);
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SecuritySMimeSign",
-		"hidden", hide_smime ? "1" : "0", NULL);
-
-	bonobo_ui_component_add_listener (
-		p->uic, "SecuritySMimeSign",
-		menu_security_smime_sign_cb, composer);
-
-	/* Security -> S/MIME Encrypt */
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SecuritySMimeEncrypt",
-		"state", p->smime_encrypt ? "1" : "0", NULL);
-	bonobo_ui_component_set_prop (
-		p->uic, "/commands/SecuritySMimeEncrypt",
-		"hidden", hide_smime ? "1" : "0", NULL);
-
-	bonobo_ui_component_add_listener (
-		p->uic, "SecuritySMimeEncrypt",
-		menu_security_smime_encrypt_cb, composer);
-
-	bonobo_ui_component_thaw (p->uic, NULL);
-
-	/* Create the UIComponent for the non-control entries */
-
-	p->entry_uic = bonobo_ui_component_new_default ();
-
-	/* Setup main menu plugin mechanism */
-	target = em_menu_target_new_widget(p->menu, (GtkWidget *)composer);
-	e_menu_update_target((EMenu *)p->menu, target);
-	e_menu_activate((EMenu *)p->menu, p->uic, TRUE);
+	return TRUE;
 }
 
-
-/* Miscellaneous callbacks.  */
-
-static void
-attachment_bar_changed_cb (EAttachmentBar *bar,
-			   void *data)
+static gboolean
+msg_composer_key_press_event (GtkWidget *widget,
+                              GdkEventKey *event)
 {
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-	EMsgComposerPrivate *p = composer->priv;
+	EMsgComposer *composer = E_MSG_COMPOSER (widget);
+	GtkWidget *input_widget;
 
-	guint attachment_num = e_attachment_bar_get_num_attachments (
-		E_ATTACHMENT_BAR (p->attachment_bar));
-	if (attachment_num) {
-		gchar *num_text = g_strdup_printf (
-			ngettext ("<b>%d</b> Attachment", "<b>%d</b> Attachments", attachment_num),
-			attachment_num);
-		gtk_label_set_markup (GTK_LABEL (p->attachment_expander_num),
-				      num_text);
-		g_free (num_text);
+	input_widget =
+		e_composer_header_table_get_header (
+		e_msg_composer_get_header_table (composer),
+		E_COMPOSER_HEADER_SUBJECT)->input_widget;
 
-		gtk_widget_show (p->attachment_expander_icon);
-		show_attachments (composer, TRUE);
-	} else {
-		gtk_label_set_text (GTK_LABEL (p->attachment_expander_num), "");
-		gtk_widget_hide (p->attachment_expander_icon);
-		show_attachments (composer, FALSE);
+#ifdef HAVE_XFREE
+	if (event->keyval == XF86XK_Send) {
+		g_signal_emit (G_OBJECT (composer), signals[SEND], 0);
+		return TRUE;
+	}
+#endif /* HAVE_XFREE */
+
+	if (event->keyval == GDK_Escape) {
+		gtk_action_activate (ACTION (CLOSE));
+		return TRUE;
 	}
 
+	if (event->keyval == GDK_Tab && gtk_widget_is_focus (input_widget)) {
+		gtkhtml_editor_run_command (
+			GTKHTML_EDITOR (composer), "grab-focus");
+		return TRUE;
+	}
 
-	/* Mark the composer as changed so it prompts about unsaved
-	   changes on close */
-	e_msg_composer_set_changed (composer);
+	/* Chain up to parent's key_press_event() method. */
+	return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
 }
-static void
-attachment_expander_activate_cb (EExpander *expander,
-				void      *data)
-{
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-	gboolean show = e_expander_get_expanded (expander);
 
-	/* Update the expander label */
-	if (show)
-		gtk_label_set_text_with_mnemonic (GTK_LABEL (composer->priv->attachment_expander_label),
-		_("Hide _Attachment Bar"));
-	else
-		gtk_label_set_text_with_mnemonic (GTK_LABEL (composer->priv->attachment_expander_label),
-		_("Show _Attachment Bar"));
- }
-static void
-subject_changed_cb (EMsgComposerHdrs *hdrs,
-		    gchar *subject,
-		    void *data)
+static gboolean
+msg_composer_drag_motion (GtkWidget *widget,
+                          GdkDragContext *context,
+                          gint x,
+                          gint y,
+                          guint time)
 {
-	EMsgComposer *composer;
+	GList *targets;
+	GdkDragAction actions = 0;
+	GdkDragAction chosen_action;
 
-	composer = E_MSG_COMPOSER (data);
+	targets = context->targets;
+	while (targets != NULL) {
+		gint ii;
+
+		for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++)
+			if (targets->data == (gpointer) drag_info[ii].atom)
+				actions |= drag_info[ii].actions;
 
-	gtk_window_set_title (GTK_WINDOW (composer), subject[0] ? subject : _("Compose Message"));
-}
+		targets = g_list_next (targets);
+	}
 
-static void
-hdrs_changed_cb (EMsgComposerHdrs *hdrs,
-		 void *data)
-{
-	EMsgComposer *composer;
+	actions &= context->actions;
+	chosen_action = context->suggested_action;
 
-	composer = E_MSG_COMPOSER (data);
+	/* we default to copy */
+	if (chosen_action == GDK_ACTION_ASK &&
+		(actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) !=
+		(GDK_ACTION_MOVE|GDK_ACTION_COPY))
+		chosen_action = GDK_ACTION_COPY;
 
-	/* Mark the composer as changed so it prompts about unsaved changes on close */
-	e_msg_composer_set_changed (composer);
-}
+	gdk_drag_status (context, chosen_action, time);
 
-enum {
-	UPDATE_AUTO_CC,
-	UPDATE_AUTO_BCC,
-};
+	return (chosen_action != 0);
+}
 
 static void
-update_auto_recipients (EMsgComposerHdrs *hdrs, int mode, const char *auto_addrs)
+msg_composer_drag_data_received (GtkWidget *widget,
+                                 GdkDragContext *context,
+                                 gint x,
+                                 gint y,
+                                 GtkSelectionData *selection,
+                                 guint info,
+                                 guint time)
 {
-	EDestination *dest, **destv = NULL;
-	CamelInternetAddress *iaddr;
-	GList *list, *tail, *node;
-	int i, n = 0;
-
-	tail = list = NULL;
+	EMsgComposer *composer;
 
-	if (auto_addrs) {
-		iaddr = camel_internet_address_new ();
-		if (camel_address_decode (CAMEL_ADDRESS (iaddr), auto_addrs) != -1) {
-			for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
-				const char *name, *addr;
+	/* Widget may be EMsgComposer or GtkHTML. */
+	composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget));
 
-				if (!camel_internet_address_get (iaddr, i, &name, &addr))
-					continue;
+	if (selection->data == NULL)
+		return;
 
-				dest = e_destination_new ();
-				e_destination_set_auto_recipient (dest, TRUE);
+	if (selection->length == -1)
+		return;
 
-				if (name)
-					e_destination_set_name (dest, name);
+	if (context->action == GDK_ACTION_ASK) {
+		EMPopup *emp;
+		GSList *menus = NULL;
+		GtkMenu *menu;
+		gint ii;
+		struct _drop_data *m;
 
-				if (addr)
-					e_destination_set_email (dest, addr);
+		m = g_malloc0(sizeof (*m));
+		m->context = g_object_ref (context);
+		m->composer = g_object_ref (composer);
+		m->action = context->action;
+		m->info = info;
+		m->time = time;
+		m->selection = g_malloc0(sizeof (*m->selection));
+		m->selection->data = g_malloc (selection->length);
+		memcpy (m->selection->data, selection->data, selection->length);
+		m->selection->length = selection->length;
 
-				node = g_list_alloc ();
-				node->data = dest;
-				node->next = NULL;
-
-				if (tail) {
-					node->prev = tail;
-					tail->next = node;
-				} else {
-					node->prev = NULL;
-					list = node;
-				}
+		emp = em_popup_new ("org.gnome.evolution.mail.composer.popup.drop");
+		for (ii = 0; ii < G_N_ELEMENTS (drop_popup_menu); ii++)
+			menus = g_slist_append (menus, &drop_popup_menu[ii]);
+
+		e_popup_add_items ((EPopup *)emp, menus, NULL, drop_popup_free, m);
+		menu = e_popup_create_menu_once ((EPopup *)emp, NULL, 0);
+		gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, time);
+	} else {
+		drop_action (
+			composer, context, context->action, selection,
+			info, time, !GTK_WIDGET_TOPLEVEL (widget));
+	}
+}
 
-				tail = node;
-				n++;
-			}
-		}
+static void
+msg_composer_cut_clipboard (GtkhtmlEditor *editor)
+{
+	EMsgComposer *composer;
+	GtkWidget *parent;
+	GtkWidget *widget;
 
-		camel_object_unref (iaddr);
-	}
+	composer = E_MSG_COMPOSER (editor);
+	widget = gtk_window_get_focus (GTK_WINDOW (editor));
+	parent = gtk_widget_get_parent (widget);
 
-	switch (mode) {
-	case UPDATE_AUTO_CC:
-		destv = e_msg_composer_hdrs_get_cc (hdrs);
-		break;
-	case UPDATE_AUTO_BCC:
-		destv = e_msg_composer_hdrs_get_bcc (hdrs);
-		break;
-	default:
-		g_return_if_reached ();
+	if (parent == composer->priv->header_table) {
+		gtk_editable_cut_clipboard (GTK_EDITABLE (widget));
+		return;
 	}
 
-	if (destv) {
-		for (i = 0; destv[i]; i++) {
-			if (!e_destination_is_auto_recipient (destv[i])) {
-				node = g_list_alloc ();
-				node->data = e_destination_copy (destv[i]);
-				node->next = NULL;
-
-				if (tail) {
-					node->prev = tail;
-					tail->next = node;
-				} else {
-					node->prev = NULL;
-					list = node;
-				}
-
-				tail = node;
-				n++;
-			}
-		}
+	/* Chain up to parent's cut_clipboard() method. */
+	GTKHTML_EDITOR_CLASS (parent_class)->cut_clipboard (editor);
+}
 
-		e_destination_freev (destv);
-	}
+static void
+msg_composer_copy_clipboard (GtkhtmlEditor *editor)
+{
+	EMsgComposer *composer;
+	GtkWidget *parent;
+	GtkWidget *widget;
 
-	destv = destination_list_to_vector_sized (list, n);
-	g_list_free (list);
+	composer = E_MSG_COMPOSER (editor);
+	widget = gtk_window_get_focus (GTK_WINDOW (editor));
+	parent = gtk_widget_get_parent (widget);
 
-	switch (mode) {
-	case UPDATE_AUTO_CC:
-		e_msg_composer_hdrs_set_cc (hdrs, destv);
-		break;
-	case UPDATE_AUTO_BCC:
-		e_msg_composer_hdrs_set_bcc (hdrs, destv);
-		break;
-	default:
-		g_return_if_reached ();
+	if (parent == composer->priv->header_table) {
+		gtk_editable_copy_clipboard (GTK_EDITABLE (widget));
+		return;
 	}
 
-	e_destination_freev (destv);
+	/* Chain up to parent's copy_clipboard() method. */
+	GTKHTML_EDITOR_CLASS (parent_class)->copy_clipboard (editor);
 }
 
 static void
-from_changed_cb (EMsgComposerHdrs *hdrs, void *data)
+msg_composer_paste_clipboard (GtkhtmlEditor *editor)
 {
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-	EMsgComposerPrivate *p = composer->priv;
-	EAccount *account;
+	EMsgComposer *composer;
+	GtkWidget *parent;
+	GtkWidget *widget;
 
-	account = e_msg_composer_hdrs_get_from_account (hdrs);
+	composer = E_MSG_COMPOSER (editor);
+	widget = gtk_window_get_focus (GTK_WINDOW (editor));
+	parent = gtk_widget_get_parent (widget);
 
-	if (account) {
-		e_msg_composer_set_pgp_sign (composer,
-					     account->pgp_always_sign &&
-					     (!account->pgp_no_imip_sign || !p->mime_type ||
-					      g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) != 0));
-		e_msg_composer_set_smime_sign (composer, account->smime_sign_default);
-		e_msg_composer_set_smime_encrypt (composer, account->smime_encrypt_default);
-		update_auto_recipients (hdrs, UPDATE_AUTO_CC, account->always_cc ? account->cc_addrs : NULL);
-		update_auto_recipients (hdrs, UPDATE_AUTO_BCC, account->always_bcc ? account->bcc_addrs : NULL);
-	} else {
-		update_auto_recipients (hdrs, UPDATE_AUTO_CC, NULL);
-		update_auto_recipients (hdrs, UPDATE_AUTO_BCC, NULL);
+	if (parent == composer->priv->header_table) {
+		gtk_editable_paste_clipboard (GTK_EDITABLE (widget));
+		return;
 	}
 
-	set_editor_signature (composer);
-	e_msg_composer_show_sig_file (composer);
+	/* Chain up to parent's paste_clipboard() method. */
+	GTKHTML_EDITOR_CLASS (parent_class)->paste_clipboard (editor);
 }
 
-
-/* GObject methods.  */
-
 static void
-composer_finalise (GObject *object)
+msg_composer_select_all (GtkhtmlEditor *editor)
 {
-	EMsgComposer *composer = E_MSG_COMPOSER (object);
-	EMsgComposerPrivate *p = composer->priv;
-
-	if (p->extra_hdr_names) {
-		int i;
-
-		for (i = 0; i < p->extra_hdr_names->len; i++) {
-			g_free (p->extra_hdr_names->pdata[i]);
-			g_free (p->extra_hdr_values->pdata[i]);
-		}
-		g_ptr_array_free (p->extra_hdr_names, TRUE);
-		g_ptr_array_free (p->extra_hdr_values, TRUE);
-	}
+	EMsgComposer *composer;
+	GtkWidget *parent;
+	GtkWidget *widget;
 
-	g_hash_table_destroy (p->inline_images);
-	g_hash_table_destroy (p->inline_images_by_url);
+	composer = E_MSG_COMPOSER (editor);
+	widget = gtk_window_get_focus (GTK_WINDOW (editor));
+	parent = gtk_widget_get_parent (widget);
+
+	if (parent == composer->priv->header_table) {
+		gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+		gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
+	} else
+		/* Chain up to the parent's select_all() method. */
+		GTKHTML_EDITOR_CLASS (parent_class)->select_all (editor);
+}
 
-	g_free (p->charset);
-	g_free (p->mime_type);
-	g_free (p->mime_body);
+static void
+msg_composer_command_before (GtkhtmlEditor *editor,
+                             const gchar *command)
+{
+	EMsgComposer *composer;
+	const gchar *data;
 
-	if (p->redirect)
-		camel_object_unref (p->redirect);
+	composer = E_MSG_COMPOSER (editor);
 
+	if (strcmp (command, "insert-paragraph") != 0)
+		return;
 
-	g_free (p);
+	if (composer->priv->in_signature_insert)
+		return;
 
-	p = NULL;
-	composer->priv = NULL;
+	data = gtkhtml_editor_get_paragraph_data (editor, "orig");
+	if (data != NULL && *data == '1') {
+		gtkhtml_editor_run_command (editor, "text-default-color");
+		gtkhtml_editor_run_command (editor, "italic-off");
+		return;
+	};
 
-	if (G_OBJECT_CLASS (parent_class)->finalize != NULL)
-		(* G_OBJECT_CLASS (parent_class)->finalize) (object);
+	data = gtkhtml_editor_get_paragraph_data (editor, "signature");
+	if (data != NULL && *data == '1') {
+		gtkhtml_editor_run_command (editor, "text-default-color");
+		gtkhtml_editor_run_command (editor, "italic-off");
+	}
 }
 
 static void
-composer_dispose(GObject *object)
+msg_composer_command_after (GtkhtmlEditor *editor,
+                            const gchar *command)
 {
-	/* When destroy() is called, the contents of the window
-	 * (including the remote editor control) will already have
-	 * been destroyed, so we have to do this here.
-	 */
-	autosave_manager_unregister (am, E_MSG_COMPOSER (object));
+	EMsgComposer *composer;
+	const gchar *data;
 
-	if (G_OBJECT_CLASS (parent_class)->dispose != NULL)
-		(* G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
+	composer = E_MSG_COMPOSER (editor);
 
-/* GtkObject methods */
-static void
-destroy (GtkObject *object)
-{
-	EMsgComposer *composer = (EMsgComposer *)object;
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
+	if (strcmp (command, "insert-paragraph") != 0)
+		return;
 
-	CORBA_exception_init (&ev);
+	if (composer->priv->in_signature_insert)
+		return;
 
-	if (p->menu) {
-		e_menu_update_target((EMenu *)p->menu, NULL);
-		g_object_unref(p->menu);
-		p->menu = NULL;
-	}
+	gtkhtml_editor_run_command (editor, "italic-off");
 
-	if (p->load) {
-		gtk_widget_destroy(p->load);
-		p->load = NULL;
-	}
+	data = gtkhtml_editor_get_paragraph_data (editor, "orig");
+	if (data != NULL && *data == '1')
+		e_msg_composer_reply_indent (composer);
+	gtkhtml_editor_set_paragraph_data (editor, "orig", "0");
 
-	if (p->saveas) {
-		gtk_widget_destroy(p->saveas);
-		p->saveas = NULL;
-	}
+	data = gtkhtml_editor_get_paragraph_data (editor, "signature");
+	if (data == NULL || *data != '1')
+		return;
 
-	if (p->uic) {
-		bonobo_object_unref (BONOBO_OBJECT (p->uic));
-		p->uic = NULL;
-	}
+	/* Clear the signature. */
+	if (gtkhtml_editor_is_paragraph_empty (editor))
+		gtkhtml_editor_set_paragraph_data (editor, "signature" ,"0");
 
-	if (p->entry_uic) {
-		bonobo_object_unref (BONOBO_OBJECT (p->entry_uic));
-		p->entry_uic = NULL;
-	}
+	else if (gtkhtml_editor_is_previous_paragraph_empty (editor) &&
+		gtkhtml_editor_run_command (editor, "cursor-backward")) {
 
-	/* FIXME?  I assume the Bonobo widget will get destroyed
-	   normally?  */
-	if (p->address_dialog != NULL) {
-		gtk_widget_destroy (p->address_dialog);
-		p->address_dialog = NULL;
-	}
-	if (p->hdrs != NULL) {
-		gtk_widget_destroy (p->hdrs);
-		p->hdrs = NULL;
+		gtkhtml_editor_set_paragraph_data (editor, "signature", "0");
+		gtkhtml_editor_run_command (editor, "cursor-forward");
 	}
 
-	if (p->notify_id) {
-		GConfClient *gconf = gconf_client_get_default ();
-		gconf_client_notify_remove (gconf, p->notify_id);
-		p->notify_id = 0;
-		g_object_unref (gconf);
-	}
+	gtkhtml_editor_run_command (editor, "text-default-color");
+	gtkhtml_editor_run_command (editor, "italic-off");
+}
 
-	if (p->persist_stream_interface != CORBA_OBJECT_NIL) {
-		Bonobo_Unknown_unref (p->persist_stream_interface, &ev);
-		CORBA_Object_release (p->persist_stream_interface, &ev);
-		p->persist_stream_interface = CORBA_OBJECT_NIL;
-	}
+static gchar *
+msg_composer_image_uri (GtkhtmlEditor *editor,
+                        const gchar *uri)
+{
+	EMsgComposer *composer;
+	GHashTable *hash_table;
+	CamelMimePart *part;
+	const gchar *cid;
 
-	if (p->persist_file_interface != CORBA_OBJECT_NIL) {
-		Bonobo_Unknown_unref (p->persist_file_interface, &ev);
-		CORBA_Object_release (p->persist_file_interface, &ev);
-		p->persist_file_interface = CORBA_OBJECT_NIL;
-	}
+	composer = E_MSG_COMPOSER (editor);
 
-	if (p->eeditor_engine != CORBA_OBJECT_NIL) {
-		Bonobo_Unknown_unref (p->eeditor_engine, &ev);
-		CORBA_Object_release (p->eeditor_engine, &ev);
-		p->eeditor_engine = CORBA_OBJECT_NIL;
-	}
+	hash_table = composer->priv->inline_images_by_url;
+	part = g_hash_table_lookup (hash_table, uri);
 
-	CORBA_exception_free (&ev);
+	if (part == NULL && g_str_has_prefix (uri, "file:"))
+		part = e_msg_composer_add_inline_image_from_file (
+			composer, uri + 5);
 
-	if (p->eeditor_listener) {
-		bonobo_object_unref (p->eeditor_listener);
-		p->eeditor_listener = NULL;
+	if (part == NULL && g_str_has_prefix (uri, "cid:")) {
+		hash_table = composer->priv->inline_images;
+		part = g_hash_table_lookup (hash_table, uri);
 	}
 
-	if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
-		(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+	if (part == NULL)
+		return NULL;
+
+	composer->priv->current_images =
+		g_list_prepend (composer->priv->current_images, part);
+
+	cid = camel_mime_part_get_content_id (part);
+	if (cid == NULL)
+		return NULL;
+
+	return g_strconcat ("cid:", cid, NULL);
 }
 
-
-/* show the help menu item of the composer */
 static void
-e_msg_composer_show_help (EMsgComposer *composer)
+msg_composer_link_clicked (GtkhtmlEditor *editor,
+                           const gchar *uri)
 {
 	GError *error = NULL;
 
-	gnome_help_display (
-		"evolution.xml", "usage-composer", &error);
-	if (error != NULL) {
+	if (uri == NULL || *uri == '\0')
+		return;
+
+	if (g_ascii_strncasecmp (uri, "mailto:";, 7) == 0)
+		return;
+
+	if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0)
+		return;
+
+	if (g_ascii_strncasecmp (uri, "cid:", 4) == 0)
+		return;
+
+	gnome_url_show (uri, &error);
+
+	if (error) {
 		g_warning ("%s", error->message);
 		g_error_free (error);
 	}
 }
 
+static void
+msg_composer_object_deleted (GtkhtmlEditor *editor)
+{
+	const gchar *data;
 
-/* GtkWidget methods.  */
+	if (!gtkhtml_editor_is_paragraph_empty (editor))
+		return;
 
-static int
-delete_event (GtkWidget *widget,
-	      GdkEventAny *event)
-{
-	do_exit (E_MSG_COMPOSER (widget));
+	data = gtkhtml_editor_get_paragraph_data (editor, "orig");
+	if (data != NULL && *data == '1') {
+		gtkhtml_editor_set_paragraph_data (editor, "orig", "0");
+		gtkhtml_editor_run_command (editor, "indent-zero");
+		gtkhtml_editor_run_command (editor, "style-normal");
+		gtkhtml_editor_run_command (editor, "text-default-color");
+		gtkhtml_editor_run_command (editor, "italic-off");
+		gtkhtml_editor_run_command (editor, "insert-paragraph");
+		gtkhtml_editor_run_command (editor, "delete-back");
+	}
 
-	return TRUE;
+	data = gtkhtml_editor_get_paragraph_data (editor, "signature");
+	if (data != NULL && *data == '1')
+		gtkhtml_editor_set_paragraph_data (editor, "signature", "0");
 }
 
 static void
-attach_message(EMsgComposer *composer, CamelMimeMessage *msg)
+msg_composer_uri_requested (GtkhtmlEditor *editor,
+                            const gchar *uri,
+                            GtkHTMLStream *stream)
 {
-	CamelMimePart *mime_part;
-	const char *subject;
-	EMsgComposerPrivate *p = composer->priv;
+	EMsgComposer *composer;
+	GHashTable *hash_table;
+	GByteArray *array;
+	CamelDataWrapper *wrapper;
+	CamelStream *camel_stream;
+	CamelMimePart *part;
+	GtkHTML *html;
 
-	mime_part = camel_mime_part_new();
-	camel_mime_part_set_disposition(mime_part, "inline");
-	subject = camel_mime_message_get_subject(msg);
-	if (subject) {
-		char *desc = g_strdup_printf(_("Attached message - %s"), subject);
+	/* XXX It's unfortunate we have to expose GtkHTML structs here.
+	 *     Maybe we could rework this to use a GOutputStream. */
 
-		camel_mime_part_set_description(mime_part, desc);
-		g_free(desc);
-	} else
-		camel_mime_part_set_description(mime_part, _("Attached message"));
+	composer = E_MSG_COMPOSER (editor);
+	html = gtkhtml_editor_get_html (editor);
 
-	camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
-	camel_mime_part_set_content_type(mime_part, "message/rfc822");
-	e_attachment_bar_attach_mime_part(E_ATTACHMENT_BAR(p->attachment_bar), mime_part);
-	camel_object_unref(mime_part);
-}
+	hash_table = composer->priv->inline_images_by_url;
+	part = g_hash_table_lookup (hash_table, uri);
 
-struct _drop_data {
-	EMsgComposer *composer;
+	if (part == NULL) {
+		hash_table = composer->priv->inline_images;
+		part = g_hash_table_lookup (hash_table, uri);
+	}
 
-	GdkDragContext *context;
-	/* Only selection->data and selection->length are valid */
-	GtkSelectionData *selection;
+	if (part == NULL) {
+		gtk_html_end (html, stream, GTK_HTML_STREAM_ERROR);
+		return;
+	}
 
-	guint32 action;
-	guint info;
-	guint time;
+	array = g_byte_array_new ();
+	camel_stream = camel_stream_mem_new_with_byte_array (array);
+	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
+	camel_data_wrapper_decode_to_stream (wrapper, camel_stream);
 
-	unsigned int move:1;
-	unsigned int moved:1;
-	unsigned int aborted:1;
-};
+	gtk_html_write (
+		gtkhtml_editor_get_html (editor), stream,
+		(gchar *) array->data, array->len);
 
-int
-e_msg_composer_get_remote_download_count (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	return e_attachment_bar_get_download_count
-				(E_ATTACHMENT_BAR (p->attachment_bar));
+	camel_object_unref (camel_stream);
+
+	gtk_html_end (html, stream, GTK_HTML_STREAM_OK);
 }
 
-static gchar *
-attachment_guess_mime_type (const char *file_name)
+static void
+msg_composer_class_init (EMsgComposerClass *class)
 {
-	GnomeVFSFileInfo *info;
-	GnomeVFSResult result;
-	gchar *type = NULL;
-
-	info = gnome_vfs_file_info_new ();
-	result = gnome_vfs_get_file_info (file_name, info,
-					  GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
-					  GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
-					  GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
-	if (result == GNOME_VFS_OK)
-		type = g_strdup (gnome_vfs_file_info_get_mime_type (info));
-
-	gnome_vfs_file_info_unref (info);
+	GObjectClass *object_class;
+	GtkObjectClass *gtk_object_class;
+	GtkWidgetClass *widget_class;
+	GtkhtmlEditorClass *editor_class;
+	gint ii;
 
-	return type;
+	for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++)
+		drag_info[ii].atom =
+			gdk_atom_intern (drag_info[ii].target, FALSE);
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (EMsgComposerPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructor = msg_composer_constructor;
+	object_class->dispose = msg_composer_dispose;
+	object_class->finalize = msg_composer_finalize;
+
+	gtk_object_class = GTK_OBJECT_CLASS (class);
+	gtk_object_class->destroy = msg_composer_destroy;
+
+	widget_class = GTK_WIDGET_CLASS (class);
+	widget_class->map = msg_composer_map;
+	widget_class->delete_event = msg_composer_delete_event;
+	widget_class->key_press_event = msg_composer_key_press_event;
+	widget_class->drag_motion = msg_composer_drag_motion;
+	widget_class->drag_data_received = msg_composer_drag_data_received;
+
+	editor_class = GTKHTML_EDITOR_CLASS (class);
+	editor_class->cut_clipboard = msg_composer_cut_clipboard;
+	editor_class->copy_clipboard = msg_composer_copy_clipboard;
+	editor_class->paste_clipboard = msg_composer_paste_clipboard;
+	editor_class->select_all = msg_composer_select_all;
+	editor_class->command_before = msg_composer_command_before;
+	editor_class->command_after = msg_composer_command_after;
+	editor_class->image_uri = msg_composer_image_uri;
+	editor_class->link_clicked = msg_composer_link_clicked;
+	editor_class->object_deleted = msg_composer_object_deleted;
+	editor_class->uri_requested = msg_composer_uri_requested;
+
+	signals[SEND] = g_signal_new (
+		"send",
+		E_TYPE_MSG_COMPOSER,
+		G_SIGNAL_RUN_LAST,
+		0, NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[SAVE_DRAFT] = g_signal_new (
+		"save-draft",
+		E_TYPE_MSG_COMPOSER,
+		G_SIGNAL_RUN_LAST,
+		0, NULL, NULL,
+		g_cclosure_marshal_VOID__BOOLEAN,
+		G_TYPE_NONE, 1,
+		G_TYPE_BOOLEAN);
 }
 
 static void
-drop_action(EMsgComposer *composer, GdkDragContext *context, guint32 action, GtkSelectionData *selection, guint info, guint time, gboolean html_dnd)
+msg_composer_init (EMsgComposer *composer)
 {
-	char *tmp, *str, **urls;
-	CamelMimePart *mime_part;
-	CamelStream *stream;
-	CamelMimeMessage *msg;
-	char *content_type;
-	int i, success = FALSE, delete = FALSE;
-	EMsgComposerPrivate *p = composer->priv;
+	EComposerHeaderTable *table;
+#if 0 /* GTKHTML-EDITOR */
+	EMMenuTargetWidget *target;
+#endif
+	GtkHTML *html;
 
-	switch (info) {
-	case DND_TYPE_MESSAGE_RFC822:
-		d(printf ("dropping a message/rfc822\n"));
-		/* write the message(s) out to a CamelStream so we can use it */
-		stream = camel_stream_mem_new ();
-		camel_stream_write (stream, (const gchar *)selection->data, selection->length);
-		camel_stream_reset (stream);
+	composer->priv = E_MSG_COMPOSER_GET_PRIVATE (composer);
 
-		msg = camel_mime_message_new ();
-		if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) {
-			attach_message(composer, msg);
-			success = TRUE;
-			delete = action == GDK_ACTION_MOVE;
-		}
+	e_composer_private_init (composer);
 
-		camel_object_unref(msg);
-		camel_object_unref(stream);
-		break;
-	case DND_TYPE_NETSCAPE_URL:
-		d(printf ("dropping a _NETSCAPE_URL\n"));
-		tmp = g_strndup ((const gchar *) selection->data, selection->length);
-		urls = g_strsplit (tmp, "\n", 2);
-		g_free (tmp);
+	all_composers = g_slist_prepend (all_composers, composer);
+	html = gtkhtml_editor_get_html (GTKHTML_EDITOR (composer));
+	table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table);
 
-		/* _NETSCAPE_URL is represented as "URI\nTITLE" */
-		handle_uri (composer, urls[0], html_dnd);
+	gtk_window_set_title (GTK_WINDOW (composer), _("Compose Message"));
+	gtk_window_set_icon_name (GTK_WINDOW (composer), "mail-message-new");
 
-		g_strfreev (urls);
-		success = TRUE;
-		break;
-	case DND_TYPE_TEXT_URI_LIST:
-		d(printf ("dropping a text/uri-list\n"));
-		tmp = g_strndup ((const gchar *) selection->data, selection->length);
-		urls = g_strsplit (tmp, "\n", 0);
-		g_free (tmp);
-
-		for (i = 0; urls[i] != NULL; i++) {
-			str = g_strstrip (urls[i]);
-			if (str[0] == '#' || str[0] == '\0')
-				continue;
-
-			handle_uri (composer, str, html_dnd);
-		}
-
-		g_strfreev (urls);
-		success = TRUE;
-		break;
-	case DND_TYPE_TEXT_VCARD:
-	case DND_TYPE_TEXT_CALENDAR:
-		content_type = gdk_atom_name (selection->type);
-		d(printf ("dropping a %s\n", content_type));
+	/* Drag-and-Drop Support */
 
-		mime_part = camel_mime_part_new ();
-		camel_mime_part_set_content (mime_part, (const gchar *)selection->data, selection->length, content_type);
-		camel_mime_part_set_disposition (mime_part, "inline");
+	gtk_drag_dest_set (
+		GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL,
+		drop_types, G_N_ELEMENTS (drop_types),
+		GDK_ACTION_COPY | GDK_ACTION_ASK | GDK_ACTION_MOVE);
 
-		e_attachment_bar_attach_mime_part (E_ATTACHMENT_BAR (p->attachment_bar), mime_part);
+	g_signal_connect (
+		html, "drag-data-received",
+		G_CALLBACK (msg_composer_drag_data_received), NULL);
 
-		camel_object_unref (mime_part);
-		g_free (content_type);
+	/* Plugin Support */
 
-		success = TRUE;
-		break;
-	case DND_TYPE_X_UID_LIST: {
-		GPtrArray *uids;
-		char *inptr, *inend;
-		CamelFolder *folder;
-		CamelException ex = CAMEL_EXCEPTION_INITIALISER;
+#if 0 /* GTKHTML-EDITOR */
+	/** @HookPoint-EMMenu: Main Mail Menu
+	 * @Id: org.gnome.evolution.mail.composer
+	 * @Class: org.gnome.evolution.mail.bonobomenu:1.0
+	 * @Target: EMMenuTargetWidget
+	 *
+	 * The main menu of the composer window.  The widget of the
+	 * target will point to the EMsgComposer object.
+	 */
+	composer->priv->menu = em_menu_new ("org.gnome.evolution.mail.composer");
+	target = em_menu_target_new_widget (p->menu, (GtkWidget *)composer);
+	e_menu_update_target ((EMenu *)p->menu, target);
+	e_menu_activate ((EMenu *)p->menu, p->uic, TRUE);
 
-		/* NB: This all runs synchronously, could be very slow/hang/block the ui */
+#endif
 
-		uids = g_ptr_array_new();
+	/* Configure Headers */
 
-		inptr = (char*)selection->data;
-		inend = (char*)(selection->data + selection->length);
-		while (inptr < inend) {
-			char *start = inptr;
+	e_composer_header_table_set_account_list (
+		table, mail_config_get_accounts ());
+	e_composer_header_table_set_signature_list (
+		table, mail_config_get_signatures ());
 
-			while (inptr < inend && *inptr)
-				inptr++;
+	g_signal_connect_swapped (
+		table, "notify::account",
+		G_CALLBACK (msg_composer_account_changed_cb), composer);
+	g_signal_connect_swapped (
+		table, "notify::destinations-bcc",
+		G_CALLBACK (msg_composer_notify_header_cb), composer);
+	g_signal_connect_swapped (
+		table, "notify::destinations-cc",
+		G_CALLBACK (msg_composer_notify_header_cb), composer);
+	g_signal_connect_swapped (
+		table, "notify::destinations-to",
+		G_CALLBACK (msg_composer_notify_header_cb), composer);
+	g_signal_connect_swapped (
+		table, "notify::reply-to",
+		G_CALLBACK (msg_composer_notify_header_cb), composer);
+	g_signal_connect_swapped (
+		table, "notify::signature",
+		G_CALLBACK (e_msg_composer_show_sig_file), composer);
+	g_signal_connect_swapped (
+		table, "notify::subject",
+		G_CALLBACK (msg_composer_subject_changed_cb), composer);
+	g_signal_connect_swapped (
+		table, "notify::subject",
+		G_CALLBACK (msg_composer_notify_header_cb), composer);
 
-			if (start > (char *)selection->data)
-				g_ptr_array_add(uids, g_strndup(start, inptr-start));
+	msg_composer_account_changed_cb (composer);
 
-			inptr++;
-		}
+	/* Attachment Bar */
 
-		if (uids->len > 0) {
-			folder = mail_tool_uri_to_folder((const gchar *)selection->data, 0, &ex);
-			if (folder) {
-				if (uids->len == 1) {
-					msg = camel_folder_get_message(folder, uids->pdata[0], &ex);
-					if (msg == NULL)
-						goto fail;
-					attach_message(composer, msg);
-				} else {
-					CamelMultipart *mp = camel_multipart_new();
-					char *desc;
+	g_signal_connect (
+		composer->priv->attachment_bar, "button_press_event",
+		G_CALLBACK (attachment_bar_button_press_event_cb), NULL);
+	g_signal_connect (
+		composer->priv->attachment_bar, "key_press_event",
+		G_CALLBACK (attachment_bar_key_press_event_cb), NULL);
+	g_signal_connect (
+		composer->priv->attachment_bar, "popup-menu",
+		G_CALLBACK (attachment_bar_popup_menu_cb), NULL);
+	g_signal_connect (
+		composer->priv->attachment_bar, "changed",
+		G_CALLBACK (attachment_bar_changed_cb), composer);
+	g_signal_connect_after (
+		composer->priv->attachment_expander, "notify::expanded",
+		G_CALLBACK (attachment_expander_notify_cb), composer);
 
-					camel_data_wrapper_set_mime_type((CamelDataWrapper *)mp, "multipart/digest");
-					camel_multipart_set_boundary(mp, NULL);
-					for (i=0;i<uids->len;i++) {
-						msg = camel_folder_get_message(folder, uids->pdata[i], &ex);
-						if (msg) {
-							mime_part = camel_mime_part_new();
-							camel_mime_part_set_disposition(mime_part, "inline");
-							camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)msg);
-							camel_mime_part_set_content_type(mime_part, "message/rfc822");
-							camel_multipart_add_part(mp, mime_part);
-							camel_object_unref(mime_part);
-							camel_object_unref(msg);
-						} else {
-							camel_object_unref(mp);
-							goto fail;
-						}
-					}
-					mime_part = camel_mime_part_new();
-					camel_medium_set_content_object((CamelMedium *)mime_part, (CamelDataWrapper *)mp);
-					/* translators, this count will always be >1 */
-					desc = g_strdup_printf(ngettext("Attached message", "%d attached messages", uids->len), uids->len);
-					camel_mime_part_set_description(mime_part, desc);
-					g_free(desc);
-					e_attachment_bar_attach_mime_part(E_ATTACHMENT_BAR(p->attachment_bar), mime_part);
-					camel_object_unref(mime_part);
-					camel_object_unref(mp);
-				}
-				success = TRUE;
-				delete = action == GDK_ACTION_MOVE;
-			fail:
-				if (camel_exception_is_set(&ex)) {
-					char *name;
+	e_composer_autosave_register (composer);
 
-					camel_object_get(folder, NULL, CAMEL_FOLDER_NAME, &name, NULL);
-					e_error_run((GtkWindow *)composer, "mail-composer:attach-nomessages",
-						    name?name:(char *)selection->data, camel_exception_get_description(&ex), NULL);
-					camel_object_free(folder, CAMEL_FOLDER_NAME, name);
-				}
-				camel_object_unref(folder);
-			} else {
-				e_error_run((GtkWindow *)composer, "mail-composer:attach-nomessages",
-					    (const gchar*)selection->data, camel_exception_get_description(&ex), NULL);
-			}
+	/* Initialization may have tripped the "changed" state. */
+	gtkhtml_editor_set_changed (GTKHTML_EDITOR (composer), FALSE);
+}
 
-			camel_exception_clear(&ex);
-		}
+GType
+e_msg_composer_get_type (void)
+{
+	static GType type = 0;
 
-		g_ptr_array_free(uids, TRUE);
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (EMsgComposerClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) msg_composer_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (EMsgComposer),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) msg_composer_init,
+			NULL   /* value_table */
+		};
 
-		break; }
-	default:
-		d(printf ("dropping an unknown\n"));
-		break;
+		type = g_type_register_static (
+			GTKHTML_TYPE_EDITOR, "EMsgComposer", &type_info, 0);
 	}
 
-	if (e_attachment_bar_get_num_attachments(E_ATTACHMENT_BAR(p->attachment_bar)))
-		show_attachments (composer, TRUE);
-
-	gtk_drag_finish(context, success, delete, time);
+	return type;
 }
 
-static void
-drop_popup_copy(EPopup *ep, EPopupItem *item, void *data)
-{
-	struct _drop_data *m = data;
-	drop_action(m->composer, m->context, GDK_ACTION_COPY, m->selection, m->info, m->time, FALSE);
-}
+/* Callbacks.  */
 
-static void
-drop_popup_move(EPopup *ep, EPopupItem *item, void *data)
+static EMsgComposer *
+create_composer (gint visible_mask)
 {
-	struct _drop_data *m = data;
-	drop_action(m->composer, m->context, GDK_ACTION_MOVE, m->selection, m->info, m->time, FALSE);
-}
+	EMsgComposer *composer;
+	EMsgComposerPrivate *p;
+	EComposerHeaderTable *table;
+	GtkToggleAction *action;
+	gboolean active;
 
-static void
-drop_popup_cancel(EPopup *ep, EPopupItem *item, void *data)
-{
-	struct _drop_data *m = data;
-	gtk_drag_finish(m->context, FALSE, FALSE, m->time);
-}
+	composer = g_object_new (E_TYPE_MSG_COMPOSER, NULL);
+	table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table);
+	p = composer->priv;
 
-static EPopupItem drop_popup_menu[] = {
-	{ E_POPUP_ITEM, "00.emc.02", N_("_Copy"), drop_popup_copy, NULL, "mail-copy", 0 },
-	{ E_POPUP_ITEM, "00.emc.03", N_("_Move"), drop_popup_move, NULL, "mail-move", 0 },
-	{ E_POPUP_BAR, "10.emc" },
-	{ E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), drop_popup_cancel, NULL, NULL, 0 },
-};
+	/* Configure View Menu */
 
-static void
-drop_popup_free(EPopup *ep, GSList *items, void *data)
-{
-	struct _drop_data *m = data;
+	/* If we're mailing, you cannot disable "To". */
+	action = GTK_TOGGLE_ACTION (ACTION (VIEW_TO));
+	active = visible_mask & E_MSG_COMPOSER_VISIBLE_TO;
+	gtk_action_set_sensitive (ACTION (VIEW_TO), active);
+	gtk_toggle_action_set_active (action, active);
+
+	/* Ditto for "Post-To". */
+	action = GTK_TOGGLE_ACTION (ACTION (VIEW_POST_TO));
+	active = visible_mask & E_MSG_COMPOSER_VISIBLE_POSTTO;
+	gtk_action_set_sensitive (ACTION (VIEW_POST_TO), active);
+	gtk_toggle_action_set_active (action, active);
+
+	/* Disable "Cc" if we're posting. */
+	if (!(visible_mask & E_MSG_COMPOSER_VISIBLE_CC)) {
+		action = GTK_TOGGLE_ACTION (ACTION (VIEW_CC));
+		gtk_toggle_action_set_active (action, FALSE);
+	}
+
+	/* Disable "Bcc" if we're posting. */
+	if (!(visible_mask & E_MSG_COMPOSER_VISIBLE_BCC)) {
+		action = GTK_TOGGLE_ACTION (ACTION (VIEW_BCC));
+		gtk_toggle_action_set_active (action, FALSE);
+	}
 
-	g_slist_free(items);
+	action = GTK_TOGGLE_ACTION (ACTION (VIEW_SUBJECT));
+	gtk_toggle_action_set_active (action, TRUE);
 
-	g_object_unref(m->context);
-	g_object_unref(m->composer);
-	g_free(m->selection->data);
-	g_free(m->selection);
-	g_free(m);
+	return composer;
 }
 
-static void
-drag_data_received (GtkWidget *w, GdkDragContext *context,
-		    int x, int y, GtkSelectionData *selection,
-		    guint info, guint time,
-		    EMsgComposer *composer)
+/**
+ * e_msg_composer_new_with_type:
+ *
+ * Create a new message composer widget. The type can be
+ * E_MSG_COMPOSER_MAIL, E_MSG_COMPOSER_POST or E_MSG_COMPOSER_MAIL_POST.
+ *
+ * Returns: A pointer to the newly created widget
+ **/
+
+EMsgComposer *
+e_msg_composer_new_with_type (int type)
 {
-	if (selection->data == NULL || selection->length == -1)
-		return;
+	EMsgComposer *composer;
+	gint visible_mask;
 
-	if (context->action == GDK_ACTION_ASK) {
-		EMPopup *emp;
-		GSList *menus = NULL;
-		GtkMenu *menu;
-		int i;
-		struct _drop_data *m;
+	switch (type) {
+		case E_MSG_COMPOSER_MAIL:
+			visible_mask = E_MSG_COMPOSER_VISIBLE_MASK_MAIL;
+			break;
 
-		m = g_malloc0(sizeof(*m));
-		m->context = context;
-		g_object_ref(context);
-		m->composer = composer;
-		g_object_ref(composer);
-		m->action = context->action;
-		m->info = info;
-		m->time = time;
-		m->selection = g_malloc0(sizeof(*m->selection));
-		m->selection->data = g_malloc(selection->length);
-		memcpy(m->selection->data, selection->data, selection->length);
-		m->selection->length = selection->length;
+		case E_MSG_COMPOSER_POST:
+			visible_mask = E_MSG_COMPOSER_VISIBLE_MASK_POST;
+			break;
 
-		emp = em_popup_new("org.gnome.evolution.mail.composer.popup.drop");
-		for (i=0;i<sizeof(drop_popup_menu)/sizeof(drop_popup_menu[0]);i++)
-			menus = g_slist_append(menus, &drop_popup_menu[i]);
-
-		e_popup_add_items((EPopup *)emp, menus, NULL, drop_popup_free, m);
-		menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0);
-		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, time);
-	} else {
-		drop_action(composer, context, context->action, selection, info, time, w != GTK_WIDGET (composer));
+		default:
+			visible_mask =
+				E_MSG_COMPOSER_VISIBLE_MASK_MAIL |
+				E_MSG_COMPOSER_VISIBLE_MASK_POST;
+			break;
 	}
+
+	composer = create_composer (visible_mask);
+
+	set_editor_text (composer, "", TRUE);
+
+	return composer;
 }
 
+/**
+ * e_msg_composer_new:
+ *
+ * Create a new message composer widget.
+ *
+ * Returns: A pointer to the newly created widget
+ **/
+EMsgComposer *
+e_msg_composer_new (void)
+{
+	return e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL);
+}
 
 static gboolean
-drag_motion(GObject *o, GdkDragContext *context, gint x, gint y, guint time, EMsgComposer *composer)
+is_special_header (const gchar *hdr_name)
 {
-	GList *targets;
-	GdkDragAction action, actions = 0;
+	/* Note: a header is a "special header" if it has any meaning:
+	   1. it's not a X-* header or
+	   2. it's an X-Evolution* header
+	*/
+	if (g_ascii_strncasecmp (hdr_name, "X-", 2))
+		return TRUE;
 
-	for (targets = context->targets; targets; targets = targets->next) {
-		int i;
+	if (!g_ascii_strncasecmp (hdr_name, "X-Evolution", 11))
+		return TRUE;
 
-		for (i=0;i<sizeof(drag_info)/sizeof(drag_info[0]);i++)
-			if (targets->data == (void *)drag_info[i].atom)
-				actions |= drag_info[i].actions;
-	}
+	/* we can keep all other X-* headers */
 
-	actions &= context->actions;
-	action = context->suggested_action;
-	/* we default to copy */
-	if (action == GDK_ACTION_ASK && (actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) != (GDK_ACTION_MOVE|GDK_ACTION_COPY))
-		action = GDK_ACTION_COPY;
+	return FALSE;
+}
 
-	gdk_drag_status(context, action, time);
+static void
+e_msg_composer_set_pending_body (EMsgComposer *composer,
+                                 gchar *text,
+                                 gssize length)
+{
+	g_object_set_data_full (
+		G_OBJECT (composer), "body:text",
+		text, (GDestroyNotify) g_free);
 
-	return action != 0;
+	g_object_set_data (
+		G_OBJECT (composer), "body:length",
+		GSIZE_TO_POINTER (length));
 }
 
 static void
-class_init (EMsgComposerClass *klass)
+e_msg_composer_flush_pending_body (EMsgComposer *composer)
 {
-	GtkObjectClass *object_class;
-	GtkWidgetClass *widget_class;
-	GObjectClass *gobject_class;
-	int i;
+	const gchar *body;
+	gpointer data;
+	gssize length;
+
+	body = g_object_get_data (G_OBJECT (composer), "body:text");
+	data = g_object_get_data (G_OBJECT (composer), "body:length");
+	length = GPOINTER_TO_SIZE (data);
 
-	for (i=0;i<sizeof(drag_info)/sizeof(drag_info[0]);i++)
-		drag_info[i].atom = gdk_atom_intern(drag_info[i].target, FALSE);
+	if (body != NULL)
+		set_editor_text (composer, body, FALSE);
 
-	gobject_class = G_OBJECT_CLASS(klass);
-	object_class = GTK_OBJECT_CLASS (klass);
-	widget_class = GTK_WIDGET_CLASS (klass);
+	g_object_set_data (G_OBJECT (composer), "body:text", NULL);
+}
 
-	gobject_class->finalize = composer_finalise;
-	gobject_class->dispose = composer_dispose;
-	object_class->destroy = destroy;
-	widget_class->delete_event = delete_event;
+static void
+add_attachments_handle_mime_part (EMsgComposer *composer,
+                                  CamelMimePart *mime_part,
+				  gboolean just_inlines,
+                                  gboolean related,
+                                  gint depth)
+{
+	CamelContentType *content_type;
+	CamelDataWrapper *wrapper;
 
-	parent_class = g_type_class_ref(bonobo_window_get_type ());
+	if (!mime_part)
+		return;
 
-	signals[SEND] =
-		g_signal_new ("send",
-			      E_TYPE_MSG_COMPOSER,
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EMsgComposerClass, send),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
+	content_type = camel_mime_part_get_content_type (mime_part);
+	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
 
-	signals[SAVE_DRAFT] =
-		g_signal_new ("save-draft",
-			      E_TYPE_MSG_COMPOSER,
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (EMsgComposerClass, save_draft),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__BOOLEAN,
-			      G_TYPE_NONE,
-			      1, G_TYPE_BOOLEAN);
+	if (CAMEL_IS_MULTIPART (wrapper)) {
+		/* another layer of multipartness... */
+		add_attachments_from_multipart (
+			composer, (CamelMultipart *) wrapper,
+			just_inlines, depth + 1);
+	} else if (just_inlines) {
+		if (camel_mime_part_get_content_id (mime_part) ||
+		    camel_mime_part_get_content_location (mime_part))
+			e_msg_composer_add_inline_image_from_mime_part (
+				composer, mime_part);
+	} else if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
+		/* do nothing */
+	} else if (related && camel_content_type_is (content_type, "image", "*")) {
+		e_msg_composer_add_inline_image_from_mime_part (composer, mime_part);
+	} else if (camel_content_type_is (content_type, "text", "*")) {
+		/* do nothing */
+	} else {
+		e_msg_composer_attach (composer, mime_part);
+	}
 }
 
 static void
-init (EMsgComposer *composer)
+add_attachments_from_multipart (EMsgComposer *composer,
+                                CamelMultipart *multipart,
+				gboolean just_inlines,
+                                gint depth)
 {
-	EMsgComposerPrivate *p = g_new0(EMsgComposerPrivate,1);
-	GHashTable *inline_images;
-	GHashTable *inline_images_by_url;
+	/* find appropriate message attachments to add to the composer */
+	CamelMimePart *mime_part;
+	gboolean related;
+	gint i, nparts;
 
-	inline_images = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) NULL);
+	related = camel_content_type_is (
+		CAMEL_DATA_WRAPPER (multipart)->mime_type,
+		"multipart", "related");
 
-	inline_images_by_url = g_hash_table_new_full (
-		g_str_hash, g_str_equal,
-		(GDestroyNotify) g_free,
-		(GDestroyNotify) camel_object_unref);
+	if (CAMEL_IS_MULTIPART_SIGNED (multipart)) {
+		mime_part = camel_multipart_get_part (
+			multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
+		add_attachments_handle_mime_part (
+			composer, mime_part, just_inlines, related, depth);
+	} else if (CAMEL_IS_MULTIPART_ENCRYPTED (multipart)) {
+		/* XXX What should we do in this case? */
+	} else {
+		nparts = camel_multipart_get_number (multipart);
 
-	p->uic                      = NULL;
+		for (i = 0; i < nparts; i++) {
+			mime_part = camel_multipart_get_part (multipart, i);
+			add_attachments_handle_mime_part (
+				composer, mime_part, just_inlines,
+				related, depth);
+		}
+	}
+}
 
-	p->hdrs                     = NULL;
-	p->extra_hdr_names          = g_ptr_array_new ();
-	p->extra_hdr_values         = g_ptr_array_new ();
+/**
+ * e_msg_composer_add_message_attachments:
+ * @composer: the composer to add the attachments to.
+ * @message: the source message to copy the attachments from.
+ * @just_inlines: whether to attach all attachments or just add
+ * inline images.
+ *
+ * Walk through all the mime parts in @message and add them to the composer
+ * specified in @composer.
+ */
+void
+e_msg_composer_add_message_attachments (EMsgComposer *composer,
+                                        CamelMimeMessage *message,
+					gboolean just_inlines)
+{
+	CamelDataWrapper *wrapper;
 
-	p->focused_entry            = NULL;
+	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (message));
+	if (!CAMEL_IS_MULTIPART (wrapper))
+		return;
 
-	p->eeditor                   = NULL;
+	add_attachments_from_multipart (
+		composer, (CamelMultipart *) wrapper, just_inlines, 0);
+}
 
-	p->address_dialog           = NULL;
+static void
+handle_multipart_signed (EMsgComposer *composer,
+                         CamelMultipart *multipart,
+                         gint depth)
+{
+	CamelContentType *content_type;
+	CamelDataWrapper *content;
+	CamelMimePart *mime_part;
+	GtkToggleAction *action;
 
-	p->attachment_bar           = NULL;
-	p->attachment_scrolled_window = NULL;
+	/* FIXME: make sure this isn't an s/mime signed part?? */
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+	gtk_toggle_action_set_active (action, TRUE);
 
-	p->persist_file_interface   = CORBA_OBJECT_NIL;
-	p->persist_stream_interface = CORBA_OBJECT_NIL;
+	mime_part = camel_multipart_get_part (
+		multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
 
-	p->eeditor_engine            = CORBA_OBJECT_NIL;
-	p->inline_images            = inline_images;
-	p->inline_images_by_url     = inline_images_by_url;
-	p->current_images           = NULL;
+	if (mime_part != NULL)
+		return;
 
-	p->attachment_bar_visible   = FALSE;
-	p->send_html                = FALSE;
-	p->pgp_sign                 = FALSE;
-	p->pgp_encrypt              = FALSE;
-	p->smime_sign               = FALSE;
-	p->smime_encrypt            = FALSE;
+	content_type = camel_mime_part_get_content_type (mime_part);
 
-	p->has_changed              = FALSE;
-	p->autosaved                = FALSE;
+	content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
 
-	p->redirect                 = NULL;
-	p->send_invoked		    = FALSE;
-	p->charset                  = NULL;
+	if (CAMEL_IS_MULTIPART (content)) {
+		multipart = CAMEL_MULTIPART (content);
 
-	p->enable_autosave          = TRUE;
-	p->autosave_file            = NULL;
-	p->autosave_fd              = -1;
+		/* Note: depth is preserved here because we're not
+		   counting multipart/signed as a multipart, instead
+		   we want to treat the content part as our mime part
+		   here. */
 
-	/** @HookPoint-EMMenu: Main Mail Menu
-	 * @Id: org.gnome.evolution.mail.composer
-	 * @Class: org.gnome.evolution.mail.bonobomenu:1.0
-	 * @Target: EMMenuTargetWidget
-	 *
-	 * The main menu of the composer window.  The widget of the
-	 * target will point to the EMsgComposer object.
-	 */
-	p->menu = em_menu_new("org.gnome.evolution.mail.composer");
-
-	composer->priv = p;
-}
-
-
-GtkType
-e_msg_composer_get_type (void)
-{
-	static GType type = 0;
-
-	if (type == 0) {
-		static const GTypeInfo info = {
-			sizeof (EMsgComposerClass),
-			NULL, NULL,
-			(GClassInitFunc) class_init,
-			NULL, NULL,
-			sizeof (EMsgComposer),
-			0,
-			(GInstanceInitFunc) init,
-		};
+		if (CAMEL_IS_MULTIPART_SIGNED (content)) {
+			/* handle the signed content and configure the composer to sign outgoing messages */
+			handle_multipart_signed (composer, multipart, depth);
+		} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
+			/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
+			handle_multipart_encrypted (composer, mime_part, depth);
+		} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
+			/* this contains the text/plain and text/html versions of the message body */
+			handle_multipart_alternative (composer, multipart, depth);
+		} else {
+			/* there must be attachments... */
+			handle_multipart (composer, multipart, depth);
+		}
+	} else if (camel_content_type_is (content_type, "text", "*")) {
+		gchar *html;
+		gssize length;
 
-		type = g_type_register_static (bonobo_window_get_type (), "EMsgComposer", &info, 0);
+		html = em_utils_part_to_html (mime_part, &length, NULL);
+		e_msg_composer_set_pending_body (composer, html, length);
+	} else {
+		e_msg_composer_attach (composer, mime_part);
 	}
-
-	return type;
 }
 
 static void
-e_msg_composer_load_config (EMsgComposer *composer, int visible_mask)
+handle_multipart_encrypted (EMsgComposer *composer,
+                            CamelMimePart *multipart,
+                            gint depth)
 {
-	GConfClient *gconf;
-	EMsgComposerPrivate *p = composer->priv;
+	CamelContentType *content_type;
+	CamelCipherContext *cipher;
+	CamelDataWrapper *content;
+	CamelMimePart *mime_part;
+	CamelException ex;
+	CamelCipherValidity *valid;
+	GtkToggleAction *action;
 
-	gconf = gconf_client_get_default ();
+	/* FIXME: make sure this is a PGP/MIME encrypted part?? */
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT));
+	gtk_toggle_action_set_active (action, TRUE);
 
-	p->view_from = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/From", NULL);
-	p->view_replyto = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/ReplyTo", NULL);
-	p->view_to = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/To", NULL);
-	p->view_postto = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/PostTo", NULL);
-	p->view_cc = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/Cc", NULL);
-	p->view_bcc = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/Bcc", NULL);
-	p->view_subject = gconf_client_get_bool (
-		gconf, "/apps/evolution/mail/composer/view/Subject", NULL);
-
-	/* if we're mailing, you cannot disable to so it should appear checked */
-	if (visible_mask & E_MSG_COMPOSER_VISIBLE_TO)
-		p->view_to = TRUE;
-	else
-		p->view_to = FALSE;
+	camel_exception_init (&ex);
+	cipher = mail_crypto_get_pgp_cipher_context (NULL);
+	mime_part = camel_mime_part_new ();
+	valid = camel_cipher_decrypt (cipher, multipart, mime_part, &ex);
+	camel_object_unref (cipher);
+	camel_exception_clear (&ex);
+	if (valid == NULL)
+		return;
+	camel_cipher_validity_free (valid);
 
-	/* ditto for post-to */
-	if (visible_mask & E_MSG_COMPOSER_VISIBLE_POSTTO)
-		p->view_postto = TRUE;
-	else
-		p->view_postto = FALSE;
+	content_type = camel_mime_part_get_content_type (mime_part);
 
-	/* we set these to false initially if we're posting */
-	if (!(visible_mask & E_MSG_COMPOSER_VISIBLE_CC))
-		p->view_cc = FALSE;
+	content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
 
-	if (!(visible_mask & E_MSG_COMPOSER_VISIBLE_BCC))
-		p->view_bcc = FALSE;
+	if (CAMEL_IS_MULTIPART (content)) {
+		CamelMultipart *content_multipart = CAMEL_MULTIPART (content);
 
-	g_object_unref (gconf);
-}
+		/* Note: depth is preserved here because we're not
+		   counting multipart/encrypted as a multipart, instead
+		   we want to treat the content part as our mime part
+		   here. */
 
-static int
-e_msg_composer_get_visible_flags (EMsgComposer *composer)
-{
-	int flags = 0;
-	EMsgComposerPrivate *p = composer->priv;
+		if (CAMEL_IS_MULTIPART_SIGNED (content)) {
+			/* handle the signed content and configure the composer to sign outgoing messages */
+			handle_multipart_signed (composer, content_multipart, depth);
+		} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
+			/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
+			handle_multipart_encrypted (composer, mime_part, depth);
+		} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
+			/* this contains the text/plain and text/html versions of the message body */
+			handle_multipart_alternative (composer, content_multipart, depth);
+		} else {
+			/* there must be attachments... */
+			handle_multipart (composer, content_multipart, depth);
+		}
+	} else if (camel_content_type_is (content_type, "text", "*")) {
+		gchar *html;
+		gssize length;
 
-	if (p->view_from)
-		flags |= E_MSG_COMPOSER_VISIBLE_FROM;
-	if (p->view_replyto)
-		flags |= E_MSG_COMPOSER_VISIBLE_REPLYTO;
-	if (p->view_to)
-		flags |= E_MSG_COMPOSER_VISIBLE_TO;
-	if (p->view_postto)
-		flags |= E_MSG_COMPOSER_VISIBLE_POSTTO;
-	if (p->view_cc)
-		flags |= E_MSG_COMPOSER_VISIBLE_CC;
-	if (p->view_bcc)
-		flags |= E_MSG_COMPOSER_VISIBLE_BCC;
-	if (p->view_subject)
-		flags |= E_MSG_COMPOSER_VISIBLE_SUBJECT;
+		html = em_utils_part_to_html (mime_part, &length, NULL);
+		e_msg_composer_set_pending_body (composer, html, length);
+	} else {
+		e_msg_composer_attach (composer, mime_part);
+	}
 
-	/*
-	 * Until we have a GUI way, lets make sure that
-	 * even if the user screws up, we will do the right
-	 * thing (screws up == edit the config file manually
-	 * and screw up).
-	 */
-	flags |= E_MSG_COMPOSER_VISIBLE_SUBJECT;
-	return flags;
+	camel_object_unref (mime_part);
 }
 
-
 static void
-map_default_cb (EMsgComposer *composer, gpointer user_data)
+handle_multipart_alternative (EMsgComposer *composer,
+                              CamelMultipart *multipart,
+                              gint depth)
 {
-	GtkWidget *widget;
-	CORBA_Environment ev;
-	const char *subject;
-	const char *text;
-	EMsgComposerPrivate *p = composer->priv;
+	/* Find the text/html part and set the composer body to it's contents */
+	CamelMimePart *text_part = NULL;
+	gint i, nparts;
+
+	nparts = camel_multipart_get_number (multipart);
 
-	/* If the 'To:' field is empty, focus it */
+	for (i = 0; i < nparts; i++) {
+		CamelContentType *content_type;
+		CamelDataWrapper *content;
+		CamelMimePart *mime_part;
 
-	widget = e_msg_composer_hdrs_get_to_entry (E_MSG_COMPOSER_HDRS (p->hdrs));
-	text = gtk_entry_get_text (GTK_ENTRY (widget));
+		mime_part = camel_multipart_get_part (multipart, i);
 
-	if (!text || text[0] == '\0') {
-		gtk_widget_grab_focus (widget);
+		if (!mime_part)
+			continue;
 
-		return;
-	}
+		content_type = camel_mime_part_get_content_type (mime_part);
+		content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
 
-	/* If not, check the subject field */
+		if (CAMEL_IS_MULTIPART (content)) {
+			CamelMultipart *mp;
 
-	subject = e_msg_composer_hdrs_get_subject (E_MSG_COMPOSER_HDRS (p->hdrs));
+			mp = CAMEL_MULTIPART (content);
 
-	if (!subject || subject[0] == '\0') {
-		widget = e_msg_composer_hdrs_get_subject_entry (E_MSG_COMPOSER_HDRS (p->hdrs));
-		gtk_widget_grab_focus (widget);
-		return;
+			if (CAMEL_IS_MULTIPART_SIGNED (content)) {
+				/* handle the signed content and configure the composer to sign outgoing messages */
+				handle_multipart_signed (composer, mp, depth + 1);
+			} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
+				/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
+				handle_multipart_encrypted (composer, mime_part, depth + 1);
+			} else {
+				/* depth doesn't matter so long as we don't pass 0 */
+				handle_multipart (composer, mp, depth + 1);
+			}
+		} else if (camel_content_type_is (content_type, "text", "html")) {
+			/* text/html is preferable, so once we find it we're done... */
+			text_part = mime_part;
+			break;
+		} else if (camel_content_type_is (content_type, "text", "*")) {
+			/* anyt text part not text/html is second rate so the first
+			   text part we find isn't necessarily the one we'll use. */
+			if (!text_part)
+				text_part = mime_part;
+		} else {
+			e_msg_composer_attach (composer, mime_part);
+		}
 	}
 
-	/* Jump to the editor as a last resort. */
+	if (text_part) {
+		gchar *html;
+		gssize length;
 
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "grab-focus", &ev);
-	CORBA_exception_free (&ev);
+		html = em_utils_part_to_html (text_part, &length, NULL);
+		e_msg_composer_set_pending_body (composer, html, length);
+	}
 }
 
 static void
-msg_composer_destroy_notify (void *data)
-{
-	EMsgComposer *composer = E_MSG_COMPOSER (data);
-
-	all_composers = g_slist_remove (all_composers, composer);
-}
-
-static int
-composer_key_pressed (EMsgComposer *composer, GdkEventKey *event, void *user_data)
+handle_multipart (EMsgComposer *composer,
+                  CamelMultipart *multipart,
+                  gint depth)
 {
-	GtkWidget *widget;
-	EMsgComposerPrivate *p = composer->priv;
-	widget = e_msg_composer_hdrs_get_subject_entry (E_MSG_COMPOSER_HDRS (p->hdrs));
-
-#ifdef HAVE_XFREE
-	if (event->keyval == XF86XK_Send) {
-		g_signal_emit (G_OBJECT (composer), signals[SEND], 0);
-		g_signal_stop_emission_by_name (composer, "key-press-event");
-		return TRUE;
-	}
-#endif /* HAVE_XFREE */
-
-	if (event->keyval == GDK_Escape) {
-		do_exit (composer);
-		g_signal_stop_emission_by_name (composer, "key-press-event");
-		return TRUE;
-	} else if ((event->keyval == GDK_Tab) && (gtk_widget_is_focus(widget))) {
-		CORBA_Environment ev;
-		CORBA_exception_init (&ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "grab-focus", &ev);
-		CORBA_exception_free (&ev);
-		g_signal_stop_emission_by_name (composer, "key-press-event");
-		return TRUE;
-	}
-	return FALSE;
-}
+	gint i, nparts;
 
+	nparts = camel_multipart_get_number (multipart);
 
-/* Verbs for non-control entries */
-static BonoboUIVerb entry_verbs [] = {
-	BONOBO_UI_VERB ("EditCut", menu_edit_cut_cb),
-	BONOBO_UI_VERB ("EditCopy", menu_edit_copy_cb),
-	BONOBO_UI_VERB ("EditPaste", menu_edit_paste_cb),
-	BONOBO_UI_VERB ("EditSelectAll", menu_edit_select_all_cb),
-	BONOBO_UI_VERB_END
-};
-
-/* All this snot is so that Cut/Copy/Paste work. */
-static gboolean
-composer_entry_focus_in_event_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
-{
-	EMsgComposer *composer = user_data;
-	EMsgComposerPrivate *p = composer->priv;
-	BonoboUIContainer *container;
-	char *xmlfile;
+	for (i = 0; i < nparts; i++) {
+		CamelContentType *content_type;
+		CamelDataWrapper *content;
+		CamelMimePart *mime_part;
 
-	p->focused_entry = widget;
+		mime_part = camel_multipart_get_part (multipart, i);
 
-	container = bonobo_window_get_ui_container (BONOBO_WINDOW (composer));
-	bonobo_ui_component_set_container (p->entry_uic, bonobo_object_corba_objref (BONOBO_OBJECT (container)), NULL);
+		if (!mime_part)
+			continue;
 
-	bonobo_ui_component_add_verb_list_with_data (p->entry_uic, entry_verbs, composer);
+		content_type = camel_mime_part_get_content_type (mime_part);
+		content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
 
-	bonobo_ui_component_freeze (p->entry_uic, NULL);
+		if (CAMEL_IS_MULTIPART (content)) {
+			CamelMultipart *mp;
 
-	xmlfile = g_build_filename (EVOLUTION_UIDIR, "evolution-composer-entries.xml", NULL);
-	bonobo_ui_util_set_ui (p->entry_uic, PREFIX,
-			       xmlfile,
-			       "evolution-composer-entries", NULL);
-	g_free (xmlfile);
+			mp = CAMEL_MULTIPART (content);
 
-	bonobo_ui_component_thaw (p->entry_uic, NULL);
+			if (CAMEL_IS_MULTIPART_SIGNED (content)) {
+				/* handle the signed content and configure the composer to sign outgoing messages */
+				handle_multipart_signed (composer, mp, depth + 1);
+			} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
+				/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
+				handle_multipart_encrypted (composer, mime_part, depth + 1);
+			} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
+				handle_multipart_alternative (composer, mp, depth + 1);
+			} else {
+				/* depth doesn't matter so long as we don't pass 0 */
+				handle_multipart (composer, mp, depth + 1);
+			}
+		} else if (depth == 0 && i == 0) {
+			gchar *html;
+			gssize length;
 
-	return FALSE;
+			/* Since the first part is not multipart/alternative,
+			 * this must be the body. */
+			html = em_utils_part_to_html (mime_part, &length, NULL);
+			e_msg_composer_set_pending_body (composer, html, length);
+		} else if (camel_mime_part_get_content_id (mime_part) ||
+			   camel_mime_part_get_content_location (mime_part)) {
+			/* special in-line attachment */
+			e_msg_composer_add_inline_image_from_mime_part (composer, mime_part);
+		} else {
+			/* normal attachment */
+			e_msg_composer_attach (composer, mime_part);
+		}
+	}
 }
 
-static gboolean
-composer_entry_focus_out_event_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
+static void
+set_signature_gui (EMsgComposer *composer)
 {
-	EMsgComposer *composer = user_data;
-	EMsgComposerPrivate *p = composer->priv;
+	GtkhtmlEditor *editor;
+	EComposerHeaderTable *table;
+	ESignature *signature = NULL;
+	const gchar *data;
+	gchar *decoded;
 
-	g_return_val_if_fail (p->focused_entry == widget, FALSE);
-	p->focused_entry = NULL;
+	editor = GTKHTML_EDITOR (composer);
+	table = e_msg_composer_get_header_table (composer);
 
-	bonobo_ui_component_unset_container (p->entry_uic, NULL);
+	if (!gtkhtml_editor_search_by_data (editor, 1, "ClueFlow", "signature", "1"))
+		return;
 
-	return FALSE;
+	data = gtkhtml_editor_get_paragraph_data (editor, "signature_name");
+	if (g_str_has_prefix (data, "uid:")) {
+		decoded = decode_signature_name (data + 4);
+		signature = mail_config_get_signature_by_uid (decoded);
+		g_free (decoded);
+	} else if (g_str_has_prefix (data, "name:")) {
+		decoded = decode_signature_name (data + 5);
+		signature = mail_config_get_signature_by_name (decoded);
+		g_free (decoded);
+	}
+
+	e_composer_header_table_set_signature (table, signature);
 }
 
-static void
-setup_cut_copy_paste (EMsgComposer *composer)
+/**
+ * e_msg_composer_new_with_message:
+ * @message: The message to use as the source
+ *
+ * Create a new message composer widget.
+ *
+ * Note: Designed to work only for messages constructed using Evolution.
+ *
+ * Returns: A pointer to the newly created widget
+ **/
+EMsgComposer *
+e_msg_composer_new_with_message (CamelMimeMessage *message)
 {
-	EMsgComposerHdrs *hdrs;
-	EMsgComposerPrivate *p = composer->priv;
-	GtkWidget *entry;
-
-	hdrs = (EMsgComposerHdrs *) p->hdrs;
+	const CamelInternetAddress *to, *cc, *bcc;
+	GList *To = NULL, *Cc = NULL, *Bcc = NULL, *postto = NULL;
+	const gchar *format, *subject;
+	EDestination **Tov, **Ccv, **Bccv;
+	GHashTable *auto_cc, *auto_bcc;
+	CamelContentType *content_type;
+	struct _camel_header_raw *headers;
+	CamelDataWrapper *content;
+	EAccount *account = NULL;
+	gchar *account_name;
+	EMsgComposer *composer;
+	EComposerHeaderTable *table;
+	GtkToggleAction *action;
+	struct _camel_header_raw *xev;
+	gint len, i;
+	EMsgComposerPrivate *p;
 
-	entry = e_msg_composer_hdrs_get_subject_entry (hdrs);
-	g_signal_connect (entry, "focus_in_event", G_CALLBACK (composer_entry_focus_in_event_cb), composer);
-	g_signal_connect (entry, "focus_out_event", G_CALLBACK (composer_entry_focus_out_event_cb), composer);
+	for (headers = CAMEL_MIME_PART (message)->headers;headers;headers = headers->next) {
+		if (!strcmp (headers->name, "X-Evolution-PostTo"))
+			postto = g_list_append (postto, g_strstrip (g_strdup (headers->value)));
+	}
 
-	entry = e_msg_composer_hdrs_get_reply_to_entry (hdrs);
-	g_signal_connect (entry, "focus_in_event", G_CALLBACK (composer_entry_focus_in_event_cb), composer);
-	g_signal_connect (entry, "focus_out_event", G_CALLBACK (composer_entry_focus_out_event_cb), composer);
+	if (postto != NULL)
+		composer = create_composer (E_MSG_COMPOSER_VISIBLE_MASK_POST);
+	else
+		composer = create_composer (E_MSG_COMPOSER_VISIBLE_MASK_MAIL);
+	p = composer->priv;
 
-	entry = e_msg_composer_hdrs_get_to_entry (hdrs);
-	g_signal_connect (entry, "focus_in_event", G_CALLBACK (composer_entry_focus_in_event_cb), composer);
-	g_signal_connect (entry, "focus_out_event", G_CALLBACK (composer_entry_focus_out_event_cb), composer);
+	if (!composer) {
+		g_list_foreach (postto, (GFunc)g_free, NULL);
+		g_list_free (postto);
+		return NULL;
+	}
 
-	entry = e_msg_composer_hdrs_get_cc_entry (hdrs);
-	g_signal_connect (entry, "focus_in_event", G_CALLBACK (composer_entry_focus_in_event_cb), composer);
-	g_signal_connect (entry, "focus_out_event", G_CALLBACK (composer_entry_focus_out_event_cb), composer);
+	table = e_msg_composer_get_header_table (composer);
 
-	entry = e_msg_composer_hdrs_get_bcc_entry (hdrs);
-	g_signal_connect (entry, "focus_in_event", G_CALLBACK (composer_entry_focus_in_event_cb), composer);
-	g_signal_connect (entry, "focus_out_event", G_CALLBACK (composer_entry_focus_out_event_cb), composer);
+	if (postto) {
+		e_composer_header_table_set_post_to_list (table, postto);
+		g_list_foreach (postto, (GFunc)g_free, NULL);
+		g_list_free (postto);
+		postto = NULL;
+	}
 
-	entry = e_msg_composer_hdrs_get_post_to_label (hdrs);
-	g_signal_connect (entry, "focus_in_event", G_CALLBACK (composer_entry_focus_in_event_cb), composer);
-	g_signal_connect (entry, "focus_out_event", G_CALLBACK (composer_entry_focus_out_event_cb), composer);
-}
+	/* Restore the Account preference */
+	account_name = (char *) camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Account");
+	if (account_name) {
+		account_name = g_strdup (account_name);
+		g_strstrip (account_name);
 
-static void
-composer_settings_update (GConfClient *gconf, guint cnxn_id, GConfEntry *entry, gpointer data)
-{
-	gboolean bool;
-	EMsgComposer *composer = data;
-	EMsgComposerPrivate *p = composer->priv;
+		if ((account = mail_config_get_account_by_uid (account_name)) == NULL)
+			/* 'old' setting */
+			account = mail_config_get_account_by_name (account_name);
+		if (account) {
+			g_free (account_name);
+			account_name = g_strdup (account->name);
+		}
+	}
 
-	bool = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/magic_smileys", NULL);
-	bonobo_widget_set_property (BONOBO_WIDGET (p->eeditor),
-				    "MagicSmileys", TC_CORBA_boolean, bool,
-				    NULL);
+	if (postto == NULL) {
+		auto_cc = g_hash_table_new_full (
+			camel_strcase_hash, camel_strcase_equal,
+			(GDestroyNotify) g_free,
+			(GDestroyNotify) NULL);
 
-	bool = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/magic_links", NULL);
-	bonobo_widget_set_property (BONOBO_WIDGET (p->eeditor),
-				    "MagicLinks", TC_CORBA_boolean, bool,
-				    NULL);
+		auto_bcc = g_hash_table_new_full (
+			camel_strcase_hash, camel_strcase_equal,
+			(GDestroyNotify) g_free,
+			(GDestroyNotify) NULL);
 
-	bool = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/inline_spelling", NULL);
-	bonobo_widget_set_property (BONOBO_WIDGET (p->eeditor),
-				   "InlineSpelling", TC_CORBA_boolean, bool,
-				   NULL);
-}
+		if (account) {
+			CamelInternetAddress *iaddr;
 
-static void
-e_msg_composer_unrealize (GtkWidget *widget, gpointer data)
-{
-	EMsgComposer *composer = E_MSG_COMPOSER (widget);
-	GConfClient *gconf;
-	GError *error = NULL;
-	int width, height;
+			/* hash our auto-recipients for this account */
+			if (account->always_cc) {
+				iaddr = camel_internet_address_new ();
+				if (camel_address_decode (CAMEL_ADDRESS (iaddr), account->cc_addrs) != -1) {
+					for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
+						const gchar *name, *addr;
 
-	gtk_window_get_size (GTK_WINDOW (composer), &width, &height);
+						if (!camel_internet_address_get (iaddr, i, &name, &addr))
+							continue;
 
-	gconf = gconf_client_get_default ();
-	if (!gconf_client_set_int (gconf, "/apps/evolution/mail/composer/width", width, &error)) {
-		g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-		g_clear_error(&error);
-	}
-	if (!gconf_client_set_int (gconf, "/apps/evolution/mail/composer/height", height, &error)) {
-		g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-		g_error_free(error);
-	}
-	g_object_unref (gconf);
-}
+						g_hash_table_insert (auto_cc, g_strdup (addr), GINT_TO_POINTER (TRUE));
+					}
+				}
+				camel_object_unref (iaddr);
+			}
 
-/* Callbacks.  */
+			if (account->always_bcc) {
+				iaddr = camel_internet_address_new ();
+				if (camel_address_decode (CAMEL_ADDRESS (iaddr), account->bcc_addrs) != -1) {
+					for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
+						const gchar *name, *addr;
 
-static void
-emcab_add(EPopup *ep, EPopupItem *item, void *data)
-{
-	EAttachmentBar *bar = data;
-	EMsgComposer *toplevel = E_MSG_COMPOSER (gtk_widget_get_toplevel (GTK_WIDGET (bar)));
-	GtkWidget **attachment_selector = e_attachment_bar_get_selector(E_ATTACHMENT_BAR(bar));
+						if (!camel_internet_address_get (iaddr, i, &name, &addr))
+							continue;
 
-	e_msg_composer_select_file_attachments (toplevel, attachment_selector, add_to_bar);
-}
+						g_hash_table_insert (auto_bcc, g_strdup (addr), GINT_TO_POINTER (TRUE));
+					}
+				}
+				camel_object_unref (iaddr);
+			}
+		}
 
-static void
-emcab_properties(EPopup *ep, EPopupItem *item, void *data)
-{
-	EAttachmentBar *bar = data;
+		to = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
+		cc = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
+		bcc = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
 
-	e_attachment_bar_edit_selected(bar);
-}
+		len = CAMEL_ADDRESS (to)->addresses->len;
+		for (i = 0; i < len; i++) {
+			const gchar *name, *addr;
 
-static void
-emcab_remove(EPopup *ep, EPopupItem *item, void *data)
-{
-	EAttachmentBar *bar = data;
+			if (camel_internet_address_get (to, i, &name, &addr)) {
+				EDestination *dest = e_destination_new ();
+				e_destination_set_name (dest, name);
+				e_destination_set_email (dest, addr);
+				To = g_list_append (To, dest);
+			}
+		}
+		Tov = destination_list_to_vector (To);
+		g_list_free (To);
 
-	e_attachment_bar_remove_selected(bar);
-}
+		len = CAMEL_ADDRESS (cc)->addresses->len;
+		for (i = 0; i < len; i++) {
+			const gchar *name, *addr;
 
-/* Popup menu handling.  */
-static EPopupItem emcab_popups[] = {
-	{ E_POPUP_ITEM, "10.attach", N_("_Remove"), emcab_remove, NULL, GTK_STOCK_REMOVE, EM_POPUP_ATTACHMENTS_MANY },
-	{ E_POPUP_ITEM, "20.attach", N_("_Properties"), emcab_properties, NULL, GTK_STOCK_PROPERTIES, EM_POPUP_ATTACHMENTS_ONE },
-	{ E_POPUP_BAR, "30.attach.00", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MANY|EM_POPUP_ATTACHMENTS_ONE },
-	{ E_POPUP_ITEM, "30.attach.01", N_("_Add attachment..."), emcab_add, NULL, GTK_STOCK_ADD, 0 },
-};
+			if (camel_internet_address_get (cc, i, &name, &addr)) {
+				EDestination *dest = e_destination_new ();
+				e_destination_set_name (dest, name);
+				e_destination_set_email (dest, addr);
 
-static void
-emcab_popup_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data)
-{
-	EAttachmentBar *bar = user_data;
-	GnomeIconList *icon_list = user_data;
-	GList *selection;
-	GnomeCanvasPixbuf *image;
+				if (g_hash_table_lookup (auto_cc, addr))
+					e_destination_set_auto_recipient (dest, TRUE);
 
-	gdk_window_get_origin (((GtkWidget*) bar)->window, x, y);
+				Cc = g_list_append (Cc, dest);
+			}
+		}
 
-	selection = gnome_icon_list_get_selection (icon_list);
-	if (selection == NULL)
-		return;
+		Ccv = destination_list_to_vector (Cc);
+		g_hash_table_destroy (auto_cc);
+		g_list_free (Cc);
 
-	image = gnome_icon_list_get_icon_pixbuf_item (icon_list, GPOINTER_TO_INT(selection->data));
-	if (image == NULL)
-		return;
+		len = CAMEL_ADDRESS (bcc)->addresses->len;
+		for (i = 0; i < len; i++) {
+			const gchar *name, *addr;
 
-	/* Put menu to the center of icon. */
-	*x += (int)(image->item.x1 + image->item.x2) / 2;
-	*y += (int)(image->item.y1 + image->item.y2) / 2;
-}
+			if (camel_internet_address_get (bcc, i, &name, &addr)) {
+				EDestination *dest = e_destination_new ();
+				e_destination_set_name (dest, name);
+				e_destination_set_email (dest, addr);
 
-static void
-emcab_popups_free(EPopup *ep, GSList *l, void *data)
-{
-	g_slist_free(l);
-}
+				if (g_hash_table_lookup (auto_bcc, addr))
+					e_destination_set_auto_recipient (dest, TRUE);
 
-/* if id != -1, then use it as an index for target of the popup */
+				Bcc = g_list_append (Bcc, dest);
+			}
+		}
 
-static void
-emcab_popup(EAttachmentBar *bar, GdkEventButton *event, int id)
-{
-	GSList *attachments = NULL, *menus = NULL;
-	int i;
-	EMPopup *emp;
-	EMPopupTargetAttachments *t;
-	GtkMenu *menu;
+		Bccv = destination_list_to_vector (Bcc);
+		g_hash_table_destroy (auto_bcc);
+		g_list_free (Bcc);
+	} else {
+		Tov = NULL;
+		Ccv = NULL;
+		Bccv = NULL;
+	}
 
-	attachments = e_attachment_bar_get_attachment(bar, id);
+	subject = camel_mime_message_get_subject (message);
 
-	for (i=0;i<sizeof(emcab_popups)/sizeof(emcab_popups[0]);i++)
-		menus = g_slist_prepend(menus, &emcab_popups[i]);
+	e_composer_header_table_set_account_name (table, account_name);
+	e_composer_header_table_set_destinations_to (table, Tov);
+	e_composer_header_table_set_destinations_cc (table, Ccv);
+	e_composer_header_table_set_destinations_bcc (table, Bccv);
+	e_composer_header_table_set_subject (table, subject);
 
-	/** @HookPoint-EMPopup: Composer Attachment Bar Context Menu
-	 * @Id: org.gnome.evolution.mail.composer.attachmentbar.popup
-	 * @Class: org.gnome.evolution.mail.popup:1.0
-	 * @Target: EMPopupTargetAttachments
-	 *
-	 * This is the context menu on the composer attachment bar.
-	 */
-	emp = em_popup_new("org.gnome.evolution.mail.composer.attachmentbar.popup");
-	e_popup_add_items((EPopup *)emp, menus, NULL,emcab_popups_free, bar);
-	t = em_popup_target_new_attachments(emp, attachments);
-	t->target.widget = (GtkWidget *)bar;
-	menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)t, 0);
+	g_free (account_name);
 
-	if (event == NULL)
-		gtk_menu_popup(menu, NULL, NULL, emcab_popup_position, bar, 0, gtk_get_current_event_time());
-	else
-		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
-}
+	e_destination_freev (Tov);
+	e_destination_freev (Ccv);
+	e_destination_freev (Bccv);
 
-static gboolean
-popup_menu_event (GtkWidget *widget)
-{
-	emcab_popup((EAttachmentBar *)widget, NULL, -1);
-	return TRUE;
-}
+	/* Restore the format editing preference */
+	format = camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Format");
+	if (format) {
+		gchar **flags;
 
+		while (*format && camel_mime_is_lwsp (*format))
+			format++;
 
-static int
-button_press_event (GtkWidget *widget, GdkEventButton *event)
-{
-	EAttachmentBar *bar = (EAttachmentBar *)widget;
-	GnomeIconList *icon_list = GNOME_ICON_LIST(widget);
-	int icon_number;
+		flags = g_strsplit (format, ", ", 0);
+		for (i=0;flags[i];i++) {
+			printf ("restoring draft flag '%s'\n", flags[i]);
 
-	if (event->button != 3)
-		return FALSE;
+			if (g_ascii_strcasecmp (flags[i], "text/html") == 0)
+				gtkhtml_editor_set_html_mode (
+					GTKHTML_EDITOR (composer), TRUE);
+			else if (g_ascii_strcasecmp (flags[i], "text/plain") == 0)
+				gtkhtml_editor_set_html_mode (
+					GTKHTML_EDITOR (composer), FALSE);
+			else if (g_ascii_strcasecmp (flags[i], "pgp-sign") == 0) {
+				action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+				gtk_toggle_action_set_active (action, TRUE);
+			} else if (g_ascii_strcasecmp (flags[i], "pgp-encrypt") == 0) {
+				action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT));
+				gtk_toggle_action_set_active (action, TRUE);
+			} else if (g_ascii_strcasecmp (flags[i], "smime-sign") == 0) {
+				action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
+				gtk_toggle_action_set_active (action, TRUE);
+			} else if (g_ascii_strcasecmp (flags[i], "smime-encrypt") == 0) {
+				action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
+				gtk_toggle_action_set_active (action, TRUE);
+			}
+		}
+		g_strfreev (flags);
+	}
 
-	icon_number = gnome_icon_list_get_icon_at (icon_list, event->x, event->y);
-	if (icon_number >= 0) {
-		gnome_icon_list_unselect_all(icon_list);
-		gnome_icon_list_select_icon (icon_list, icon_number);
+	/* Remove any other X-Evolution-* headers that may have been set */
+	xev = mail_tool_remove_xevolution_headers (message);
+	camel_header_raw_clear (&xev);
+	
+	/* Check for receipt request */
+	if (camel_medium_get_header (CAMEL_MEDIUM (message), "Disposition-Notification-To")) {
+		action = GTK_TOGGLE_ACTION (ACTION (REQUEST_READ_RECEIPT));
+		gtk_toggle_action_set_active (action, TRUE);
+	}
+	
+	/* Check for mail priority */
+	if (camel_medium_get_header (CAMEL_MEDIUM (message), "X-Priority")) {
+		action = GTK_TOGGLE_ACTION (ACTION (PRIORITIZE_MESSAGE));
+		gtk_toggle_action_set_active (action, TRUE);
 	}
 
-	emcab_popup(bar, event, icon_number);
+	/* set extra headers */
+	headers = CAMEL_MIME_PART (message)->headers;
+	while (headers) {
+		if (!is_special_header (headers->name) ||
+		    !g_ascii_strcasecmp (headers->name, "References") ||
+		    !g_ascii_strcasecmp (headers->name, "In-Reply-To")) {
+			g_ptr_array_add (p->extra_hdr_names, g_strdup (headers->name));
+			g_ptr_array_add (p->extra_hdr_values, g_strdup (headers->value));
+		}
 
-	return TRUE;
-}
+		headers = headers->next;
+	}
 
-static gint
-key_press_event(GtkWidget *widget, GdkEventKey *event)
-{
-	EAttachmentBar *bar = E_ATTACHMENT_BAR(widget);
+	/* Restore the attachments and body text */
+	content = camel_medium_get_content_object (CAMEL_MEDIUM (message));
+	if (CAMEL_IS_MULTIPART (content)) {
+		CamelMultipart *multipart;
 
-	if (event->keyval == GDK_Delete) {
-		e_attachment_bar_remove_selected (bar);
-		return TRUE;
-	}
+		multipart = CAMEL_MULTIPART (content);
+		content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (message));
 
-	return FALSE;
-}
+		if (CAMEL_IS_MULTIPART_SIGNED (content)) {
+			/* handle the signed content and configure the composer to sign outgoing messages */
+			handle_multipart_signed (composer, multipart, 0);
+		} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
+			/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
+			handle_multipart_encrypted (composer, CAMEL_MIME_PART (message), 0);
+		} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
+			/* this contains the text/plain and text/html versions of the message body */
+			handle_multipart_alternative (composer, multipart, 0);
+		} else {
+			/* there must be attachments... */
+			handle_multipart (composer, multipart, 0);
+		}
+	} else {
+		gchar *html;
+		gssize length;
 
-static EMsgComposer *
-create_composer (int visible_mask)
-{
-	EMsgComposer *composer;
-	GtkWidget *vbox, *expander_hbox;
-	Bonobo_Unknown editor_server;
-	CORBA_Environment ev;
-	GConfClient *gconf;
-	int vis;
-	GList *icon_list;
-	BonoboControlFrame *control_frame;
-	GtkWidget *html_widget = NULL;
-	gpointer servant;
-	BonoboObject *impl;
-	EMsgComposerPrivate *p;
+		html = em_utils_part_to_html ((CamelMimePart *)message, &length, NULL);
+		e_msg_composer_set_pending_body (composer, html, length);
+	}
 
-	composer = g_object_new (E_TYPE_MSG_COMPOSER, "win_name", _("Compose Message"), NULL);
-	p = composer->priv;
+	/* We wait until now to set the body text because we need to
+	 * ensure that the attachment bar has all the attachments before
+	 * we request them. */
+	e_msg_composer_flush_pending_body (composer);
 
-	gtk_window_set_title ((GtkWindow *) composer, _("Compose Message"));
+	set_signature_gui (composer);
 
-	all_composers = g_slist_prepend (all_composers, composer);
+	return composer;
+}
 
-	g_signal_connect (composer, "key-press-event",
-			  G_CALLBACK (composer_key_pressed),
-			  NULL);
-
-	g_signal_connect (composer, "destroy",
-			  G_CALLBACK (msg_composer_destroy_notify),
-			  NULL);
-
-	icon_list = e_icon_factory_get_icon_list ("mail-message-new");
-	if (icon_list) {
-		gtk_window_set_icon_list (GTK_WINDOW (composer), icon_list);
-		g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
-		g_list_free (icon_list);
-	}
-
-	/* DND support */
-	gtk_drag_dest_set (GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL,  drop_types, num_drop_types, GDK_ACTION_COPY|GDK_ACTION_ASK|GDK_ACTION_MOVE);
-	g_signal_connect(composer, "drag_data_received", G_CALLBACK (drag_data_received), composer);
-	g_signal_connect(composer, "drag-motion", G_CALLBACK(drag_motion), composer);
-	e_msg_composer_load_config (composer, visible_mask);
-
-	setup_ui (composer);
-
-	vbox = gtk_vbox_new (FALSE, 0);
-
-	vis = e_msg_composer_get_visible_flags (composer);
-	p->hdrs = e_msg_composer_hdrs_new (p->uic, visible_mask, vis);
-	if (!p->hdrs) {
-		e_error_run (GTK_WINDOW (composer), "mail-composer:no-address-control", NULL);
-		gtk_object_destroy (GTK_OBJECT (composer));
-		return NULL;
-	}
+static void
+disable_editor (EMsgComposer *composer)
+{
+	GtkhtmlEditor *editor;
+	GtkAction *action;
 
-	gtk_box_set_spacing (GTK_BOX (vbox), 6);
-	gtk_box_pack_start (GTK_BOX (vbox), p->hdrs, FALSE, FALSE, 0);
-	g_signal_connect (p->hdrs, "subject_changed",
-			  G_CALLBACK (subject_changed_cb), composer);
-	g_signal_connect (p->hdrs, "hdrs_changed",
-			  G_CALLBACK (hdrs_changed_cb), composer);
-	g_signal_connect (p->hdrs, "from_changed",
-			  G_CALLBACK (from_changed_cb), composer);
-	g_signal_connect_swapped (
-                p->hdrs, "signature_changed",
-                G_CALLBACK (e_msg_composer_show_sig_file), composer);
-	gtk_widget_show (p->hdrs);
-
-	from_changed_cb((EMsgComposerHdrs *)p->hdrs, composer);
-
-	/* Editor component.  */
-	p->eeditor = bonobo_widget_new_control (
-		GNOME_GTKHTML_EDITOR_CONTROL_ID,
-		bonobo_ui_component_get_container (p->uic));
-	if (!p->eeditor) {
-		e_error_run (GTK_WINDOW (composer), "mail-composer:no-editor-control", NULL);
-		gtk_object_destroy (GTK_OBJECT (composer));
-		return NULL;
-	}
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (p->eeditor));
-	bonobo_control_frame_set_autoactivate (control_frame, TRUE);
+	editor = GTKHTML_EDITOR (composer);
 
-	/* let the editor know which mode we are in */
-	bonobo_widget_set_property (BONOBO_WIDGET (p->eeditor),
-				    "FormatHTML", TC_CORBA_boolean, p->send_html,
-				    NULL);
+	gtkhtml_editor_run_command (editor, "editable-off");
 
-	gconf = gconf_client_get_default ();
-	composer_settings_update (gconf, 0, NULL, composer);
-	e_msg_composer_set_request_receipt (composer, gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/request_receipt", NULL));
-	gconf_client_add_dir (gconf, "/apps/evolution/mail/composer", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
-	p->notify_id = gconf_client_notify_add (gconf, "/apps/evolution/mail/composer",
-						       composer_settings_update, composer, NULL, NULL);
-	gtk_window_set_default_size (GTK_WINDOW (composer),
-				     gconf_client_get_int (gconf, "/apps/evolution/mail/composer/width", NULL),
-				     gconf_client_get_int (gconf, "/apps/evolution/mail/composer/height", NULL));
-	g_signal_connect (composer, "unrealize", G_CALLBACK (e_msg_composer_unrealize), NULL);
-	g_object_unref (gconf);
+	action = GTKHTML_EDITOR_ACTION_EDIT_MENU (composer);
+	gtk_action_set_sensitive (action, FALSE);
 
-	editor_server = bonobo_widget_get_objref (BONOBO_WIDGET (p->eeditor));
+	action = GTKHTML_EDITOR_ACTION_FORMAT_MENU (composer);
+	gtk_action_set_sensitive (action, FALSE);
 
-	/* FIXME: handle exceptions */
-	CORBA_exception_init (&ev);
-	p->persist_file_interface
-		= Bonobo_Unknown_queryInterface (editor_server, "IDL:Bonobo/PersistFile:1.0", &ev);
-	p->persist_stream_interface
-		= Bonobo_Unknown_queryInterface (editor_server, "IDL:Bonobo/PersistStream:1.0", &ev);
-	CORBA_exception_free (&ev);
-
-	gtk_box_pack_start (GTK_BOX (vbox), p->eeditor, TRUE, TRUE, 0);
-
-	/* Attachment editor, wrapped into an EScrollFrame.  It's
-	   hidden in an EExpander. */
-
-	p->attachment_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (p->attachment_scrolled_window),
-					     GTK_SHADOW_IN);
-	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (p->attachment_scrolled_window),
-					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
-	p->attachment_bar = e_attachment_bar_new (NULL);
-
-	g_signal_connect (p->attachment_bar, "button_press_event", G_CALLBACK (button_press_event), NULL);
-	g_signal_connect (p->attachment_bar, "key_press_event", G_CALLBACK (key_press_event), NULL);
-	g_signal_connect (p->attachment_bar, "popup-menu", G_CALLBACK (popup_menu_event), NULL);
-
-	GTK_WIDGET_SET_FLAGS (p->attachment_bar, GTK_CAN_FOCUS);
-	gtk_container_add (GTK_CONTAINER (p->attachment_scrolled_window),
-			   p->attachment_bar);
-	gtk_widget_show (p->attachment_bar);
-	g_signal_connect (p->attachment_bar, "changed",
-			  G_CALLBACK (attachment_bar_changed_cb), composer);
-
-	p->attachment_expander_label =
-		gtk_label_new_with_mnemonic (_("Show _Attachment Bar"));
-	p->attachment_expander_num = gtk_label_new ("");
-	gtk_label_set_use_markup (GTK_LABEL (p->attachment_expander_num), TRUE);
-	gtk_misc_set_alignment (GTK_MISC (p->attachment_expander_label), 0.0, 0.5);
-	gtk_misc_set_alignment (GTK_MISC (p->attachment_expander_num), 1.0, 0.5);
-	expander_hbox = gtk_hbox_new (FALSE, 0);
-
-	p->attachment_expander_icon = e_icon_factory_get_image ("mail-attachment", E_ICON_SIZE_MENU);
-	gtk_misc_set_alignment (GTK_MISC (p->attachment_expander_icon), 1, 0.5);
-	gtk_widget_set_size_request (p->attachment_expander_icon, 100, -1);
-
-	gtk_box_pack_start (GTK_BOX (expander_hbox), p->attachment_expander_label,
-			    TRUE, TRUE, GNOME_PAD_SMALL);
-	gtk_box_pack_start (GTK_BOX (expander_hbox), p->attachment_expander_icon,
-			    TRUE, TRUE, 0);
-	gtk_box_pack_start (GTK_BOX (expander_hbox), p->attachment_expander_num,
-			    FALSE, FALSE, GNOME_PAD_SMALL);
-	gtk_widget_show_all (expander_hbox);
-	gtk_widget_hide (p->attachment_expander_icon);
-
-	p->attachment_expander = e_expander_new ("");
-	e_expander_set_label_widget (E_EXPANDER (p->attachment_expander), expander_hbox);
-	gtk_container_add (GTK_CONTAINER (p->attachment_expander), p->attachment_scrolled_window);
-
-	gtk_box_pack_start (GTK_BOX (vbox), p->attachment_expander, FALSE, FALSE, GNOME_PAD_SMALL);
-	gtk_widget_show (p->attachment_expander);
-	e_expander_set_expanded (E_EXPANDER (p->attachment_expander), FALSE);
-	g_signal_connect_after (p->attachment_expander, "activate",
-				G_CALLBACK (attachment_expander_activate_cb), composer);
-
-	bonobo_window_set_contents (BONOBO_WINDOW (composer), vbox);
-	gtk_widget_show (vbox);
-
-	/* If we show this widget earlier, we lose network transparency. i.e. the
-	   component appears on the machine evo is running on, ignoring any DISPLAY
-	   variable. */
-	gtk_widget_show (p->eeditor);
-
-	prepare_engine (composer);
-	if (p->eeditor_engine == CORBA_OBJECT_NIL) {
-		e_error_run (GTK_WINDOW (composer), "mail-composer:no-editor-control", NULL);
-		gtk_object_destroy (GTK_OBJECT (composer));
-		return NULL;
-	}
+	action = GTKHTML_EDITOR_ACTION_INSERT_MENU (composer);
+	gtk_action_set_sensitive (action, FALSE);
 
-	/* The engine would have the GtkHTML widget stored in "html-widget"
-	 * We'll use that to listen for DnD signals
-	 */
+	gtk_widget_set_sensitive (composer->priv->attachment_bar, FALSE);
+}
 
-	servant = ORBit_small_get_servant (p->eeditor_engine);
-    	if (servant && (impl = bonobo_object (servant)))
-		html_widget = g_object_get_data (G_OBJECT(impl), "html-widget");
+/**
+ * e_msg_composer_new_redirect:
+ * @message: The message to use as the source
+ *
+ * Create a new message composer widget.
+ *
+ * Returns: A pointer to the newly created widget
+ **/
+EMsgComposer *
+e_msg_composer_new_redirect (CamelMimeMessage *message,
+                             const gchar *resent_from)
+{
+	EMsgComposer *composer;
+	EComposerHeaderTable *table;
+	const gchar *subject;
 
-	if (html_widget) {
-		g_signal_connect (html_widget, "drag_data_received", G_CALLBACK (drag_data_received), composer);
-	}
+	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
 
-	setup_cut_copy_paste (composer);
+	composer = e_msg_composer_new_with_message (message);
+	table = e_msg_composer_get_header_table (composer);
 
-	g_signal_connect (composer, "map", (GCallback) map_default_cb, NULL);
+	subject = camel_mime_message_get_subject (message);
 
-	if (am == NULL)
-		am = autosave_manager_new ();
+	composer->priv->redirect = message;
+	camel_object_ref (message);
 
-	autosave_manager_register (am, composer);
+	e_composer_header_table_set_account_name (table, resent_from);
+	e_composer_header_table_set_subject (table, subject);
 
-	p->has_changed = FALSE;
+	disable_editor (composer);
 
 	return composer;
 }
 
-static void
-set_editor_signature (EMsgComposer *composer)
+/**
+ * e_msg_composer_send:
+ * @composer: an #EMsgComposer
+ *
+ * Send the message in @composer.
+ **/
+void
+e_msg_composer_send (EMsgComposer *composer)
 {
-	EMsgComposerHdrs *hdrs;
-	ESignature *signature;
-	EAccount *account;
-	const gchar *uid;
-
-	hdrs = E_MSG_COMPOSER_HDRS (composer->priv->hdrs);
-	account = e_msg_composer_hdrs_get_from_account (hdrs);
-	g_return_if_fail (account != NULL);
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	uid = account->id->sig_uid;
-	signature = uid ? mail_config_get_signature_by_uid (uid) : NULL;
-	e_msg_composer_hdrs_set_signature (hdrs, signature);
+	g_signal_emit (composer, signals[SEND], 0);
 }
 
 /**
- * e_msg_composer_new_with_type:
- *
- * Create a new message composer widget. The type can be
- * E_MSG_COMPOSER_MAIL, E_MSG_COMPOSER_POST or E_MSG_COMPOSER_MAIL_POST.
+ * e_msg_composer_save_draft:
+ * @composer: an #EMsgComposer
  *
- * Return value: A pointer to the newly created widget
+ * Save the message in @composer to the selected account's Drafts folder.
  **/
+void
+e_msg_composer_save_draft (EMsgComposer *composer)
+{
+	GtkhtmlEditor *editor;
 
-EMsgComposer *
-e_msg_composer_new_with_type (int type)
-{
-	gboolean send_html;
-	GConfClient *gconf;
-	EMsgComposer *new;
-
-	gconf = gconf_client_get_default ();
-	send_html = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/send_html", NULL);
-	g_object_unref (gconf);
-
-	switch (type) {
-	case E_MSG_COMPOSER_MAIL:
-		new = create_composer (E_MSG_COMPOSER_VISIBLE_MASK_MAIL);
-		break;
-	case E_MSG_COMPOSER_POST:
-		new = create_composer (E_MSG_COMPOSER_VISIBLE_MASK_POST);
-		break;
-	default:
-		new = create_composer (E_MSG_COMPOSER_VISIBLE_MASK_MAIL | E_MSG_COMPOSER_VISIBLE_MASK_POST);
-	}
-
-	if (new) {
-		e_msg_composer_set_send_html (new, send_html);
-		set_editor_signature (new);
-		set_editor_text (new, "", 0, TRUE, TRUE);
-	}
-
-	return new;
-}
-
-/**
- * e_msg_composer_new:
- *
- * Create a new message composer widget.
- *
- * Return value: A pointer to the newly created widget
- **/
-EMsgComposer *
-e_msg_composer_new (void)
-{
-	return e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL);
-}
-
-static gboolean
-is_special_header (const char *hdr_name)
-{
-	/* Note: a header is a "special header" if it has any meaning:
-	   1. it's not a X-* header or
-	   2. it's an X-Evolution* header
-	*/
-	if (g_ascii_strncasecmp (hdr_name, "X-", 2))
-		return TRUE;
-
-	if (!g_ascii_strncasecmp (hdr_name, "X-Evolution", 11))
-		return TRUE;
-
-	/* we can keep all other X-* headers */
-
-	return FALSE;
-}
-
-static void
-e_msg_composer_set_pending_body (EMsgComposer *composer, char *text, ssize_t len)
-{
-	char *old;
-
-	old = g_object_get_data ((GObject *) composer, "body:text");
-	g_free (old);
-	g_object_set_data ((GObject *) composer, "body:text", text);
-	g_object_set_data ((GObject *) composer, "body:len", GSIZE_TO_POINTER (len));
-}
-
-static void
-e_msg_composer_flush_pending_body (EMsgComposer *composer, gboolean apply)
-{
-	char *body;
-	ssize_t len;
-
-	body = g_object_get_data ((GObject *) composer, "body:text");
-	len = GPOINTER_TO_SIZE (g_object_get_data ((GObject *) composer, "body:len"));
-	if (body) {
-		if (apply)
-			set_editor_text (composer, body, len, FALSE, FALSE);
-
-		g_object_set_data ((GObject *) composer, "body:text", NULL);
-		g_free (body);
-	}
-}
-
-static void
-add_attachments_handle_mime_part (EMsgComposer *composer, CamelMimePart *mime_part,
-				  gboolean just_inlines, gboolean related, int depth)
-{
-	CamelContentType *content_type;
-	CamelDataWrapper *wrapper;
-
-	if (!mime_part)
-		return;
-
-	content_type = camel_mime_part_get_content_type (mime_part);
-	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
-
-	if (CAMEL_IS_MULTIPART (wrapper)) {
-		/* another layer of multipartness... */
-		add_attachments_from_multipart (composer, (CamelMultipart *) wrapper, just_inlines, depth + 1);
-	} else if (just_inlines) {
-		if (camel_mime_part_get_content_id (mime_part) ||
-		    camel_mime_part_get_content_location (mime_part))
-			e_msg_composer_add_inline_image_from_mime_part (composer, mime_part);
-	} else if (CAMEL_IS_MIME_MESSAGE (wrapper)) {
-		/* do nothing */
-	} else if (related && camel_content_type_is (content_type, "image", "*")) {
-		e_msg_composer_add_inline_image_from_mime_part (composer, mime_part);
-	} else {
-		if (camel_content_type_is (content_type, "text", "*")) {
-			/* do nothing */
-		} else {
-			e_msg_composer_attach (composer, mime_part);
-		}
-	}
-}
-
-static void
-add_attachments_from_multipart (EMsgComposer *composer, CamelMultipart *multipart,
-				gboolean just_inlines, int depth)
-{
-	/* find appropriate message attachments to add to the composer */
-	CamelMimePart *mime_part;
-	gboolean related;
-	int i, nparts;
-
-	related = camel_content_type_is (CAMEL_DATA_WRAPPER (multipart)->mime_type, "multipart", "related");
-
-	if (CAMEL_IS_MULTIPART_SIGNED (multipart)) {
-		mime_part = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
-		add_attachments_handle_mime_part (composer, mime_part, just_inlines, related, depth);
-	} else if (CAMEL_IS_MULTIPART_ENCRYPTED (multipart)) {
-		/* what should we do in this case? */
-	} else {
-		nparts = camel_multipart_get_number (multipart);
-
-		for (i = 0; i < nparts; i++) {
-			mime_part = camel_multipart_get_part (multipart, i);
-			add_attachments_handle_mime_part (composer, mime_part, just_inlines, related, depth);
-		}
-	}
-}
-
-
-/**
- * e_msg_composer_add_message_attachments:
- * @composer: the composer to add the attachments to.
- * @message: the source message to copy the attachments from.
- * @just_inlines: whether to attach all attachments or just add
- * inline images.
- *
- * Walk through all the mime parts in @message and add them to the composer
- * specified in @composer.
- */
-void
-e_msg_composer_add_message_attachments (EMsgComposer *composer, CamelMimeMessage *message,
-					gboolean just_inlines)
-{
-	CamelDataWrapper *wrapper;
-
-	wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (message));
-	if (!CAMEL_IS_MULTIPART (wrapper))
-		return;
-
-	/* there must be attachments... */
-	add_attachments_from_multipart (composer, (CamelMultipart *) wrapper, just_inlines, 0);
-}
-
-
-static void
-handle_multipart_signed (EMsgComposer *composer, CamelMultipart *multipart, int depth)
-{
-	CamelContentType *content_type;
-	CamelDataWrapper *content;
-	CamelMimePart *mime_part;
-
-	/* FIXME: make sure this isn't an s/mime signed part?? */
-	e_msg_composer_set_pgp_sign (composer, TRUE);
-
-	mime_part = camel_multipart_get_part (multipart, CAMEL_MULTIPART_SIGNED_CONTENT);
-
-	if (!mime_part)
-		return;
-
-	content_type = camel_mime_part_get_content_type (mime_part);
-
-	content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
-
-	if (CAMEL_IS_MULTIPART (content)) {
-		multipart = CAMEL_MULTIPART (content);
-
-		/* Note: depth is preserved here because we're not
-		   counting multipart/signed as a multipart, instead
-		   we want to treat the content part as our mime part
-		   here. */
-
-		if (CAMEL_IS_MULTIPART_SIGNED (content)) {
-			/* handle the signed content and configure the composer to sign outgoing messages */
-			handle_multipart_signed (composer, multipart, depth);
-		} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
-			/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
-			handle_multipart_encrypted (composer, mime_part, depth);
-		} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
-			/* this contains the text/plain and text/html versions of the message body */
-			handle_multipart_alternative (composer, multipart, depth);
-		} else {
-			/* there must be attachments... */
-			handle_multipart (composer, multipart, depth);
-		}
-	} else if (camel_content_type_is (content_type, "text", "*")) {
-		ssize_t len;
-		char *html;
-
-		html = em_utils_part_to_html (mime_part, &len, NULL);
-		e_msg_composer_set_pending_body (composer, html, len);
-	} else {
-		e_msg_composer_attach (composer, mime_part);
-	}
-}
-
-static void
-handle_multipart_encrypted (EMsgComposer *composer, CamelMimePart *multipart, int depth)
-{
-	CamelContentType *content_type;
-	CamelCipherContext *cipher;
-	CamelDataWrapper *content;
-	CamelMimePart *mime_part;
-	CamelException ex;
-	CamelCipherValidity *valid;
-
-	/* FIXME: make sure this is a PGP/MIME encrypted part?? */
-	e_msg_composer_set_pgp_encrypt (composer, TRUE);
-
-	camel_exception_init (&ex);
-	cipher = mail_crypto_get_pgp_cipher_context (NULL);
-	mime_part = camel_mime_part_new();
-	valid = camel_cipher_decrypt(cipher, multipart, mime_part, &ex);
-	camel_object_unref(cipher);
-	camel_exception_clear (&ex);
-	if (valid == NULL)
-		return;
-	camel_cipher_validity_free(valid);
-
-	content_type = camel_mime_part_get_content_type (mime_part);
-
-	content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
-
-	if (CAMEL_IS_MULTIPART (content)) {
-		CamelMultipart *content_multipart = CAMEL_MULTIPART (content);
-
-		/* Note: depth is preserved here because we're not
-		   counting multipart/encrypted as a multipart, instead
-		   we want to treat the content part as our mime part
-		   here. */
-
-		if (CAMEL_IS_MULTIPART_SIGNED (content)) {
-			/* handle the signed content and configure the composer to sign outgoing messages */
-			handle_multipart_signed (composer, content_multipart, depth);
-		} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
-			/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
-			handle_multipart_encrypted (composer, mime_part, depth);
-		} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
-			/* this contains the text/plain and text/html versions of the message body */
-			handle_multipart_alternative (composer, content_multipart, depth);
-		} else {
-			/* there must be attachments... */
-			handle_multipart (composer, content_multipart, depth);
-		}
-	} else if (camel_content_type_is (content_type, "text", "*")) {
-		ssize_t len;
-		char *html;
-
-		html = em_utils_part_to_html (mime_part, &len, NULL);
-		e_msg_composer_set_pending_body (composer, html, len);
-	} else {
-		e_msg_composer_attach (composer, mime_part);
-	}
-
-	camel_object_unref (mime_part);
-}
-
-static void
-handle_multipart_alternative (EMsgComposer *composer, CamelMultipart *multipart, int depth)
-{
-	/* Find the text/html part and set the composer body to it's contents */
-	CamelMimePart *text_part = NULL;
-	int i, nparts;
-
-	nparts = camel_multipart_get_number (multipart);
-
-	for (i = 0; i < nparts; i++) {
-		CamelContentType *content_type;
-		CamelDataWrapper *content;
-		CamelMimePart *mime_part;
-
-		mime_part = camel_multipart_get_part (multipart, i);
-
-		if (!mime_part)
-			continue;
-
-		content_type = camel_mime_part_get_content_type (mime_part);
-		content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
-
-		if (CAMEL_IS_MULTIPART (content)) {
-			CamelMultipart *mp;
-
-			mp = CAMEL_MULTIPART (content);
-
-			if (CAMEL_IS_MULTIPART_SIGNED (content)) {
-				/* handle the signed content and configure the composer to sign outgoing messages */
-				handle_multipart_signed (composer, mp, depth + 1);
-			} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
-				/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
-				handle_multipart_encrypted (composer, mime_part, depth + 1);
-			} else {
-				/* depth doesn't matter so long as we don't pass 0 */
-				handle_multipart (composer, mp, depth + 1);
-			}
-		} else if (camel_content_type_is (content_type, "text", "html")) {
-			/* text/html is preferable, so once we find it we're done... */
-			text_part = mime_part;
-			break;
-		} else if (camel_content_type_is (content_type, "text", "*")) {
-			/* anyt text part not text/html is second rate so the first
-			   text part we find isn't necessarily the one we'll use. */
-			if (!text_part)
-				text_part = mime_part;
-		} else {
-			e_msg_composer_attach (composer, mime_part);
-		}
-	}
-
-	if (text_part) {
-		ssize_t len;
-		char *html;
-
-		html = em_utils_part_to_html(text_part, &len, NULL);
-		e_msg_composer_set_pending_body(composer, html, len);
-	}
-}
-
-static void
-handle_multipart (EMsgComposer *composer, CamelMultipart *multipart, int depth)
-{
-	int i, nparts;
-
-	nparts = camel_multipart_get_number (multipart);
-
-	for (i = 0; i < nparts; i++) {
-		CamelContentType *content_type;
-		CamelDataWrapper *content;
-		CamelMimePart *mime_part;
-
-		mime_part = camel_multipart_get_part (multipart, i);
-
-		if (!mime_part)
-			continue;
-
-		content_type = camel_mime_part_get_content_type (mime_part);
-		content = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
-
-		if (CAMEL_IS_MULTIPART (content)) {
-			CamelMultipart *mp;
-
-			mp = CAMEL_MULTIPART (content);
-
-			if (CAMEL_IS_MULTIPART_SIGNED (content)) {
-				/* handle the signed content and configure the composer to sign outgoing messages */
-				handle_multipart_signed (composer, mp, depth + 1);
-			} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
-				/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
-				handle_multipart_encrypted (composer, mime_part, depth + 1);
-			} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
-				handle_multipart_alternative (composer, mp, depth + 1);
-			} else {
-				/* depth doesn't matter so long as we don't pass 0 */
-				handle_multipart (composer, mp, depth + 1);
-			}
-		} else if (depth == 0 && i == 0) {
-			ssize_t len;
-			char *html;
-
-			/* Since the first part is not multipart/alternative, then this must be the body */
-			html = em_utils_part_to_html(mime_part, &len, NULL);
-			e_msg_composer_set_pending_body(composer, html, len);
-		} else if (camel_mime_part_get_content_id (mime_part) ||
-			   camel_mime_part_get_content_location (mime_part)) {
-			/* special in-line attachment */
-			e_msg_composer_add_inline_image_from_mime_part (composer, mime_part);
-		} else {
-			/* normal attachment */
-			e_msg_composer_attach (composer, mime_part);
-		}
-	}
-}
-
-static void
-set_signature_gui (EMsgComposer *composer)
-{
-	CORBA_Environment ev;
-	EMsgComposerPrivate *p = composer->priv;
-	EMsgComposerHdrs *hdrs;
-	ESignature *signature = NULL;
-
-	hdrs = E_MSG_COMPOSER_HDRS (composer->priv->hdrs);
-
-	CORBA_exception_init (&ev);
-	if (GNOME_GtkHTML_Editor_Engine_searchByData (p->eeditor_engine, 1, "ClueFlow", "signature", "1", &ev)) {
-		char *name, *str = NULL;
-
-		str = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "signature_name", &ev);
-		if (ev._major == CORBA_NO_EXCEPTION && str) {
-			if (!strncmp (str, "uid:", 4)) {
-				name = decode_signature_name (str + 4);
-				signature = mail_config_get_signature_by_uid (name);
-				g_free (name);
-			} else if (!strncmp (str, "name:", 5)) {
-				name = decode_signature_name (str + 4);
-				signature = mail_config_get_signature_by_name (name);
-				g_free (name);
-			}
-			CORBA_free (str);
-		}
-
-		e_msg_composer_hdrs_set_signature (hdrs, signature);
-	}
-	CORBA_exception_free (&ev);
-}
-
-
-/**
- * e_msg_composer_new_with_message:
- * @message: The message to use as the source
- *
- * Create a new message composer widget.
- *
- * Note: Designed to work only for messages constructed using Evolution.
- *
- * Return value: A pointer to the newly created widget
- **/
-EMsgComposer *
-e_msg_composer_new_with_message (CamelMimeMessage *message)
-{
-	const CamelInternetAddress *to, *cc, *bcc;
-	GList *To = NULL, *Cc = NULL, *Bcc = NULL, *postto = NULL;
-	const char *format, *subject;
-	EDestination **Tov, **Ccv, **Bccv;
-	GHashTable *auto_cc, *auto_bcc;
-	CamelContentType *content_type;
-	struct _camel_header_raw *headers;
-	CamelDataWrapper *content;
-	EAccount *account = NULL;
-	char *account_name;
-	EMsgComposer *new;
-	struct _camel_header_raw *xev;
-	int len, i;
-	EMsgComposerPrivate *p;
-
-	for (headers = CAMEL_MIME_PART (message)->headers;headers;headers = headers->next) {
-		if (!strcmp(headers->name, "X-Evolution-PostTo"))
-			postto = g_list_append(postto, g_strstrip(g_strdup(headers->value)));
-	}
-
-	new = create_composer (postto ? E_MSG_COMPOSER_VISIBLE_MASK_POST : E_MSG_COMPOSER_VISIBLE_MASK_MAIL);
-	p = new->priv;
-
-	if (!new) {
-		g_list_foreach(postto, (GFunc)g_free, NULL);
-		g_list_free(postto);
-		return NULL;
-	}
-
-	if (postto) {
-		e_msg_composer_hdrs_set_post_to_list(E_MSG_COMPOSER_HDRS (p->hdrs), postto);
-		g_list_foreach(postto, (GFunc)g_free, NULL);
-		g_list_free(postto);
-		postto = NULL;
-	}
-
-	/* Restore the Account preference */
-	account_name = (char *) camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Account");
-	if (account_name) {
-		account_name = g_strdup (account_name);
-		g_strstrip (account_name);
-
-		if ((account = mail_config_get_account_by_uid(account_name)) == NULL)
-			/* 'old' setting */
-			account = mail_config_get_account_by_name(account_name);
-		if (account) {
-			g_free (account_name);
-			account_name = g_strdup (account->name);
-		}
-	}
-
-	if (postto == NULL) {
-		auto_cc = g_hash_table_new_full (
-			camel_strcase_hash, camel_strcase_equal,
-			(GDestroyNotify) g_free,
-			(GDestroyNotify) NULL);
-
-		auto_bcc = g_hash_table_new_full (
-			camel_strcase_hash, camel_strcase_equal,
-			(GDestroyNotify) g_free,
-			(GDestroyNotify) NULL);
-
-		if (account) {
-			CamelInternetAddress *iaddr;
-
-			/* hash our auto-recipients for this account */
-			if (account->always_cc) {
-				iaddr = camel_internet_address_new ();
-				if (camel_address_decode (CAMEL_ADDRESS (iaddr), account->cc_addrs) != -1) {
-					for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
-						const char *name, *addr;
-
-						if (!camel_internet_address_get (iaddr, i, &name, &addr))
-							continue;
-
-						g_hash_table_insert (auto_cc, g_strdup (addr), GINT_TO_POINTER (TRUE));
-					}
-				}
-				camel_object_unref (iaddr);
-			}
-
-			if (account->always_bcc) {
-				iaddr = camel_internet_address_new ();
-				if (camel_address_decode (CAMEL_ADDRESS (iaddr), account->bcc_addrs) != -1) {
-					for (i = 0; i < camel_address_length (CAMEL_ADDRESS (iaddr)); i++) {
-						const char *name, *addr;
-
-						if (!camel_internet_address_get (iaddr, i, &name, &addr))
-							continue;
-
-						g_hash_table_insert (auto_bcc, g_strdup (addr), GINT_TO_POINTER (TRUE));
-					}
-				}
-				camel_object_unref (iaddr);
-			}
-		}
-
-		to = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
-		cc = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
-		bcc = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
-
-		len = CAMEL_ADDRESS (to)->addresses->len;
-		for (i = 0; i < len; i++) {
-			const char *name, *addr;
-
-			if (camel_internet_address_get (to, i, &name, &addr)) {
-				EDestination *dest = e_destination_new ();
-				e_destination_set_name (dest, name);
-				e_destination_set_email (dest, addr);
-				To = g_list_append (To, dest);
-			}
-		}
-		Tov = destination_list_to_vector (To);
-		g_list_free (To);
-
-		len = CAMEL_ADDRESS (cc)->addresses->len;
-		for (i = 0; i < len; i++) {
-			const char *name, *addr;
-
-			if (camel_internet_address_get (cc, i, &name, &addr)) {
-				EDestination *dest = e_destination_new ();
-				e_destination_set_name (dest, name);
-				e_destination_set_email (dest, addr);
-
-				if (g_hash_table_lookup (auto_cc, addr))
-					e_destination_set_auto_recipient (dest, TRUE);
-
-				Cc = g_list_append (Cc, dest);
-			}
-		}
-
-		Ccv = destination_list_to_vector (Cc);
-		g_hash_table_destroy (auto_cc);
-		g_list_free (Cc);
-
-		len = CAMEL_ADDRESS (bcc)->addresses->len;
-		for (i = 0; i < len; i++) {
-			const char *name, *addr;
-
-			if (camel_internet_address_get (bcc, i, &name, &addr)) {
-				EDestination *dest = e_destination_new ();
-				e_destination_set_name (dest, name);
-				e_destination_set_email (dest, addr);
-
-				if (g_hash_table_lookup (auto_bcc, addr))
-					e_destination_set_auto_recipient (dest, TRUE);
-
-				Bcc = g_list_append (Bcc, dest);
-			}
-		}
-
-		Bccv = destination_list_to_vector (Bcc);
-		g_hash_table_destroy (auto_bcc);
-		g_list_free (Bcc);
-	} else {
-		Tov = NULL;
-		Ccv = NULL;
-		Bccv = NULL;
-	}
-
-	subject = camel_mime_message_get_subject (message);
-
-	e_msg_composer_set_headers (new, account_name, Tov, Ccv, Bccv, subject);
-
-	g_free (account_name);
-
-	e_destination_freev (Tov);
-	e_destination_freev (Ccv);
-	e_destination_freev (Bccv);
-
-	/* Restore the format editing preference */
-	format = camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Format");
-	if (format) {
-		char **flags;
-
-		while (*format && camel_mime_is_lwsp(*format))
-			format++;
-
-		flags = g_strsplit(format, ", ", 0);
-		for (i=0;flags[i];i++) {
-			printf("restoring draft flag '%s'\n", flags[i]);
-
-			if (g_ascii_strcasecmp(flags[i], "text/html") == 0)
-				e_msg_composer_set_send_html (new, TRUE);
-			else if (g_ascii_strcasecmp(flags[i], "text/plain") == 0)
-				e_msg_composer_set_send_html (new, FALSE);
-			else if (g_ascii_strcasecmp(flags[i], "pgp-sign") == 0)
-				e_msg_composer_set_pgp_sign(new, TRUE);
-			else if (g_ascii_strcasecmp(flags[i], "pgp-encrypt") == 0)
-				e_msg_composer_set_pgp_encrypt(new, TRUE);
-			else if (g_ascii_strcasecmp(flags[i], "smime-sign") == 0)
-				e_msg_composer_set_smime_sign(new, TRUE);
-			else if (g_ascii_strcasecmp(flags[i], "smime-encrypt") == 0)
-				e_msg_composer_set_smime_encrypt(new, TRUE);
-		}
-		g_strfreev(flags);
-	}
-
-	/* Remove any other X-Evolution-* headers that may have been set */
-	xev = mail_tool_remove_xevolution_headers (message);
-	camel_header_raw_clear(&xev);
-	
-	/* Check for receipt request */
-	if (camel_medium_get_header(CAMEL_MEDIUM(message), "Disposition-Notification-To")) {
-		e_msg_composer_set_request_receipt (new, TRUE);
-	}
-	
-	/* Check for mail priority */
-	if (camel_medium_get_header(CAMEL_MEDIUM(message), "X-Priority")) {
-		e_msg_composer_set_priority (new, TRUE);
-	}
-
-	/* set extra headers */
-	headers = CAMEL_MIME_PART (message)->headers;
-	while (headers) {
-		if (!is_special_header (headers->name) ||
-		    !g_ascii_strcasecmp (headers->name, "References") ||
-		    !g_ascii_strcasecmp (headers->name, "In-Reply-To")) {
-			g_ptr_array_add (p->extra_hdr_names, g_strdup (headers->name));
-			g_ptr_array_add (p->extra_hdr_values, g_strdup (headers->value));
-		}
-
-		headers = headers->next;
-	}
-
-	/* Restore the attachments and body text */
-	content = camel_medium_get_content_object (CAMEL_MEDIUM (message));
-	if (CAMEL_IS_MULTIPART (content)) {
-		CamelMultipart *multipart;
-
-		multipart = CAMEL_MULTIPART (content);
-		content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (message));
-
-		if (CAMEL_IS_MULTIPART_SIGNED (content)) {
-			/* handle the signed content and configure the composer to sign outgoing messages */
-			handle_multipart_signed (new, multipart, 0);
-		} else if (CAMEL_IS_MULTIPART_ENCRYPTED (content)) {
-			/* decrypt the encrypted content and configure the composer to encrypt outgoing messages */
-			handle_multipart_encrypted (new, CAMEL_MIME_PART (message), 0);
-		} else if (camel_content_type_is (content_type, "multipart", "alternative")) {
-			/* this contains the text/plain and text/html versions of the message body */
-			handle_multipart_alternative (new, multipart, 0);
-		} else {
-			/* there must be attachments... */
-			handle_multipart (new, multipart, 0);
-		}
-	} else {
-		ssize_t length;
-		char *html;
-
-		html = em_utils_part_to_html((CamelMimePart *)message, &length, NULL);
-		e_msg_composer_set_pending_body(new, html, length);
-	}
-
-	/* We wait until now to set the body text because we need to ensure that
-	 * the attachment bar has all the attachments, before we request them.
-	 */
-	e_msg_composer_flush_pending_body (new, TRUE);
-
-	set_signature_gui (new);
-
-	return new;
-}
-
-static void
-disable_editor (EMsgComposer *composer)
-{
-	CORBA_Environment ev;
-	EMsgComposerPrivate *p = composer->priv;
-
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "editable-off", &ev);
-	CORBA_exception_free (&ev);
-
-	gtk_widget_set_sensitive (p->attachment_bar, FALSE);
-
-	bonobo_ui_component_set_prop (p->uic, "/menu/Edit", "sensitive", "0", NULL);
-	bonobo_ui_component_set_prop (p->uic, "/menu/Format", "sensitive", "0", NULL);
-	bonobo_ui_component_set_prop (p->uic, "/menu/Insert", "sensitive", "0", NULL);
-}
-
-/**
- * e_msg_composer_new_redirect:
- * @message: The message to use as the source
- *
- * Create a new message composer widget.
- *
- * Return value: A pointer to the newly created widget
- **/
-EMsgComposer *
-e_msg_composer_new_redirect (CamelMimeMessage *message, const char *resent_from)
-{
-	EMsgComposer *composer;
-	EMsgComposerPrivate *p;
-	const char *subject;
-
-	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
-
-	composer = e_msg_composer_new_with_message (message);
-	p = composer->priv;
-
-	subject = camel_mime_message_get_subject (message);
-
-	p->redirect = message;
-	camel_object_ref (message);
-
-	e_msg_composer_set_headers (composer, resent_from, NULL, NULL, NULL, subject);
-
-	disable_editor (composer);
-
-	return composer;
-}
-
-
-static GList *
-add_recipients (GList *list, const char *recips)
-{
-	CamelInternetAddress *cia;
-	const char *name, *addr;
-	int num, i;
-
-	cia = camel_internet_address_new ();
-	num = camel_address_decode (CAMEL_ADDRESS (cia), recips);
-
-	for (i = 0; i < num; i++) {
-		if (camel_internet_address_get (cia, i, &name, &addr)) {
-			EDestination *dest = e_destination_new ();
-			e_destination_set_name (dest, name);
-			e_destination_set_email (dest, addr);
-
-			list = g_list_append (list, dest);
-		}
-	}
-
-	return list;
-}
-
-static void
-handle_mailto (EMsgComposer *composer, const char *mailto)
-{
-	EMsgComposerHdrs *hdrs;
-	EMsgComposerPrivate *priv = composer->priv;
-	GList *to = NULL, *cc = NULL, *bcc = NULL;
-	EDestination **tov, **ccv, **bccv;
-	char *subject = NULL, *body = NULL;
-	char *header, *content, *buf;
-	size_t nread, nwritten;
-	const char *p;
-	int len, clen;
-	CamelURL *url;
-
-	buf = g_strdup (mailto);
-
-	/* Parse recipients (everything after ':' until '?' or eos). */
-	p = buf + 7;
-	len = strcspn (p, "?");
-	if (len) {
-		content = g_strndup (p, len);
-		camel_url_decode (content);
-		to = add_recipients (to, content);
-		g_free (content);
-	}
-
-	p += len;
-	if (*p == '?') {
-		p++;
-
-		while (*p) {
-			len = strcspn (p, "=&");
-
-			/* If it's malformed, give up. */
-			if (p[len] != '=')
-				break;
-
-			header = (char *) p;
-			header[len] = '\0';
-			p += len + 1;
-
-			clen = strcspn (p, "&");
-
-			content = g_strndup (p, clen);
-			camel_url_decode (content);
-
-			if (!g_ascii_strcasecmp (header, "to")) {
-				to = add_recipients (to, content);
-			} else if (!g_ascii_strcasecmp (header, "cc")) {
-				cc = add_recipients (cc, content);
-			} else if (!g_ascii_strcasecmp (header, "bcc")) {
-				bcc = add_recipients (bcc, content);
-			} else if (!g_ascii_strcasecmp (header, "subject")) {
-				g_free (subject);
-				if (g_utf8_validate (content, -1, NULL)) {
-					subject = content;
-					content = NULL;
-				} else {
-					subject = g_locale_to_utf8 (content, clen, &nread,
-								    &nwritten, NULL);
-					if (subject) {
-						subject = g_realloc (subject, nwritten + 1);
-						subject[nwritten] = '\0';
-					}
-				}
-			} else if (!g_ascii_strcasecmp (header, "body")) {
-				g_free (body);
-				if (g_utf8_validate (content, -1, NULL)) {
-					body = content;
-					content = NULL;
-				} else {
-					body = g_locale_to_utf8 (content, clen, &nread,
-								 &nwritten, NULL);
-					if (body) {
-						body = g_realloc (body, nwritten + 1);
-						body[nwritten] = '\0';
-					}
-				}
-			} else if (!g_ascii_strcasecmp (header, "attach") ||
-				   !g_ascii_strcasecmp (header, "attachment")) {
-				/* Change file url to absolute path */
-				if (!g_ascii_strncasecmp (content, "file:", 5)) {
-					url = camel_url_new (content, NULL);
-					e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar),
-							 	 url->path,
-								 "attachment");
-					camel_url_free (url);
-				} else {
-					e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar),
-								 content,
-								 "attachment");
-				}
-				gtk_widget_show (priv->attachment_expander);
-				gtk_widget_show (priv->attachment_scrolled_window);
-			} else if (!g_ascii_strcasecmp (header, "from")) {
-				/* Ignore */
-			} else if (!g_ascii_strcasecmp (header, "reply-to")) {
-				/* ignore */
-			} else {
-				/* add an arbitrary header? */
-				e_msg_composer_add_header (composer, header, content);
-			}
-
-			g_free (content);
-
-			p += clen;
-			if (*p == '&') {
-				p++;
-				if (!strcmp (p, "amp;"))
-					p += 4;
-			}
-		}
-	}
-
-	g_free (buf);
-
-	tov  = destination_list_to_vector (to);
-	ccv  = destination_list_to_vector (cc);
-	bccv = destination_list_to_vector (bcc);
-
-	g_list_free (to);
-	g_list_free (cc);
-	g_list_free (bcc);
-
-	hdrs = E_MSG_COMPOSER_HDRS (priv->hdrs);
-
-	e_msg_composer_hdrs_set_to (hdrs, tov);
-	e_msg_composer_hdrs_set_cc (hdrs, ccv);
-	e_msg_composer_hdrs_set_bcc (hdrs, bccv);
-
-	e_destination_freev (tov);
-	e_destination_freev (ccv);
-	e_destination_freev (bccv);
-
-	if (subject) {
-		e_msg_composer_hdrs_set_subject (hdrs, subject);
-		g_free (subject);
-	}
-
-	if (body) {
-		char *htmlbody;
-
-		htmlbody = camel_text_to_html (body, CAMEL_MIME_FILTER_TOHTML_PRE, 0);
-		set_editor_text (composer, htmlbody, -1, FALSE, FALSE);
-		g_free (htmlbody);
-	}
-}
-
-static void
-handle_uri (EMsgComposer *composer, const char *uri, gboolean html_dnd)
-{
-	EMsgComposerPrivate *p = composer->priv;
-
-	if (!g_ascii_strncasecmp (uri, "mailto:";, 7)) {
-		handle_mailto (composer, uri);
-	} else {
-		CamelURL *url = camel_url_new (uri, NULL);
-		gchar *type;
-
-		if (!url)
-			return;
-
-		if (!g_ascii_strcasecmp (url->protocol, "file")) {
-			type = attachment_guess_mime_type (uri);
-			if (!type)
-				return;
-
-			if (strncmp (type, "image", 5) || !html_dnd || (!p->send_html && !strncmp (type, "image", 5))) {
-				e_attachment_bar_attach (E_ATTACHMENT_BAR (p->attachment_bar),
-						url->path, "attachment");
-			}
-			g_free (type);
-		} else	{
-			e_attachment_bar_attach_remote_file (E_ATTACHMENT_BAR (p->attachment_bar),
-					uri, "attachment");
-		}
-		camel_url_free (url);
-	}
-}
-
-/**
- * e_msg_composer_new_from_url:
- * @url: a mailto URL
- *
- * Create a new message composer widget, and fill in fields as
- * defined by the provided URL.
- **/
-EMsgComposer *
-e_msg_composer_new_from_url (const char *url)
-{
-	EMsgComposer *composer;
-
-	g_return_val_if_fail (g_ascii_strncasecmp (url, "mailto:";, 7) == 0, NULL);
-
-	composer = e_msg_composer_new ();
-	if (!composer)
-		return NULL;
-
-	handle_mailto (composer, url);
-
-	return composer;
-}
-
-/**
- * e_msg_composer_set_headers:
- * @composer: a composer object
- * @from: the name of the account the user will send from,
- * or %NULL for the default account
- * @to: the values for the "To" header
- * @cc: the values for the "Cc" header
- * @bcc: the values for the "Bcc" header
- * @subject: the value for the "Subject" header
- *
- * Sets the headers in the composer to the given values.
- **/
-void
-e_msg_composer_set_headers (EMsgComposer *composer,
-			    const char *from,
-			    EDestination **to,
-			    EDestination **cc,
-			    EDestination **bcc,
-			    const char *subject)
-{
-	EMsgComposerHdrs *hdrs;
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	hdrs = E_MSG_COMPOSER_HDRS (p->hdrs);
-
-	e_msg_composer_hdrs_set_to (hdrs, to);
-	e_msg_composer_hdrs_set_cc (hdrs, cc);
-	e_msg_composer_hdrs_set_bcc (hdrs, bcc);
-	e_msg_composer_hdrs_set_subject (hdrs, subject);
-	e_msg_composer_hdrs_set_from_account (hdrs, from);
-}
-
-
-/**
- * e_msg_composer_set_body_text:
- * @composer: a composer object
- * @text: the HTML text to initialize the editor with
- *
- * Loads the given HTML text into the editor.
- **/
-void
-e_msg_composer_set_body_text (EMsgComposer *composer, const char *text, ssize_t len)
-{
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-	g_return_if_fail (text != NULL);
-
-	set_editor_text (composer, text, len, TRUE, *text == '\0');
-}
-
-/**
- * e_msg_composer_set_body:
- * @composer: a composer object
- * @body: the data to initialize the composer with
- * @mime_type: the MIME type of data
- *
- * Loads the given data into the composer as the message body.
- * This function should only be used by the CORBA composer factory.
- **/
-void
-e_msg_composer_set_body (EMsgComposer *composer, const char *body,
-			 const char *mime_type)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	set_editor_text (composer, _("<b>(The composer contains a non-text message body, which cannot be edited.)</b>"), -1, FALSE, FALSE);
-	e_msg_composer_set_send_html (composer, FALSE);
-	disable_editor (composer);
-
-	g_free (p->mime_body);
-	p->mime_body = g_strdup (body);
-	g_free (p->mime_type);
-	p->mime_type = g_strdup (mime_type);
-
-	if (g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) == 0) {
-		EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (p->hdrs);
-		EAccount *account;
-
-		account = e_msg_composer_hdrs_get_from_account (hdrs);
-		if (account && account->pgp_no_imip_sign)
-			e_msg_composer_set_pgp_sign (composer, FALSE);
-	}
-}
-
-
-/**
- * e_msg_composer_add_header:
- * @composer: a composer object
- * @name: the header name
- * @value: the header value
- *
- * Adds a header with @name and @value to the message. This header
- * may not be displayed by the composer, but will be included in
- * the message it outputs.
- **/
-void
-e_msg_composer_add_header (EMsgComposer *composer, const char *name,
-			   const char *value)
-{
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-	g_return_if_fail (name != NULL);
-	g_return_if_fail (value != NULL);
-
-	g_ptr_array_add (p->extra_hdr_names, g_strdup (name));
-	g_ptr_array_add (p->extra_hdr_values, g_strdup (value));
-}
-/**
- * e_msg_composer_modify_header :
- * @composer : a composer object
- * @name: the header name
- * @change_value: the header value to put in place of the previous
- *                value
- *
- * Searches for a header with name= name ,if found it removes
- * that header and adds a new header with the @name and @change_value .
- * If not found then it creates a new header with @name and @change_value .
- **/
-void
-e_msg_composer_modify_header (EMsgComposer *composer, const char *name,
-			      const char *change_value)
-{
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-	g_return_if_fail (name != NULL);
-	g_return_if_fail (change_value != NULL);
-
-	e_msg_composer_remove_header (composer, name);
-	e_msg_composer_add_header (composer, name, change_value);
-}
-
-/**
- * e_msg_composer_modify_header :
- * @composer : a composer object
- * @name: the header name
- *
- * Searches for the header and if found it removes it .
- **/
-void
-e_msg_composer_remove_header (EMsgComposer *composer, const char *name)
-{
-	EMsgComposerPrivate *p;
-	int i;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-	g_return_if_fail (name != NULL);
-
-	p = composer->priv;
-
-	for (i = 0; i < p->extra_hdr_names->len; i++) {
-		if (strcmp (p->extra_hdr_names->pdata[i], name) == 0) {
-			g_print ("Hit : %s",name);
-			g_ptr_array_remove_index (p->extra_hdr_names, i);
-			g_ptr_array_remove_index (p->extra_hdr_values, i);
-		}
-	}
-}
-/**
- * e_msg_composer_attach:
- * @composer: a composer object
- * @attachment: the CamelMimePart to attach
- *
- * Attaches @attachment to the message being composed in the composer.
- **/
-void
-e_msg_composer_attach (EMsgComposer *composer, CamelMimePart *attachment)
-{
-	EAttachmentBar *bar;
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-	g_return_if_fail (CAMEL_IS_MIME_PART (attachment));
-
-	bar = E_ATTACHMENT_BAR (p->attachment_bar);
-	e_attachment_bar_attach_mime_part (bar, attachment);
-
-	show_attachments (composer, TRUE);
-}
-
-
-/**
- * e_msg_composer_add_inline_image_from_file:
- * @composer: a composer object
- * @file_name: the name of the file containing the image
- *
- * This reads in the image in @file_name and adds it to @composer
- * as an inline image, to be wrapped in a multipart/related.
- *
- * Return value: the newly-created CamelMimePart (which must be reffed
- * if the caller wants to keep its own reference), or %NULL on error.
- **/
-CamelMimePart *
-e_msg_composer_add_inline_image_from_file (EMsgComposer *composer,
-					   const char *file_name)
-{
-	char *mime_type, *cid, *url, *name, *dec_file_name;
-	CamelStream *stream;
-	CamelDataWrapper *wrapper;
-	CamelMimePart *part;
-	struct stat statbuf;
-	EMsgComposerPrivate *p = composer->priv;
-
-	dec_file_name = g_strdup(file_name);
-	camel_url_decode(dec_file_name);
-
-	/* check for regular file */
-	if (g_stat (dec_file_name, &statbuf) < 0 || !S_ISREG (statbuf.st_mode))
-		return NULL;
-
-	stream = camel_stream_fs_new_with_name (dec_file_name, O_RDONLY, 0);
-	if (!stream)
-		return NULL;
-
-	wrapper = camel_data_wrapper_new ();
-	camel_data_wrapper_construct_from_stream (wrapper, stream);
-	camel_object_unref (CAMEL_OBJECT (stream));
-
-	mime_type = e_msg_composer_guess_mime_type (dec_file_name);
-	camel_data_wrapper_set_mime_type (wrapper, mime_type ? mime_type : "application/octet-stream");
-	g_free (mime_type);
-
-	part = camel_mime_part_new ();
-	camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
-	camel_object_unref (wrapper);
-
-	cid = camel_header_msgid_generate ();
-	camel_mime_part_set_content_id (part, cid);
-	name = g_path_get_basename(dec_file_name);
-	camel_mime_part_set_filename (part, name);
-	g_free(name);
-	camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
-
-	url = g_strdup_printf ("file:%s", dec_file_name);
-	g_hash_table_insert (p->inline_images_by_url, url, part);
-
-	url = g_strdup_printf ("cid:%s", cid);
-	g_hash_table_insert (p->inline_images, url, part);
-	g_free (cid);
-
-	g_free(dec_file_name);
-
-	return part;
-}
-
-
-/**
- * e_msg_composer_add_inline_image_from_mime_part:
- * @composer: a composer object
- * @part: a CamelMimePart containing image data
- *
- * This adds the mime part @part to @composer as an inline image, to
- * be wrapped in a multipart/related.
- **/
-void
-e_msg_composer_add_inline_image_from_mime_part (EMsgComposer  *composer,
-						CamelMimePart *part)
-{
-	char *url;
-	const char *location, *cid;
-	EMsgComposerPrivate *p = composer->priv;
-
-	cid = camel_mime_part_get_content_id (part);
-	if (!cid) {
-		camel_mime_part_set_content_id (part, NULL);
-		cid = camel_mime_part_get_content_id (part);
-	}
-
-	url = g_strdup_printf ("cid:%s", cid);
-	g_hash_table_insert (p->inline_images, url, part);
-	camel_object_ref (part);
-
-	location = camel_mime_part_get_content_location (part);
-	if (location) {
-		g_hash_table_insert (p->inline_images_by_url,
-				     g_strdup (location), part);
-	}
-}
-
-
-/**
- * e_msg_composer_get_message:
- * @composer: A message composer widget
- *
- * Retrieve the message edited by the user as a CamelMimeMessage.  The
- * CamelMimeMessage object is created on the fly; subsequent calls to this
- * function will always create new objects from scratch.
- *
- * Return value: A pointer to the new CamelMimeMessage object
- **/
-CamelMimeMessage *
-e_msg_composer_get_message (EMsgComposer *composer, gboolean save_html_object_data)
-{
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
-	if ( e_msg_composer_get_remote_download_count (composer) != 0) {
-		if (!em_utils_prompt_user((GtkWindow *)composer, NULL, "mail-composer:ask-send-message-pending-download", NULL)) {
-			return NULL;
-		}
-	}
-
-	return build_message (composer, save_html_object_data);
-}
-
-CamelMimeMessage *
-e_msg_composer_get_message_print (EMsgComposer *composer, gboolean save_html_object_data)
-{
-	EMsgComposer *temp_composer;
-	CamelMimeMessage *msg;
-	GString *flags;
-
-	msg = build_message (composer, save_html_object_data);
-	if (msg == NULL)
-		return NULL;
-
-	temp_composer = e_msg_composer_new_with_message (msg);
-	camel_object_unref (msg);
-
-	/* build flags string */
-	flags = g_string_sized_new (128);
-	if (temp_composer->priv->send_html)
-		g_string_append (flags, "text/html");
-	else
-		g_string_append (flags, "text/plain");
-	if (temp_composer->priv->pgp_sign)
-		g_string_append (flags, ", pgp-sign");
-	if (temp_composer->priv->pgp_encrypt)
-		g_string_append (flags, ", pgp-encrypt");
-	if (temp_composer->priv->smime_sign)
-		g_string_append (flags, ", smime-sign");
-	if (temp_composer->priv->smime_encrypt)
-		g_string_append (flags, ", smime-encrypt");
-
-	/* override composer flags */
-	temp_composer->priv->send_html = TRUE;
-	temp_composer->priv->pgp_sign = FALSE;
-	temp_composer->priv->pgp_encrypt = FALSE;
-	temp_composer->priv->smime_sign = FALSE;
-	temp_composer->priv->smime_encrypt = FALSE;
-
-	msg = build_message (temp_composer, save_html_object_data);
-	if (msg != NULL)
-		camel_medium_set_header (
-			CAMEL_MEDIUM (msg),
-			"X-Evolution-Format", flags->str);
-
-	e_msg_composer_delete (temp_composer);
-	g_string_free (flags, TRUE);
-
-	return msg;
-}
-
-CamelMimeMessage *
-e_msg_composer_get_message_draft (EMsgComposer *composer)
-{
-	CamelMimeMessage *msg;
-	EAccount *account;
-	gboolean old_flags[4];
-	gboolean old_send_html;
-	GString *flags;
-	int i;
-	EMsgComposerPrivate *p = composer->priv;
-
-	/* always save drafts as HTML to preserve formatting */
-	old_send_html = p->send_html;
-	p->send_html = TRUE;
-	old_flags[0] = p->pgp_sign;
-	p->pgp_sign = FALSE;
-	old_flags[1] = p->pgp_encrypt;
-	p->pgp_encrypt = FALSE;
-	old_flags[2] = p->smime_sign;
-	p->smime_sign = FALSE;
-	old_flags[3] = p->smime_encrypt;
-	p->smime_encrypt = FALSE;
-
-	msg = build_message (composer, TRUE);
-	if (msg == NULL)
-		return NULL;
-
-	p->send_html = old_send_html;
-	p->pgp_sign = old_flags[0];
-	p->pgp_encrypt = old_flags[1];
-	p->smime_sign = old_flags[2];
-	p->smime_encrypt = old_flags[3];
-
-	/* Attach account info to the draft. */
-	account = e_msg_composer_get_preferred_account (composer);
-	if (account && account->name)
-		camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Account", account->uid);
-
-	/* build_message() set this to text/html since we set p->send_html to
-	   TRUE before calling e_msg_composer_get_message() */
-	if (!p->send_html)
-		flags = g_string_new("text/plain");
-	else
-		flags = g_string_new("text/html");
-
-	/* This should probably only save the setting if it is
-	 * different from the from-account default? */
-	for (i=0;i<4;i++) {
-		if (old_flags[i])
-			g_string_append_printf(flags, ", %s", emc_draft_format_names[i]);
-	}
-
-	camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Format", flags->str);
-	g_string_free(flags, TRUE);
-
-	return msg;
-}
-
-
-static void
-delete_old_signature (EMsgComposer *composer)
-{
-	CORBA_Environment ev;
-	EMsgComposerPrivate *p = composer->priv;
-
-	/* printf ("delete_old_signature\n"); */
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "block-selection", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "cursor-bod", &ev);
-	if (GNOME_GtkHTML_Editor_Engine_searchByData (p->eeditor_engine, 1, "ClueFlow", "signature", "1", &ev)) {
-		/* printf ("found\n"); */
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "select-paragraph", &ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "delete", &ev);
-		/* selection-move-right doesn't succeed means that we are already on the end of document */
-		/* if (!rv)
-		   break; */
-		GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "signature", "0", &ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "delete-back", &ev);
-	}
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "unblock-selection", &ev);
-	CORBA_exception_free (&ev);
-}
-
-
-/**
- * e_msg_composer_show_sig:
- * @composer: A message composer widget
- *
- * Set a signature
- **/
-void
-e_msg_composer_show_sig_file (EMsgComposer *composer)
-{
-	CORBA_Environment ev;
-	char *html;
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	/* printf ("e_msg_composer_show_sig_file\n"); */
-	/* printf ("set sig '%s' '%s'\n", sig_file, p->sig_file); */
-	if (!p->redirect) {
-		p->in_signature_insert = TRUE;
-		CORBA_exception_init (&ev);
-		GNOME_GtkHTML_Editor_Engine_freeze (p->eeditor_engine, &ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "cursor-position-save", &ev);
-		GNOME_GtkHTML_Editor_Engine_undoBegin (p->eeditor_engine, "Set signature", "Reset signature", &ev);
-
-		delete_old_signature (composer);
-		html = get_signature_html (composer);
-		if (html) {
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "insert-paragraph", &ev);
-			if (!GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "cursor-backward", &ev))
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "insert-paragraph", &ev);
-			else
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "cursor-forward", &ev);
-		/* printf ("insert %s\n", html); */
-			GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "orig", "0", &ev);
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "indent-zero", &ev);
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "style-normal", &ev);
-			GNOME_GtkHTML_Editor_Engine_insertHTML (p->eeditor_engine, html, &ev);
-			g_free (html);
-		}
-
-		GNOME_GtkHTML_Editor_Engine_undoEnd (p->eeditor_engine, &ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "cursor-position-restore", &ev);
-		GNOME_GtkHTML_Editor_Engine_thaw (p->eeditor_engine, &ev);
-		CORBA_exception_free (&ev);
-		p->in_signature_insert = FALSE;
-	}
-	/* printf ("e_msg_composer_show_sig_file end\n"); */
-}
-
-
-/**
- * e_msg_composer_set_send_html:
- * @composer: A message composer widget
- * @send_html: Whether the composer should have the "Send HTML" flag set
- *
- * Set the status of the "Send HTML" toggle item.  The user can override it.
- **/
-void
-e_msg_composer_set_send_html (EMsgComposer *composer,
-			      gboolean send_html)
-{
-	CORBA_Environment ev;
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	if (p->send_html && send_html)
-		return;
-
-	if (!p->send_html && !send_html)
-		return;
-
-	p->send_html = send_html;
-
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "block-redraw", &ev);
-	CORBA_exception_free (&ev);
-
-	bonobo_ui_component_set_prop (p->uic, "/commands/FormatHtml",
-				      "state", p->send_html ? "1" : "0", NULL);
-
-	/* let the editor know which mode we are in */
-	bonobo_widget_set_property (BONOBO_WIDGET (p->eeditor),
-				    "FormatHTML", TC_CORBA_boolean,
-				    p->send_html, NULL);
-
-
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "unblock-redraw", &ev);
-	CORBA_exception_free (&ev);
-}
-
-
-/**
- * e_msg_composer_get_send_html:
- * @composer: A message composer widget
- *
- * Get the status of the "Send HTML mail" flag.
- *
- * Return value: The status of the "Send HTML mail" flag.
- **/
-gboolean
-e_msg_composer_get_send_html (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
-
-	return p->send_html;
-}
-
-
-/**
- * e_msg_composer_get_preferred_account:
- * @composer: composer
- *
- * Returns the user-specified account (from field).
- */
-EAccount *
-e_msg_composer_get_preferred_account (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	EMsgComposerHdrs *hdrs;
-
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
-
-	hdrs = E_MSG_COMPOSER_HDRS (p->hdrs);
-
-	return e_msg_composer_hdrs_get_from_account (hdrs);
-}
-
-
-/**
- * e_msg_composer_set_pgp_sign:
- * @composer: A message composer widget
- * @send_html: Whether the composer should have the "PGP Sign" flag set
- *
- * Set the status of the "PGP Sign" toggle item.  The user can override it.
- **/
-void
-e_msg_composer_set_pgp_sign (EMsgComposer *composer, gboolean pgp_sign)
-{
-	EMsgComposerPrivate *p = composer->priv;
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	if (p->pgp_sign && pgp_sign)
-		return;
-	if (!p->pgp_sign && !pgp_sign)
-		return;
+	editor = GTKHTML_EDITOR (composer);
 
-	p->pgp_sign = pgp_sign;
-	e_msg_composer_set_changed (composer);
+	g_signal_emit (composer, signals[SAVE_DRAFT], 0, FALSE);
 
-	bonobo_ui_component_set_prop (p->uic, "/commands/SecurityPGPSign",
-				      "state", p->pgp_sign ? "1" : "0", NULL);
+	/* XXX This should be elsewhere. */
+	gtkhtml_editor_set_changed (editor, FALSE);
+	e_composer_autosave_set_saved (composer, FALSE);
 }
 
-
-/**
- * e_msg_composer_get_pgp_sign:
- * @composer: A message composer widget
- *
- * Get the status of the "PGP Sign" flag.
- *
- * Return value: The status of the "PGP Sign" flag.
- **/
-gboolean
-e_msg_composer_get_pgp_sign (EMsgComposer *composer)
+static GList *
+add_recipients (GList *list, const gchar *recips)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	CamelInternetAddress *cia;
+	const gchar *name, *addr;
+	gint num, i;
 
-	return p->pgp_sign;
-}
+	cia = camel_internet_address_new ();
+	num = camel_address_decode (CAMEL_ADDRESS (cia), recips);
 
+	for (i = 0; i < num; i++) {
+		if (camel_internet_address_get (cia, i, &name, &addr)) {
+			EDestination *dest = e_destination_new ();
+			e_destination_set_name (dest, name);
+			e_destination_set_email (dest, addr);
 
-/**
- * e_msg_composer_set_pgp_encrypt:
- * @composer: A message composer widget
- * @send_html: Whether the composer should have the "PGP Encrypt" flag set
- *
- * Set the status of the "PGP Encrypt" toggle item.  The user can override it.
- **/
-void
-e_msg_composer_set_pgp_encrypt (EMsgComposer *composer, gboolean pgp_encrypt)
+			list = g_list_append (list, dest);
+		}
+	}
+
+	return list;
+}
+
+static void
+handle_mailto (EMsgComposer *composer, const gchar *mailto)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	EMsgComposerPrivate *priv = composer->priv;
+	EComposerHeaderTable *table;
+	GList *to = NULL, *cc = NULL, *bcc = NULL;
+	EDestination **tov, **ccv, **bccv;
+	gchar *subject = NULL, *body = NULL;
+	gchar *header, *content, *buf;
+	gsize nread, nwritten;
+	const gchar *p;
+	gint len, clen;
+	CamelURL *url;
 
-	if (p->pgp_encrypt && pgp_encrypt)
-		return;
-	if (!p->pgp_encrypt && !pgp_encrypt)
-		return;
+	table = e_msg_composer_get_header_table (composer);
 
-	p->pgp_encrypt = pgp_encrypt;
-	e_msg_composer_set_changed (composer);
+	buf = g_strdup (mailto);
 
-	bonobo_ui_component_set_prop (p->uic, "/commands/SecurityPGPEncrypt",
-				      "state", p->pgp_encrypt ? "1" : "0", NULL);
-}
+	/* Parse recipients (everything after ':' until '?' or eos). */
+	p = buf + 7;
+	len = strcspn (p, "?");
+	if (len) {
+		content = g_strndup (p, len);
+		camel_url_decode (content);
+		to = add_recipients (to, content);
+		g_free (content);
+	}
 
+	p += len;
+	if (*p == '?') {
+		p++;
 
-/**
- * e_msg_composer_get_pgp_encrypt:
- * @composer: A message composer widget
- *
- * Get the status of the "PGP Encrypt" flag.
- *
- * Return value: The status of the "PGP Encrypt" flag.
- **/
-gboolean
-e_msg_composer_get_pgp_encrypt (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+		while (*p) {
+			len = strcspn (p, "=&");
 
-	return p->pgp_encrypt;
-}
+			/* If it's malformed, give up. */
+			if (p[len] != '=')
+				break;
 
+			header = (char *) p;
+			header[len] = '\0';
+			p += len + 1;
 
-/**
- * e_msg_composer_set_smime_sign:
- * @composer: A message composer widget
- * @send_html: Whether the composer should have the "S/MIME Sign" flag set
- *
- * Set the status of the "S/MIME Sign" toggle item.  The user can override it.
- **/
-void
-e_msg_composer_set_smime_sign (EMsgComposer *composer, gboolean smime_sign)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+			clen = strcspn (p, "&");
 
-	if (p->smime_sign && smime_sign)
-		return;
-	if (!p->smime_sign && !smime_sign)
-		return;
+			content = g_strndup (p, clen);
+			camel_url_decode (content);
+
+			if (!g_ascii_strcasecmp (header, "to")) {
+				to = add_recipients (to, content);
+			} else if (!g_ascii_strcasecmp (header, "cc")) {
+				cc = add_recipients (cc, content);
+			} else if (!g_ascii_strcasecmp (header, "bcc")) {
+				bcc = add_recipients (bcc, content);
+			} else if (!g_ascii_strcasecmp (header, "subject")) {
+				g_free (subject);
+				if (g_utf8_validate (content, -1, NULL)) {
+					subject = content;
+					content = NULL;
+				} else {
+					subject = g_locale_to_utf8 (content, clen, &nread,
+								    &nwritten, NULL);
+					if (subject) {
+						subject = g_realloc (subject, nwritten + 1);
+						subject[nwritten] = '\0';
+					}
+				}
+			} else if (!g_ascii_strcasecmp (header, "body")) {
+				g_free (body);
+				if (g_utf8_validate (content, -1, NULL)) {
+					body = content;
+					content = NULL;
+				} else {
+					body = g_locale_to_utf8 (content, clen, &nread,
+								 &nwritten, NULL);
+					if (body) {
+						body = g_realloc (body, nwritten + 1);
+						body[nwritten] = '\0';
+					}
+				}
+			} else if (!g_ascii_strcasecmp (header, "attach") ||
+				   !g_ascii_strcasecmp (header, "attachment")) {
+				/* Change file url to absolute path */
+				if (!g_ascii_strncasecmp (content, "file:", 5)) {
+					url = camel_url_new (content, NULL);
+					e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar),
+							 	 url->path,
+								 "attachment");
+					camel_url_free (url);
+				} else {
+					e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar),
+								 content,
+								 "attachment");
+				}
+				gtk_widget_show (priv->attachment_expander);
+				gtk_widget_show (priv->attachment_scrolled_window);
+			} else if (!g_ascii_strcasecmp (header, "from")) {
+				/* Ignore */
+			} else if (!g_ascii_strcasecmp (header, "reply-to")) {
+				/* ignore */
+			} else {
+				/* add an arbitrary header? */
+				e_msg_composer_add_header (composer, header, content);
+			}
 
-	p->smime_sign = smime_sign;
-	e_msg_composer_set_changed (composer);
+			g_free (content);
 
-	bonobo_ui_component_set_prop (p->uic, "/commands/SecuritySMimeSign",
-				      "state", p->smime_sign ? "1" : "0", NULL);
-}
+			p += clen;
+			if (*p == '&') {
+				p++;
+				if (!strcmp (p, "amp;"))
+					p += 4;
+			}
+		}
+	}
 
+	g_free (buf);
 
-/**
- * e_msg_composer_get_smime_sign:
- * @composer: A message composer widget
- *
- * Get the status of the "S/MIME Sign" flag.
- *
- * Return value: The status of the "S/MIME Sign" flag.
- **/
-gboolean
-e_msg_composer_get_smime_sign (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	tov  = destination_list_to_vector (to);
+	ccv  = destination_list_to_vector (cc);
+	bccv = destination_list_to_vector (bcc);
 
-	return p->smime_sign;
-}
+	g_list_free (to);
+	g_list_free (cc);
+	g_list_free (bcc);
 
+	e_composer_header_table_set_destinations_to (table, tov);
+	e_composer_header_table_set_destinations_cc (table, ccv);
+	e_composer_header_table_set_destinations_bcc (table, bccv);
 
-/**
- * e_msg_composer_set_smime_encrypt:
- * @composer: A message composer widget
- * @send_html: Whether the composer should have the "S/MIME Encrypt" flag set
- *
- * Set the status of the "S/MIME Encrypt" toggle item.  The user can override it.
- **/
-void
-e_msg_composer_set_smime_encrypt (EMsgComposer *composer, gboolean smime_encrypt)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	e_destination_freev (tov);
+	e_destination_freev (ccv);
+	e_destination_freev (bccv);
 
-	if (p->smime_encrypt && smime_encrypt)
-		return;
-	if (!p->smime_encrypt && !smime_encrypt)
-		return;
+	e_composer_header_table_set_subject (table, subject);
+	g_free (subject);
 
-	p->smime_encrypt = smime_encrypt;
-	e_msg_composer_set_changed (composer);
+	if (body) {
+		gchar *htmlbody;
 
-	bonobo_ui_component_set_prop (p->uic, "/commands/SecuritySMimeEncrypt",
-				      "state", p->smime_encrypt ? "1" : "0", NULL);
+		htmlbody = camel_text_to_html (body, CAMEL_MIME_FILTER_TOHTML_PRE, 0);
+		set_editor_text (composer, htmlbody, FALSE);
+		g_free (htmlbody);
+	}
 }
 
-
-/**
- * e_msg_composer_get_smime_encrypt:
- * @composer: A message composer widget
- *
- * Get the status of the "S/MIME Encrypt" flag.
- *
- * Return value: The status of the "S/MIME Encrypt" flag.
- **/
-gboolean
-e_msg_composer_get_smime_encrypt (EMsgComposer *composer)
+static void
+handle_uri (EMsgComposer *composer,
+            const gchar *uri,
+            gboolean html_dnd)
 {
 	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	GtkhtmlEditor *editor;
+	gboolean html_content;
 
-	return p->smime_encrypt;
-}
+	editor = GTKHTML_EDITOR (composer);
+	html_content = gtkhtml_editor_get_html_mode (editor);
 
+	if (!g_ascii_strncasecmp (uri, "mailto:";, 7)) {
+		handle_mailto (composer, uri);
+	} else {
+		CamelURL *url = camel_url_new (uri, NULL);
+		gchar *type;
 
-/**
- * e_msg_composer_get_view_from:
- * @composer: A message composer widget
- *
- * Get the status of the "View From header" flag.
- *
- * Return value: The status of the "View From header" flag.
- **/
-gboolean
-e_msg_composer_get_view_from (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+		if (!url)
+			return;
 
-	return p->view_from;
-}
+		if (!g_ascii_strcasecmp (url->protocol, "file")) {
+			type = e_msg_composer_guess_mime_type (uri);
+			if (!type)
+				return;
 
+			if (strncmp (type, "image", 5) || !html_dnd || (!html_content && !strncmp (type, "image", 5))) {
+				e_attachment_bar_attach (E_ATTACHMENT_BAR (p->attachment_bar),
+						url->path, "attachment");
+			}
+			g_free (type);
+		} else	{
+			e_attachment_bar_attach_remote_file (E_ATTACHMENT_BAR (p->attachment_bar),
+					uri, "attachment");
+		}
+		camel_url_free (url);
+	}
+}
 
 /**
- * e_msg_composer_set_view_from:
- * @composer: A message composer widget
- * @state: whether to show or hide the From selector
+ * e_msg_composer_new_from_url:
+ * @url: a mailto URL
  *
- * Controls the state of the From selector
- */
-void
-e_msg_composer_set_view_from (EMsgComposer *composer, gboolean view_from)
+ * Create a new message composer widget, and fill in fields as
+ * defined by the provided URL.
+ **/
+EMsgComposer *
+e_msg_composer_new_from_url (const gchar *url)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	GConfClient *gconf;
-	GError *error = NULL;
-	
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	if ((p->view_from && view_from) ||
-	    (!p->view_from && !view_from))
-		return;
+	EMsgComposer *composer;
 
-	p->view_from = view_from;
-	bonobo_ui_component_set_prop (p->uic, "/commands/ViewFrom",
-				      "state", p->view_from ? "1" : "0", NULL);
+	g_return_val_if_fail (g_ascii_strncasecmp (url, "mailto:";, 7) == 0, NULL);
 
-	gconf = gconf_client_get_default ();
-	if (!gconf_client_set_bool (gconf, "/apps/evolution/mail/composer/view/From", view_from, &error)) {
-		g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-		g_error_free(error);
-	}
-	
-	g_object_unref (gconf);
+	composer = e_msg_composer_new ();
+	if (!composer)
+		return NULL;
 
-	e_msg_composer_hdrs_set_visible (E_MSG_COMPOSER_HDRS (p->hdrs),
-					 e_msg_composer_get_visible_flags (composer));
-}
+	handle_mailto (composer, url);
 
+	return composer;
+}
 
 /**
- * e_msg_composer_get_view_replyto:
- * @composer: A message composer widget
- *
- * Get the status of the "View Reply-To header" flag.
+ * e_msg_composer_set_body_text:
+ * @composer: a composer object
+ * @text: the HTML text to initialize the editor with
  *
- * Return value: The status of the "View Reply-To header" flag.
+ * Loads the given HTML text into the editor.
  **/
-gboolean
-e_msg_composer_get_view_replyto (EMsgComposer *composer)
+void
+e_msg_composer_set_body_text (EMsgComposer *composer,
+                              const gchar *text,
+                              gssize len)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (text != NULL);
 
-	return p->view_replyto;
+	set_editor_text (composer, text, TRUE);
 }
 
-
 /**
- * e_msg_composer_set_view_replyto:
- * @composer: A message composer widget
- * @state: whether to show or hide the Reply-To selector
+ * e_msg_composer_set_body:
+ * @composer: a composer object
+ * @body: the data to initialize the composer with
+ * @mime_type: the MIME type of data
  *
- * Controls the state of the Reply-To selector
- */
+ * Loads the given data ginto the composer as the message body.
+ * This function should only be used by the CORBA composer factory.
+ **/
 void
-e_msg_composer_set_view_replyto (EMsgComposer *composer, gboolean view_replyto)
+e_msg_composer_set_body (EMsgComposer *composer,
+                         const gchar *body,
+			 const gchar *mime_type)
 {
 	EMsgComposerPrivate *p = composer->priv;
-	GConfClient *gconf;
-	GError *error = NULL;
-	
+	EComposerHeaderTable *table;
+
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	if ((p->view_replyto && view_replyto) ||
-	    (!p->view_replyto && !view_replyto))
-		return;
+	table = e_msg_composer_get_header_table (composer);
 
-	p->view_replyto = view_replyto;
-	bonobo_ui_component_set_prop (p->uic, "/commands/ViewReplyTo",
-				      "state", p->view_replyto ? "1" : "0", NULL);
+	set_editor_text (composer, _("<b>(The composer contains a non-text message body, which cannot be edited.)</b>"), FALSE);
+	gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (composer), FALSE);
+	disable_editor (composer);
 
-	/* we do this /only/ if the fields is in the visible_mask */
-	gconf = gconf_client_get_default ();
-	if (!gconf_client_set_bool (gconf, "/apps/evolution/mail/composer/view/ReplyTo", view_replyto, &error)) {
-		g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-		g_error_free(error);
-	}
-	g_object_unref (gconf);
+	g_free (p->mime_body);
+	p->mime_body = g_strdup (body);
+	g_free (p->mime_type);
+	p->mime_type = g_strdup (mime_type);
 
-	e_msg_composer_hdrs_set_visible (E_MSG_COMPOSER_HDRS (p->hdrs),
-					 e_msg_composer_get_visible_flags (composer));
-}
+	if (g_ascii_strncasecmp (p->mime_type, "text/calendar", 13) == 0) {
+		EAccount *account;
 
+		account = e_composer_header_table_get_account (table);
+		if (account && account->pgp_no_imip_sign) {
+			GtkToggleAction *action;
+
+			action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+			gtk_toggle_action_set_active (action, FALSE);
+		}
+	}
+}
 
 /**
- * e_msg_composer_get_view_to:
- * @composer: A message composer widget
- *
- * Get the status of the "View To header" flag.
+ * e_msg_composer_add_header:
+ * @composer: a composer object
+ * @name: the header name
+ * @value: the header value
  *
- * Return value: The status of the "View To header" flag.
+ * Adds a header with @name and @value to the message. This header
+ * may not be displayed by the composer, but will be included in
+ * the message it outputs.
  **/
-gboolean
-e_msg_composer_get_view_to (EMsgComposer *composer)
+void
+e_msg_composer_add_header (EMsgComposer *composer,
+                           const gchar *name,
+			   const gchar *value)
 {
 	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
 
-	return p->view_to;
-}
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (name != NULL);
+	g_return_if_fail (value != NULL);
 
+	g_ptr_array_add (p->extra_hdr_names, g_strdup (name));
+	g_ptr_array_add (p->extra_hdr_values, g_strdup (value));
+}
 
 /**
- * e_msg_composer_set_view_to:
- * @composer: A message composer widget
- * @state: whether to show or hide the To selector
+ * e_msg_composer_modify_header :
+ * @composer : a composer object
+ * @name: the header name
+ * @change_value: the header value to put in place of the previous
+ *                value
  *
- * Controls the state of the To selector
- */
+ * Searches for a header with name= name ,if found it removes
+ * that header and adds a new header with the @name and @change_value .
+ * If not found then it creates a new header with @name and @change_value .
+ **/
 void
-e_msg_composer_set_view_to (EMsgComposer *composer, gboolean view_to)
+e_msg_composer_modify_header (EMsgComposer *composer,
+                              const gchar *name,
+			      const gchar *change_value)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	GConfClient *gconf;
-	GError *error = NULL;
-	
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (name != NULL);
+	g_return_if_fail (change_value != NULL);
 
-	if ((p->view_to && view_to) ||
-	    (!p->view_to && !view_to))
-		return;
+	e_msg_composer_remove_header (composer, name);
+	e_msg_composer_add_header (composer, name, change_value);
+}
+
+/**
+ * e_msg_composer_modify_header :
+ * @composer : a composer object
+ * @name: the header name
+ *
+ * Searches for the header and if found it removes it .
+ **/
+void
+e_msg_composer_remove_header (EMsgComposer *composer,
+                              const gchar *name)
+{
+	EMsgComposerPrivate *p;
+	gint i;
+
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (name != NULL);
 
-	p->view_to = view_to;
-	bonobo_ui_component_set_prop (p->uic, "/commands/ViewTo",
-				      "state", p->view_to ? "1" : "0", NULL);
+	p = composer->priv;
 
-	if ((E_MSG_COMPOSER_HDRS(p->hdrs))->visible_mask & E_MSG_COMPOSER_VISIBLE_TO) {
-		gconf = gconf_client_get_default ();
-		if (!gconf_client_set_bool (gconf, "/apps/evolution/mail/composer/view/To", view_to, &error)) {
-			g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-			g_error_free(error);
+	for (i = 0; i < p->extra_hdr_names->len; i++) {
+		if (strcmp (p->extra_hdr_names->pdata[i], name) == 0) {
+			g_ptr_array_remove_index (p->extra_hdr_names, i);
+			g_ptr_array_remove_index (p->extra_hdr_values, i);
 		}
-		g_object_unref (gconf);
 	}
-
-	e_msg_composer_hdrs_set_visible (E_MSG_COMPOSER_HDRS (p->hdrs),
-					 e_msg_composer_get_visible_flags (composer));
 }
 
-
-
 /**
- * e_msg_composer_get_view_postto:
- * @composer: A message composer widget
- *
- * Get the status of the "View PostTo header" flag.
+ * e_msg_composer_attach:
+ * @composer: a composer object
+ * @attachment: the CamelMimePart to attach
  *
- * Return value: The status of the "View PostTo header" flag.
+ * Attaches @attachment to the message being composed in the composer.
  **/
-gboolean
-e_msg_composer_get_view_postto (EMsgComposer *composer)
+void
+e_msg_composer_attach (EMsgComposer *composer, CamelMimePart *attachment)
 {
+	EAttachmentBar *bar;
 	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
 
-	return p->view_postto;
-}
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_if_fail (CAMEL_IS_MIME_PART (attachment));
 
+	bar = E_ATTACHMENT_BAR (p->attachment_bar);
+	e_attachment_bar_attach_mime_part (bar, attachment);
+}
 
 /**
- * e_msg_composer_set_view_postto:
- * @composer: A message composer widget
- * @state: whether to show or hide the PostTo selector
+ * e_msg_composer_add_inline_image_from_file:
+ * @composer: a composer object
+ * @filename: the name of the file containing the image
  *
- * Controls the state of the PostTo selector
- */
-void
-e_msg_composer_set_view_postto (EMsgComposer *composer, gboolean view_postto)
+ * This reads in the image in @filename and adds it to @composer
+ * as an inline image, to be wrapped in a multipart/related.
+ *
+ * Returns: the newly-created CamelMimePart (which must be reffed
+ * if the caller wants to keep its own reference), or %NULL on error.
+ **/
+CamelMimePart *
+e_msg_composer_add_inline_image_from_file (EMsgComposer *composer,
+					   const gchar *filename)
 {
-	GConfClient *gconf;
-	GError *error = NULL;
-	
+	gchar *mime_type, *cid, *url, *name, *dec_file_name;
+	CamelStream *stream;
+	CamelDataWrapper *wrapper;
+	CamelMimePart *part;
 	EMsgComposerPrivate *p = composer->priv;
 
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	dec_file_name = g_strdup (filename);
+	camel_url_decode (dec_file_name);
 
-	if ((p->view_postto && view_postto) ||
-	    (!p->view_postto && !view_postto))
-		return;
+	if (!g_file_test (dec_file_name, G_FILE_TEST_IS_REGULAR))
+		return NULL;
+
+	stream = camel_stream_fs_new_with_name (dec_file_name, O_RDONLY, 0);
+	if (!stream)
+		return NULL;
 
-	p->view_postto = view_postto;
-	bonobo_ui_component_set_prop (p->uic, "/commands/ViewPostTo",
-				      "state", p->view_postto ? "1" : "0", NULL);
+	wrapper = camel_data_wrapper_new ();
+	camel_data_wrapper_construct_from_stream (wrapper, stream);
+	camel_object_unref (CAMEL_OBJECT (stream));
 
-	if ((E_MSG_COMPOSER_HDRS(p->hdrs))->visible_mask & E_MSG_COMPOSER_VISIBLE_POSTTO) {
-		gconf = gconf_client_get_default ();
-		if (!gconf_client_set_bool (gconf, "/apps/evolution/mail/composer/view/PostTo", view_postto, &error)) {
-			g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-			g_error_free(error);
-		}
-		g_object_unref (gconf);
-	}
+	mime_type = e_msg_composer_guess_mime_type (dec_file_name);
+	if (mime_type == NULL)
+		mime_type = g_strdup ("application/octet-stream");
+	camel_data_wrapper_set_mime_type (wrapper, mime_type);
+	g_free (mime_type);
 
-	e_msg_composer_hdrs_set_visible (E_MSG_COMPOSER_HDRS (p->hdrs),
-					 e_msg_composer_get_visible_flags (composer));
-}
+	part = camel_mime_part_new ();
+	camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
+	camel_object_unref (wrapper);
+
+	cid = camel_header_msgid_generate ();
+	camel_mime_part_set_content_id (part, cid);
+	name = g_path_get_basename (dec_file_name);
+	camel_mime_part_set_filename (part, name);
+	g_free (name);
+	camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
+
+	url = g_strdup_printf ("file:%s", dec_file_name);
+	g_hash_table_insert (p->inline_images_by_url, url, part);
+
+	url = g_strdup_printf ("cid:%s", cid);
+	g_hash_table_insert (p->inline_images, url, part);
+	g_free (cid);
 
+	g_free (dec_file_name);
 
+	return part;
+}
 
 /**
- * e_msg_composer_get_view_cc:
- * @composer: A message composer widget
- *
- * Get the status of the "View CC header" flag.
+ * e_msg_composer_add_inline_image_from_mime_part:
+ * @composer: a composer object
+ * @part: a CamelMimePart containing image data
  *
- * Return value: The status of the "View CC header" flag.
+ * This adds the mime part @part to @composer as an inline image, to
+ * be wrapped in a multipart/related.
  **/
-gboolean
-e_msg_composer_get_view_cc (EMsgComposer *composer)
+void
+e_msg_composer_add_inline_image_from_mime_part (EMsgComposer  *composer,
+						CamelMimePart *part)
 {
+	gchar *url;
+	const gchar *location, *cid;
 	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
 
-	return p->view_cc;
-}
+	cid = camel_mime_part_get_content_id (part);
+	if (!cid) {
+		camel_mime_part_set_content_id (part, NULL);
+		cid = camel_mime_part_get_content_id (part);
+	}
+
+	url = g_strdup_printf ("cid:%s", cid);
+	g_hash_table_insert (p->inline_images, url, part);
+	camel_object_ref (part);
 
+	location = camel_mime_part_get_content_location (part);
+	if (location != NULL)
+		g_hash_table_insert (
+			p->inline_images_by_url,
+			g_strdup (location), part);
+}
 
 /**
- * e_msg_composer_set_view_cc:
+ * e_msg_composer_get_message:
  * @composer: A message composer widget
- * @state: whether to show or hide the cc view
  *
- * Controls the state of the CC display
- */
-void
-e_msg_composer_set_view_cc (EMsgComposer *composer, gboolean view_cc)
+ * Retrieve the message edited by the user as a CamelMimeMessage.  The
+ * CamelMimeMessage object is created on the fly; subsequent calls to this
+ * function will always create new objects from scratch.
+ *
+ * Returns: A pointer to the new CamelMimeMessage object
+ **/
+CamelMimeMessage *
+e_msg_composer_get_message (EMsgComposer *composer,
+                            gboolean save_html_object_data)
 {
-	GConfClient *gconf;
-	GError *error = NULL;
-	EMsgComposerPrivate *p = composer->priv;
-
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	if ((p->view_cc && view_cc) ||
-	    (!p->view_cc && !view_cc))
-		return;
+	GtkhtmlEditor *editor;
+	gboolean html_content;
 
-	p->view_cc = view_cc;
-	bonobo_ui_component_set_prop (p->uic, "/commands/ViewCC",
-				      "state", p->view_cc ? "1" : "0", NULL);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-	if ((E_MSG_COMPOSER_HDRS (p->hdrs))->visible_mask & E_MSG_COMPOSER_VISIBLE_CC) {
-		gconf = gconf_client_get_default ();
-		if (!gconf_client_set_bool (gconf, "/apps/evolution/mail/composer/view/Cc", view_cc, &error)) {
-			g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-			g_error_free(error);
+	if (e_msg_composer_get_remote_download_count (composer) != 0) {
+		if (!em_utils_prompt_user (GTK_WINDOW (composer), NULL,
+			"mail-composer:ask-send-message-pending-download", NULL)) {
+			return NULL;
 		}
-		g_object_unref (gconf);
 	}
 
-	e_msg_composer_hdrs_set_visible (E_MSG_COMPOSER_HDRS (p->hdrs),
-					 e_msg_composer_get_visible_flags (composer));
+	editor = GTKHTML_EDITOR (composer);
+	html_content = gtkhtml_editor_get_html_mode (editor);
+
+	return build_message (composer, html_content, save_html_object_data);
 }
 
+static gchar *
+msg_composer_get_message_print_helper (EMsgComposer *composer,
+                                       gboolean html_content)
+{
+	GtkToggleAction *action;
+	GString *string;
 
+	string = g_string_sized_new (128);
 
-/**
- * e_msg_composer_get_view_bcc:
- * @composer: A message composer widget
- *
- * Get the status of the "View BCC header" flag.
- *
- * Return value: The status of the "View BCC header" flag.
- **/
-gboolean
-e_msg_composer_get_view_bcc (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
+	if (html_content)
+		g_string_append (string, "text/html");
+	else
+		g_string_append (string, "text/plain");
 
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+	if (gtk_toggle_action_get_active (action))
+		g_string_append (string, ", pgp-sign");
+	gtk_toggle_action_set_active (action, FALSE);
+
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT));
+	if (gtk_toggle_action_get_active (action))
+		g_string_append (string, ", pgp-encrypt");
+	gtk_toggle_action_set_active (action, FALSE);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
+	if (gtk_toggle_action_get_active (action))
+		g_string_append (string, ", smime-sign");
+	gtk_toggle_action_set_active (action, FALSE);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
+	if (gtk_toggle_action_get_active (action))
+		g_string_append (string, ", smime-encrypt");
+	gtk_toggle_action_set_active (action, FALSE);
 
-	return p->view_bcc;
+	return g_string_free (string, FALSE);
 }
 
-
-/**
- * e_msg_composer_set_view_bcc:
- * @composer: A message composer widget
- * @state: whether to show or hide the bcc view
- *
- * Controls the state of the BCC display
- */
-void
-e_msg_composer_set_view_bcc (EMsgComposer *composer, gboolean view_bcc)
+CamelMimeMessage *
+e_msg_composer_get_message_print (EMsgComposer *composer,
+                                  gboolean save_html_object_data)
 {
-	GConfClient *gconf;
-	GError *error = NULL;
-	EMsgComposerPrivate *p = composer->priv;
+	GtkhtmlEditor *editor;
+	EMsgComposer *temp_composer;
+	CamelMimeMessage *msg;
+	gboolean html_content;
+	gchar *flags;
 
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	editor = GTKHTML_EDITOR (composer);
+	html_content = gtkhtml_editor_get_html_mode (editor);
 
-	if ((p->view_bcc && view_bcc) ||
-	    (!p->view_bcc && !view_bcc))
-		return;
+	msg = build_message (composer, html_content, save_html_object_data);
+	if (msg == NULL)
+		return NULL;
+
+	temp_composer = e_msg_composer_new_with_message (msg);
+	camel_object_unref (msg);
 
-	p->view_bcc = view_bcc;
-	bonobo_ui_component_set_prop (p->uic, "/commands/ViewBCC",
-				      "state", p->view_bcc ? "1" : "0", NULL);
+	/* Override composer flags. */
+	flags = msg_composer_get_message_print_helper (
+		temp_composer, html_content);
 
-	if ((E_MSG_COMPOSER_HDRS (p->hdrs))->visible_mask & E_MSG_COMPOSER_VISIBLE_BCC) {
-		gconf = gconf_client_get_default ();
-		if (!gconf_client_set_bool (gconf, "/apps/evolution/mail/composer/view/Bcc", view_bcc, &error)) {
-			g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
-			g_error_free(error);
-		}
-		g_object_unref (gconf);
-	}
+	msg = build_message (temp_composer, TRUE, save_html_object_data);
+	if (msg != NULL)
+		camel_medium_set_header (
+			CAMEL_MEDIUM (msg), "X-Evolution-Format", flags);
 
-	e_msg_composer_hdrs_set_visible (E_MSG_COMPOSER_HDRS (p->hdrs),
-					 e_msg_composer_get_visible_flags (composer));
+	gtk_widget_destroy (GTK_WIDGET (temp_composer));
+	g_free (flags);
+
+	return msg;
 }
 
+CamelMimeMessage *
+e_msg_composer_get_message_draft (EMsgComposer *composer)
+{
+	GtkhtmlEditor *editor;
+	EComposerHeaderTable *table;
+	GtkToggleAction *action;
+	CamelMimeMessage *msg;
+	EAccount *account;
+	gboolean html_content;
+	gboolean pgp_encrypt;
+	gboolean pgp_sign;
+	gboolean smime_encrypt;
+	gboolean smime_sign;
+	GString *flags;
+
+	editor = GTKHTML_EDITOR (composer);
+	table = e_msg_composer_get_header_table (composer);
+	html_content = gtkhtml_editor_get_html_mode (editor);
+
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+	pgp_sign = gtk_toggle_action_get_active (action);
+	gtk_toggle_action_set_active (action, FALSE);
+
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT));
+	pgp_encrypt = gtk_toggle_action_get_active (action);
+	gtk_toggle_action_set_active (action, FALSE);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
+	smime_sign = gtk_toggle_action_get_active (action);
+	gtk_toggle_action_set_active (action, FALSE);
+
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
+	smime_encrypt = gtk_toggle_action_get_active (action);
+	gtk_toggle_action_set_active (action, FALSE);
+
+	msg = build_message (composer, TRUE, TRUE);
+	if (msg == NULL)
+		return NULL;
 
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN));
+	gtk_toggle_action_set_active (action, pgp_sign);
 
-/**
- * e_msg_composer_get_request_receipt
- * @composer: A message composer widget
- *
- * Get the status of the "Request receipt" flag.
- *
- * Return value: The status of the "Request receipt" flag.
- **/
-gboolean
-e_msg_composer_get_request_receipt (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT));
+	gtk_toggle_action_set_active (action, pgp_encrypt);
 
-	return p->request_receipt;
-}
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN));
+	gtk_toggle_action_set_active (action, smime_sign);
 
+	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
+	gtk_toggle_action_set_active (action, smime_encrypt);
 
-/**
- * e_msg_composer_set_request_receipt:
- * @composer: A message composer widget
- * @state: whether to request or not a receipt
- *
- * If set, a message delivery notification request will be sent to the recipient
- */
-void
-e_msg_composer_set_request_receipt (EMsgComposer *composer, gboolean request_receipt)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	if (msg == NULL)
+		return NULL;
 
-	if ((p->request_receipt && request_receipt) ||
-	    (!p->request_receipt && !request_receipt))
-		return;
+	/* Attach account info to the draft. */
+	account = e_composer_header_table_get_account (table);
+	if (account && account->name)
+		camel_medium_set_header (
+			CAMEL_MEDIUM (msg),
+			"X-Evolution-Account", account->uid);
 
-	p->request_receipt = request_receipt;
-	bonobo_ui_component_set_prop (p->uic, "/commands/RequestReceipt",
-				      "state", p->request_receipt ? "1" : "0", NULL);
-}
+	flags = g_string_new (html_content ? "text/html" : "text/plain");
 
+	/* This should probably only save the setting if it is
+	 * different from the from-account default? */
+	if (pgp_sign)
+		g_string_append (flags, ", pgp-sign");
+	if (pgp_encrypt)
+		g_string_append (flags, ", pgp-encrypt");
+	if (smime_sign)
+		g_string_append (flags, ", smime-sign");
+	if (smime_encrypt)
+		g_string_append (flags, ", smime-encrypt");
 
-/**
- * e_msg_composer_get_priority
- * @composer: A message composer widget
- *
- * Get the status of the "Priority" flag.
- *
- * Return value: The status of the "Priority" flag.
- **/
-gboolean
-e_msg_composer_get_priority (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	camel_medium_set_header (
+		CAMEL_MEDIUM (msg), "X-Evolution-Format", flags->str);
+	g_string_free (flags, TRUE);
 
-	return p->set_priority;
+	return msg;
 }
 
-
 /**
- * e_msg_composer_set_priority:
+ * e_msg_composer_show_sig:
  * @composer: A message composer widget
- * @state: whether to set priority or not
  *
- * If set, a message is sent with a high priority
- */
+ * Set a signature
+ **/
 void
-e_msg_composer_set_priority (EMsgComposer *composer, gboolean set_priority)
+e_msg_composer_show_sig_file (EMsgComposer *composer)
 {
-	EMsgComposerPrivate *p = composer->priv;
+	GtkhtmlEditor *editor;
+	GtkHTML *html;
+	gchar *html_text;
+
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	if ((p->set_priority && set_priority) ||
-	    (!p->set_priority && !set_priority))
+	editor = GTKHTML_EDITOR (composer);
+	html = gtkhtml_editor_get_html (editor);
+
+	if (composer->priv->redirect)
 		return;
 
-	p->set_priority= set_priority;
-	bonobo_ui_component_set_prop (p->uic, "/commands/SetPriority",
-				      "state", p->set_priority ? "1" : "0", NULL);
-}
+	composer->priv->in_signature_insert = TRUE;
 
-EDestination **
-e_msg_composer_get_recipients (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
+	gtkhtml_editor_freeze (editor);
+	gtkhtml_editor_run_command (editor, "cursor-position-save");
+	gtkhtml_editor_undo_begin (editor, "Set signature", "Reset signature");
 
-	return p->hdrs ? e_msg_composer_hdrs_get_recipients (E_MSG_COMPOSER_HDRS (p->hdrs)) : NULL;
-}
+	/* Delete the old signature. */
+	gtkhtml_editor_run_command (editor, "block-selection");
+	gtkhtml_editor_run_command (editor, "cursor-bod");
+	if (gtkhtml_editor_search_by_data (editor, 1, "ClueFlow", "signature", "1")) {
+		gtkhtml_editor_run_command (editor, "select-paragraph");
+		gtkhtml_editor_run_command (editor, "delete");
+		gtkhtml_editor_set_paragraph_data (editor, "signature", "0");
+		gtkhtml_editor_run_command (editor, "delete-back");
+	}
+	gtkhtml_editor_run_command (editor, "unblock-selection");
 
-EDestination **
-e_msg_composer_get_to (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
+	html_text = get_signature_html (composer);
+	if (html_text) {
+		gtkhtml_editor_run_command (editor, "insert-paragraph");
+		if (!gtkhtml_editor_run_command (editor, "cursor-backward"))
+			gtkhtml_editor_run_command (editor, "insert-paragraph");
+		else
+			gtkhtml_editor_run_command (editor, "cursor-forward");
+		gtkhtml_editor_set_paragraph_data (editor, "orig", "0");
+		gtkhtml_editor_run_command (editor, "indent-zero");
+		gtkhtml_editor_run_command (editor, "style-normal");
+		gtkhtml_editor_insert_html (editor, html_text);
+		g_free (html_text);
+	}
 
-	return p->hdrs ? e_msg_composer_hdrs_get_to (E_MSG_COMPOSER_HDRS (p->hdrs)) : NULL;
+	gtkhtml_editor_undo_end (editor);
+	gtkhtml_editor_run_command (editor, "cursor-position-restore");
+	gtkhtml_editor_thaw (editor);
+
+	composer->priv->in_signature_insert = FALSE;
 }
 
-EDestination **
-e_msg_composer_get_cc (EMsgComposer *composer)
+CamelInternetAddress *
+e_msg_composer_get_from (EMsgComposer *composer)
 {
-	EMsgComposerPrivate *p = composer->priv;
+	CamelInternetAddress *address;
+	EComposerHeaderTable *table;
+	EAccount *account;
+
 	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-	return p->hdrs ? e_msg_composer_hdrs_get_cc (E_MSG_COMPOSER_HDRS (p->hdrs)) : NULL;
-}
+	table = e_msg_composer_get_header_table (composer);
 
-EDestination **
-e_msg_composer_get_bcc (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
+	account = e_composer_header_table_get_account (table);
+	if (account == NULL)
+		return NULL;
+
+	address = camel_internet_address_new ();
+	camel_internet_address_add (
+		address, account->id->name, account->id->address);
 
-	return p->hdrs ? e_msg_composer_hdrs_get_bcc (E_MSG_COMPOSER_HDRS (p->hdrs)) : NULL;
+	return address;
 }
 
-const char *
-e_msg_composer_get_subject (EMsgComposer *composer)
+CamelInternetAddress *
+e_msg_composer_get_reply_to (EMsgComposer *composer)
 {
-	EMsgComposerPrivate *p = composer->priv;
+	CamelInternetAddress *address;
+	EComposerHeaderTable *table;
+	const gchar *reply_to;
+
 	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-	return p->hdrs ? e_msg_composer_hdrs_get_subject (E_MSG_COMPOSER_HDRS (p->hdrs)) : NULL;
-}
+	table = e_msg_composer_get_header_table (composer);
+
+	reply_to = e_composer_header_table_get_reply_to (table);
+	if (reply_to == NULL || *reply_to == '\0')
+		return NULL;
+
+	address = camel_internet_address_new ();
+	if (camel_address_unformat (CAMEL_ADDRESS (address), reply_to) == -1) {
+		camel_object_unref (CAMEL_OBJECT (address));
+		return NULL;
+	}
 
+	return address;
+}
 
 /**
  * e_msg_composer_guess_mime_type:
- * @file_name: filename
+ * @filename: filename
  *
- * Returns the guessed mime type of the file given by #file_name.
+ * Returns the guessed mime type of the file given by @filename.
  **/
-char *
-e_msg_composer_guess_mime_type (const char *file_name)
+gchar *
+e_msg_composer_guess_mime_type (const gchar *filename)
 {
 	GnomeVFSFileInfo *info;
 	GnomeVFSResult result;
-	char *type = NULL;
+	gchar *type = NULL;
+
+	g_return_val_if_fail (filename != NULL, NULL);
 
 	info = gnome_vfs_file_info_new ();
-	result = gnome_vfs_get_file_info (file_name, info,
-					  GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
-					  GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
-					  GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
+	result = gnome_vfs_get_file_info (
+		filename, info,
+		GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
+		GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE |
+		GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
 	if (result == GNOME_VFS_OK)
 		type = g_strdup (gnome_vfs_file_info_get_mime_type (info));
 
@@ -6203,89 +4534,6 @@
 	return type;
 }
 
-
-/**
- * e_msg_composer_set_changed:
- * @composer: An EMsgComposer object.
- *
- * Mark the composer as changed, so before the composer gets destroyed
- * the user will be prompted about unsaved changes.
- **/
-void
-e_msg_composer_set_changed (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	p->has_changed = TRUE;
-}
-
-
-/**
- * e_msg_composer_unset_changed:
- * @composer: An EMsgComposer object.
- *
- * Mark the composer as unchanged, so no prompt about unsaved changes
- * will appear before destroying the composer.
- **/
-void
-e_msg_composer_unset_changed (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	p->has_changed = FALSE;
-}
-
-gboolean
-e_msg_composer_is_dirty (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
-	gboolean rv;
-
-	CORBA_exception_init (&ev);
-	rv = p->has_changed
-		|| (GNOME_GtkHTML_Editor_Engine_hasUndo (p->eeditor_engine, &ev) &&
-		    !GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "is-saved", &ev));
-	CORBA_exception_free (&ev);
-
-	return rv;
-}
-
-/**
- * e_msg_composer_set_autosaved:
- * @composer: An EMsgComposer object.
- *
- * Mark the composer as autosaved, so before the composer gets destroyed
- * the user will be prompted about unsaved changes.
- **/
-void
-e_msg_composer_set_autosaved (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	p->autosaved = TRUE;
-}
-
-
-/**
- * e_msg_composer_unset_autosaved:
- * @composer: An EMsgComposer object.
- *
- * Mark the composer as unautosaved, so no prompt about unsaved changes
- * will appear before destroying the composer.
- **/
-void
-e_msg_composer_unset_autosaved (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
-
-	p->autosaved = FALSE;
-}
-
 /**
  * e_msg_composer_get_raw_message_text:
  *
@@ -6294,334 +4542,176 @@
 GByteArray *
 e_msg_composer_get_raw_message_text (EMsgComposer *composer)
 {
-       GByteArray *data = NULL;
-       EMsgComposerPrivate *p = composer->priv;
-       g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
-
-       data = get_text (p->persist_stream_interface, "text/plain");
-       if (data)
-		return data;
-
-       return NULL;
-}
-
-EAttachmentBar*
-e_msg_composer_get_attachment_bar (EMsgComposer *composer)
-{
-       EMsgComposerPrivate *p = composer->priv;
+	GtkhtmlEditor *editor;
+	GByteArray *array;
+	gchar *text;
+	gsize length;
 
-       return (EAttachmentBar*) p->attachment_bar;
-}
+	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-gboolean
-e_msg_composer_is_autosaved (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
+	array = g_byte_array_new ();
+	editor = GTKHTML_EDITOR (composer);
+	text = gtkhtml_editor_get_text_plain (editor, &length);
+	g_byte_array_append (array, (guint8 *) text, (guint) length);
+	g_free (text);
 
-	return p->autosaved;
+	return array;
 }
 
-void
-e_msg_composer_set_enable_autosave  (EMsgComposer *composer, gboolean enabled)
+EAttachmentBar *
+e_msg_composer_get_attachment_bar (EMsgComposer *composer)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
+	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-	p->enable_autosave = enabled;
+	return E_ATTACHMENT_BAR (composer->priv->attachment_bar);
 }
 
 void
-e_msg_composer_drop_editor_undo (EMsgComposer *composer)
+e_msg_composer_set_enable_autosave (EMsgComposer *composer,
+                                    gboolean enabled)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_dropUndo (p->eeditor_engine, &ev);
-	CORBA_exception_free (&ev);
+	e_composer_autosave_set_enabled (composer, enabled);
 }
 
-
 gboolean
 e_msg_composer_request_close_all (void)
 {
-	GSList *p, *pnext;
+	GSList *iter, *next;
 
-	for (p = all_composers; p != NULL; p = pnext) {
-		pnext = p->next;
-		do_exit (E_MSG_COMPOSER (p->data));
+	for (iter = all_composers; iter != NULL; iter = next) {
+		EMsgComposer *composer = iter->data;
+		next = iter->next;
+		gtk_action_activate (ACTION (CLOSE));
 	}
 
-	if (all_composers == NULL)
-		return TRUE;
-	else
-		return FALSE;
-}
-
-void
-e_msg_composer_check_autosave(GtkWindow *parent)
-{
-	if (am == NULL)
-		am = autosave_manager_new();
-
-	if (am->ask) {
-		am->ask = FALSE;
-		autosave_manager_query_load_orphans (am, parent);
-		am->ask = TRUE;
-	}
+	return (all_composers == NULL);
 }
 
-void
-e_msg_composer_show_attachments_ui (EMsgComposer *composer)
+EMsgComposer *
+e_msg_composer_load_from_file (const gchar *filename)
 {
-	EMsgComposerPrivate *p = composer->priv;
-
-	if (e_attachment_bar_get_num_attachments(E_ATTACHMENT_BAR(p->attachment_bar)))
-		show_attachments (composer, TRUE);
-}
+	CamelStream *stream;
+	CamelMimeMessage *msg;
+	EMsgComposer *composer;
 
-void
-e_msg_composer_set_alternative (EMsgComposer *composer, gboolean alt)
-{
-	EMsgComposerPrivate *p = composer->priv;
+	g_return_val_if_fail (filename != NULL, NULL);
 
-	p->is_alternative = alt;
-	p->send_html = !alt;
-}
+	stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0);
+	if (stream == NULL)
+		return NULL;
 
-void
-e_msg_composer_reply_indent (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
+	msg = camel_mime_message_new ();
+	camel_data_wrapper_construct_from_stream (
+		CAMEL_DATA_WRAPPER (msg), stream);
+	camel_object_unref (stream);
 
-	CORBA_exception_init (&ev);
+	composer = e_msg_composer_new_with_message (msg);
+	if (composer != NULL) {
+		g_signal_connect (
+			composer, "send",
+			G_CALLBACK (em_utils_composer_send_cb), NULL);
+
+		g_signal_connect (
+			composer, "save-draft",
+			G_CALLBACK (em_utils_composer_save_draft_cb), NULL);
 
-	if (!GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (p->eeditor_engine, &ev)) {
-		if (GNOME_GtkHTML_Editor_Engine_isPreviousParagraphEmpty (p->eeditor_engine, &ev))
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "cursor-backward", &ev);
-		else {
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "text-default-color", &ev);
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-			GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "insert-paragraph", &ev);
-			return;
-		}
+		gtk_widget_show (GTK_WIDGET (composer));
 	}
 
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "style-normal", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "indent-zero", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "text-default-color", &ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-
-	CORBA_exception_free (&ev);
-
+	return composer;
 }
 
 void
-e_msg_composer_insert_paragraph_before (EMsgComposer *composer)
+e_msg_composer_check_autosave (GtkWindow *parent)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
+	GList *orphans = NULL;
+	gint response;
+	GError *error = NULL;
 
-	if (!p->in_signature_insert) {
-		CORBA_char *orig, *signature;
-		gboolean changed = FALSE;
-		/* FIXME check for insert-paragraph command */
-
-		orig = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "orig", &ev);
-		if (ev._major == CORBA_NO_EXCEPTION) {
-			if (orig && *orig == '1') {
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "text-default-color", &ev);
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-				changed = TRUE;
-			}
-			CORBA_free (orig);
-		}
-		if (!changed) {
-			signature = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "signature", &ev);
-			if (ev._major == CORBA_NO_EXCEPTION) {
-				if (signature && *signature == '1') {
-					GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "text-default-color",
-										&ev);
-					GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-				}
-				CORBA_free (signature);
-			}
+	/* Look for orphaned autosave files. */
+	orphans = e_composer_autosave_find_orphans (&error);
+	if (orphans == NULL) {
+		if (error != NULL) {
+			g_warning ("%s", error->message);
+			g_error_free (error);
 		}
+		return;
 	}
 
-	CORBA_exception_free (&ev);
-}
-
-static void
-clear_signature (GNOME_GtkHTML_Editor_Engine e, CORBA_Environment * ev)
-{
-	if (GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (e, ev))
-		GNOME_GtkHTML_Editor_Engine_setParagraphData (e, "signature", "0", ev);
-	else if (GNOME_GtkHTML_Editor_Engine_isPreviousParagraphEmpty (e, ev)
-		 && GNOME_GtkHTML_Editor_Engine_runCommand (e, "cursor-backward", ev)) {
-		GNOME_GtkHTML_Editor_Engine_setParagraphData (e, "signature", "0", ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (e, "cursor-forward", ev);
-	}
-	GNOME_GtkHTML_Editor_Engine_runCommand (e, "text-default-color", ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (e, "italic-off", ev);
-}
+	/* Ask if the user wants to recover the orphaned files. */
+	response = e_error_run (
+		parent, "mail-composer:recover-autosave", NULL);
 
-void
-e_msg_composer_insert_paragraph_after (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
+	/* Based on the user's response, recover or delete them. */
+	while (orphans != NULL) {
+		const gchar *filename = orphans->data;
+		EMsgComposer *composer;
 
-	CORBA_exception_init (&ev);
+		if (response == GTK_RESPONSE_YES) {
+			/* FIXME: composer is never used */
+			composer = autosave_load_draft (filename);
+		} else {
+			g_unlink (filename);
+		}
 
-	if (!p->in_signature_insert) {
-	      CORBA_char *orig, *signature;
-	      /* FIXME check for insert-paragraph command */
-	      GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-
-	      orig = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "orig", &ev);
-	      if (ev._major == CORBA_NO_EXCEPTION) {
-		      if (orig && *orig == '1')
-			      e_msg_composer_reply_indent (composer);
-		      GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "orig", "0", &ev);
-		      CORBA_free (orig);
-	      }
-	      signature = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "signature", &ev);
-	      if (ev._major == CORBA_NO_EXCEPTION) {
-		      if (signature && *signature == '1')
-			      clear_signature (p->eeditor_engine, &ev);
-		      CORBA_free (signature);
-	      }
+		g_free (orphans->data);
+		orphans = g_list_delete_link (orphans, orphans);
 	}
-
-	CORBA_exception_free (&ev);
 }
 
 void
-e_msg_composer_delete (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
-
-	if (GNOME_GtkHTML_Editor_Engine_isParagraphEmpty (p->eeditor_engine, &ev)) {
-		CORBA_char *orig;
-		CORBA_char *signature;
-
-		orig = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "orig", &ev);
-		if (ev._major == CORBA_NO_EXCEPTION) {
-			if (orig && *orig == '1') {
-				GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "orig", "0", &ev);
-
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "indent-zero", &ev);
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "style-normal", &ev);
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "text-default-color", &ev);
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "italic-off", &ev);
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "insert-paragraph", &ev);
-				GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "delete-back", &ev);
-			}
-			CORBA_free (orig);
-		}
-		signature = GNOME_GtkHTML_Editor_Engine_getParagraphData (p->eeditor_engine, "signature", &ev);
-		if (ev._major == CORBA_NO_EXCEPTION) {
-			if (signature && *signature == '1')
-				GNOME_GtkHTML_Editor_Engine_setParagraphData (p->eeditor_engine, "signature", "0", &ev);
-			CORBA_free (signature);
-		}
-	}
-	CORBA_exception_free (&ev);
-}
-
-
-gchar *
-e_msg_composer_resolve_image_url (EMsgComposer *composer, gchar *url)
+e_msg_composer_set_alternative (EMsgComposer *composer,
+                                gboolean alt)
 {
-	EMsgComposerPrivate *p = composer->priv;
-	CamelMimePart *part;
-	const char *cid;
-
-	part = g_hash_table_lookup (p->inline_images_by_url, url);
-	if (!part && !strncmp (url, "file:", 5)) {
-		part = e_msg_composer_add_inline_image_from_file (composer, url + 5);
-	}
-	if (!part && !strncmp (url, "cid:", 4)) {
-		part = g_hash_table_lookup (p->inline_images, url);
-	}
-	if (!part)
-		return NULL;
-
-	p->current_images  = g_list_prepend (p->current_images, part);
-
-	cid = camel_mime_part_get_content_id (part);
-	if (!cid)
-		return NULL;
-
-	return g_strconcat ("cid:", cid, NULL);
-}
+	GtkhtmlEditor *editor;
 
-CamelMimePart*
-e_msg_composer_url_requested (EMsgComposer *composer, gchar *url)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	CamelMimePart *part = NULL;
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	part = g_hash_table_lookup (p->inline_images_by_url, url);
-	if (!part)
-		part = g_hash_table_lookup (p->inline_images, url);
-	if (!part)
-		return NULL;
+	editor = GTKHTML_EDITOR (composer);
 
-	return part;
+	composer->priv->is_alternative = alt;
+	gtkhtml_editor_set_html_mode (editor, !alt);
 }
 
 void
-e_msg_composer_link_clicked (EMsgComposer *composer, const gchar *url)
+e_msg_composer_reply_indent (EMsgComposer *composer)
 {
-	g_return_if_fail (composer != NULL);
+	GtkhtmlEditor *editor;
 
-	if (url && *url &&
-	    g_ascii_strncasecmp (url, "mailto:";, 7) &&
-	    g_ascii_strncasecmp (url, "thismessage:", 12) &&
-	    g_ascii_strncasecmp (url, "cid:", 4)) {
-		GError *err = NULL;
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-		gnome_url_show (url, &err);
+	editor = GTKHTML_EDITOR (composer);
 
-		if (err) {
-			g_warning ("gnome_url_show: %s", err->message);
-			g_error_free (err);
+	if (!gtkhtml_editor_is_paragraph_empty (editor)) {
+		if (gtkhtml_editor_is_previous_paragraph_empty (editor))
+			gtkhtml_editor_run_command (editor, "cursor-backward");
+		else {
+			gtkhtml_editor_run_command (editor, "text-default-color");
+			gtkhtml_editor_run_command (editor, "italic-off");
+			gtkhtml_editor_run_command (editor, "insert-paragraph");
+			return;
 		}
 	}
-}
 
-EMsgComposerHdrs*
-e_msg_composer_get_hdrs (EMsgComposer *composer)
-{
-	EMsgComposerPrivate *p = composer->priv;
-	return (EMsgComposerHdrs*)p->hdrs;
+	gtkhtml_editor_run_command (editor, "style-normal");
+	gtkhtml_editor_run_command (editor, "indent-zero");
+	gtkhtml_editor_run_command (editor, "text-default-color");
+	gtkhtml_editor_run_command (editor, "italic-off");
 }
 
-void
-e_msg_composer_set_saved (EMsgComposer *composer)
+EComposerHeaderTable *
+e_msg_composer_get_header_table (EMsgComposer *composer)
 {
-	CORBA_Environment ev;
-	EMsgComposerPrivate *p = composer->priv;
+	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL);
 
-	CORBA_exception_init (&ev);
-	GNOME_GtkHTML_Editor_Engine_runCommand (p->eeditor_engine, "saved", &ev);
-	CORBA_exception_free (&ev);
+	return E_COMPOSER_HEADER_TABLE (composer->priv->header_table);
 }
 
 void
-e_msg_composer_set_send_options (EMsgComposer *composer, gboolean send_enable)
+e_msg_composer_set_send_options (EMsgComposer *composer,
+                                 gboolean send_enable)
 {
-	EMsgComposerPrivate *priv;
-	priv = composer->priv;
+	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-	priv->send_invoked = send_enable;
+	composer->priv->send_invoked = send_enable;
 }

Modified: trunk/composer/e-msg-composer.h
==============================================================================
--- trunk/composer/e-msg-composer.h	(original)
+++ trunk/composer/e-msg-composer.h	Wed Apr  2 19:37:22 2008
@@ -21,187 +21,142 @@
  * Author: Ettore Perazzoli
  */
 
+#ifndef E_MSG_COMPOSER_H
+#define E_MSG_COMPOSER_H
 
-#ifndef ___E_MSG_COMPOSER_H__
-#define ___E_MSG_COMPOSER_H__
-
-typedef struct _EMsgComposer       EMsgComposer;
-typedef struct _EMsgComposerClass  EMsgComposerClass;
-
-#include <bonobo/bonobo-window.h>
-#include <bonobo/bonobo-ui-component.h>
-
-#include "e-msg-composer-hdrs.h"
-#include "Editor.h"
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-
-#define E_TYPE_MSG_COMPOSER	       (e_msg_composer_get_type ())
-#define E_MSG_COMPOSER(obj)	       (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MSG_COMPOSER, EMsgComposer))
-#define E_MSG_COMPOSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MSG_COMPOSER, EMsgComposerClass))
-#define E_IS_MSG_COMPOSER(obj)	       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MSG_COMPOSER))
-#define E_IS_MSG_COMPOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MSG_COMPOSER))
-
-
+#include <camel/camel-internet-address.h>
+#include <camel/camel-mime-message.h>
+#include <libedataserver/e-account.h>
+#include <libebook/e-destination.h>
+#include <gtkhtml-editor.h>
+
+#include "e-composer-header-table.h"
+
+/* Standard GObject macros */
+#define E_TYPE_MSG_COMPOSER \
+	(e_msg_composer_get_type ())
+#define E_MSG_COMPOSER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MSG_COMPOSER, EMsgComposer))
+#define E_MSG_COMPOSER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MSG_COMPOSER, EMsgComposerClass))
+#define E_IS_MSG_COMPOSER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MSG_COMPOSER))
+#define E_IS_MSG_COMPOSER_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((obj), E_TYPE_MSG_COMPOSER))
+#define E_MSG_COMPOSER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MSG_COMPOSER, EMsgComposerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMsgComposer EMsgComposer;
+typedef struct _EMsgComposerClass EMsgComposerClass;
+typedef struct _EMsgComposerPrivate EMsgComposerPrivate;
+
+struct _EMsgComposer {
+	GtkhtmlEditor parent;
+	EMsgComposerPrivate *priv;
+};
+
+struct _EMsgComposerClass {
+	GtkhtmlEditorClass parent_class;
+};
 
 struct _EAttachmentBar;
 
-GtkType                  e_msg_composer_get_type                         (void);
-
-EMsgComposer            *e_msg_composer_new                              (void);
-
 #define E_MSG_COMPOSER_MAIL 1
 #define E_MSG_COMPOSER_POST 2
 #define E_MSG_COMPOSER_MAIL_POST E_MSG_COMPOSER_MAIL|E_MSG_COMPOSER_POST
 
-EMsgComposer            *e_msg_composer_new_with_type                    (int type);
+GType		e_msg_composer_get_type		(void);
+EMsgComposer *	e_msg_composer_new		(void);
+EMsgComposer *	e_msg_composer_new_with_type	(gint type);
+EMsgComposer *	e_msg_composer_new_with_message	(CamelMimeMessage *msg);
+EMsgComposer *	e_msg_composer_new_from_url	(const gchar *url);
+EMsgComposer *	e_msg_composer_new_redirect	(CamelMimeMessage *message,
+						 const gchar *resent_from);
+
+void		e_msg_composer_send		(EMsgComposer *composer);
+void		e_msg_composer_save_draft	(EMsgComposer *composer);
+
+void		e_msg_composer_set_alternative	(EMsgComposer *composer,
+						 gboolean alt);
+
+void		e_msg_composer_set_body_text	(EMsgComposer *composer,
+						 const gchar *text,
+						 gssize len);
+void		e_msg_composer_set_body		(EMsgComposer *composer,
+						 const gchar *body,
+						 const gchar *mime_type);
+void		e_msg_composer_add_header	(EMsgComposer *composer,
+						 const gchar *name,
+						 const gchar *value);
+void		e_msg_composer_modify_header	(EMsgComposer *composer,
+						 const gchar *name,
+						 const gchar *value);
+void		e_msg_composer_remove_header	(EMsgComposer *composer,
+						 const gchar *name);
+void		e_msg_composer_attach		(EMsgComposer *composer,
+						 CamelMimePart *attachment);
+CamelMimePart *	e_msg_composer_add_inline_image_from_file
+						(EMsgComposer *composer,
+						 const gchar *filename);
+void		e_msg_composer_add_inline_image_from_mime_part
+						(EMsgComposer *composer,
+						 CamelMimePart *part);
+CamelMimeMessage *
+		e_msg_composer_get_message	(EMsgComposer *composer,
+						 gboolean save_html_object_data);
+CamelMimeMessage *
+		e_msg_composer_get_message_print(EMsgComposer *composer,
+						 gboolean save_html_object_data);
+CamelMimeMessage *
+		e_msg_composer_get_message_draft(EMsgComposer *composer);
+void		e_msg_composer_show_sig_file	(EMsgComposer *composer);
+
+CamelInternetAddress *
+		e_msg_composer_get_from		(EMsgComposer *composer);
+CamelInternetAddress *
+		e_msg_composer_get_reply_to	(EMsgComposer *composer);
+
+void		e_msg_composer_clear_inlined_table
+						(EMsgComposer *composer);
+gchar *		e_msg_composer_guess_mime_type	(const gchar *filename);
+void		e_msg_composer_set_enable_autosave
+						(EMsgComposer *composer,
+						 gboolean enabled);
+
+gchar *		e_msg_composer_get_sig_file_content
+						(const gchar *sigfile,
+						 gboolean in_html);
+void		e_msg_composer_add_message_attachments
+						(EMsgComposer *composer,
+						 CamelMimeMessage *message,
+						 gboolean just_inlines);
+
+gboolean	e_msg_composer_request_close_all(void);
+EMsgComposer *	e_msg_composer_load_from_file	(const gchar *filename);
+void		e_msg_composer_check_autosave	(GtkWindow *parent);
+gint		e_msg_composer_get_remote_download_count
+						(EMsgComposer *composer);
+
+void		e_msg_composer_reply_indent	(EMsgComposer *composer);
+
+EComposerHeaderTable *
+		e_msg_composer_get_header_table	(EMsgComposer *composer);
+void		e_msg_composer_set_send_options	(EMsgComposer *composer,
+						 gboolean send_enable);
+GByteArray *	e_msg_composer_get_raw_message_text
+						(EMsgComposer *composer);
+
+struct _EAttachmentBar *
+		e_msg_composer_get_attachment_bar
+						(EMsgComposer *composer);
 
-EMsgComposer            *e_msg_composer_new_with_message                 (CamelMimeMessage  *msg);
-EMsgComposer            *e_msg_composer_new_from_url                     (const char        *url);
-EMsgComposer            *e_msg_composer_new_redirect                     (CamelMimeMessage  *message,
-									  const char        *resent_from);
-void			e_msg_composer_show_attachments_ui		 (EMsgComposer *composer);
-
-void                     e_msg_composer_set_alternative                  (EMsgComposer      *composer,
-									  gboolean           alt);
-
-void                     e_msg_composer_set_headers                      (EMsgComposer      *composer,
-									  const char        *from,
-									  EDestination     **to,
-									  EDestination     **cc,
-									  EDestination     **bcc,
-									  const char        *subject);
-void                     e_msg_composer_set_body_text                    (EMsgComposer      *composer,
-									  const char        *text,
-									  ssize_t            len);
-void                     e_msg_composer_set_body                         (EMsgComposer      *composer,
-									  const char        *body,
-									  const char        *mime_type);
-void                     e_msg_composer_add_header                       (EMsgComposer      *composer,
-									  const char        *name,
-									  const char        *value);
-void			 e_msg_composer_modify_header			 (EMsgComposer      *composer,
-									  const char 	    *name,
-									  const char        *value);
-void			 e_msg_composer_remove_header		          (EMsgComposer      *composer,
-									  const char        *name);
-void                     e_msg_composer_attach                           (EMsgComposer      *composer,
-									  CamelMimePart     *attachment);
-CamelMimePart           *e_msg_composer_add_inline_image_from_file       (EMsgComposer      *composer,
-									  const char        *filename);
-void                     e_msg_composer_add_inline_image_from_mime_part  (EMsgComposer      *composer,
-									  CamelMimePart     *part);
-CamelMimeMessage        *e_msg_composer_get_message                      (EMsgComposer      *composer,
-									  gboolean           save_html_object_data);
-CamelMimeMessage        *e_msg_composer_get_message_print                (EMsgComposer      *composer,
-                                                                          gboolean           save_html_object_data);
-CamelMimeMessage        *e_msg_composer_get_message_draft                (EMsgComposer      *composer);
-void                     e_msg_composer_show_sig_file                    (EMsgComposer      *composer);
-gboolean                 e_msg_composer_get_send_html                    (EMsgComposer      *composer);
-void                     e_msg_composer_set_send_html                    (EMsgComposer      *composer,
-									  gboolean           send_html);
-
-gboolean                 e_msg_composer_get_view_from                    (EMsgComposer      *composer);
-void                     e_msg_composer_set_view_from                    (EMsgComposer      *composer,
-									  gboolean           view_from);
-gboolean                 e_msg_composer_get_view_to                      (EMsgComposer      *composer);
-void                     e_msg_composer_set_view_to                      (EMsgComposer      *composer,
-									  gboolean           view_replyto);
-gboolean                 e_msg_composer_get_view_replyto                 (EMsgComposer      *composer);
-void                     e_msg_composer_set_view_replyto                 (EMsgComposer      *composer,
-									  gboolean           view_replyto);
-gboolean                 e_msg_composer_get_view_postto                  (EMsgComposer      *composer);
-void                     e_msg_composer_set_view_postto                  (EMsgComposer      *composer,
-									  gboolean           view_replyto);
-gboolean                 e_msg_composer_get_view_cc                      (EMsgComposer      *composer);
-void                     e_msg_composer_set_view_cc                      (EMsgComposer      *composer,
-									  gboolean           view_cc);
-gboolean                 e_msg_composer_get_view_bcc                     (EMsgComposer      *composer);
-void                     e_msg_composer_set_view_bcc                     (EMsgComposer      *composer,
-									  gboolean           view_bcc);
-
-gboolean                 e_msg_composer_get_request_receipt              (EMsgComposer *composer);
-void                     e_msg_composer_set_request_receipt              (EMsgComposer *composer,
-									  gboolean      request_receipt);
-
-gboolean                 e_msg_composer_get_priority              (EMsgComposer *composer);
-void                     e_msg_composer_set_priority              (EMsgComposer *composer,
-								  gboolean      set_priority);
-
-EDestination           **e_msg_composer_get_recipients                   (EMsgComposer *composer);
-EDestination           **e_msg_composer_get_to                           (EMsgComposer *composer);
-EDestination           **e_msg_composer_get_cc                           (EMsgComposer *composer);
-EDestination           **e_msg_composer_get_bcc                          (EMsgComposer *composer);
-const char              *e_msg_composer_get_subject                      (EMsgComposer *composer);
-
-EAccount                *e_msg_composer_get_preferred_account            (EMsgComposer      *composer);
-void                     e_msg_composer_clear_inlined_table              (EMsgComposer      *composer);
-char                    *e_msg_composer_guess_mime_type                  (const char        *file_name);
-void                     e_msg_composer_set_changed                      (EMsgComposer      *composer);
-void                     e_msg_composer_unset_changed                    (EMsgComposer      *composer);
-gboolean                 e_msg_composer_is_dirty                         (EMsgComposer      *composer);
-void                     e_msg_composer_set_autosaved                    (EMsgComposer      *composer);
-void                     e_msg_composer_unset_autosaved                  (EMsgComposer      *composer);
-gboolean                 e_msg_composer_is_autosaved                     (EMsgComposer      *composer);
-void                     e_msg_composer_set_enable_autosave              (EMsgComposer      *composer,
-									  gboolean           enabled);
-
-/* PGP */
-void                     e_msg_composer_set_pgp_sign                     (EMsgComposer      *composer,
-									  gboolean           pgp_sign);
-gboolean                 e_msg_composer_get_pgp_sign                     (EMsgComposer      *composer);
-void                     e_msg_composer_set_pgp_encrypt                  (EMsgComposer      *composer,
-									  gboolean           pgp_encrypt);
-gboolean                 e_msg_composer_get_pgp_encrypt                  (EMsgComposer      *composer);
-
-/* S/MIME */
-void                     e_msg_composer_set_smime_sign                   (EMsgComposer      *composer,
-									  gboolean           smime_sign);
-gboolean                 e_msg_composer_get_smime_sign                   (EMsgComposer      *composer);
-void                     e_msg_composer_set_smime_encrypt                (EMsgComposer      *composer,
-									  gboolean           smime_encrypt);
-gboolean                 e_msg_composer_get_smime_encrypt                (EMsgComposer      *composer);
-char                    *e_msg_composer_get_sig_file_content             (const char        *sigfile,
-									  gboolean           in_html);
-void                     e_msg_composer_add_message_attachments          (EMsgComposer      *composer,
-									  CamelMimeMessage  *message,
-									  gboolean           just_inlines);
-void                     e_msg_composer_ignore                           (EMsgComposer      *composer,
-									  const char        *str);
-void                     e_msg_composer_drop_editor_undo                 (EMsgComposer      *composer);
-
-gboolean                 e_msg_composer_request_close_all                (void);
-void			 e_msg_composer_check_autosave			 (GtkWindow *parent);
-int			 e_msg_composer_get_remote_download_count   	 (EMsgComposer *composer);
-
-
-void			 e_msg_composer_reply_indent			 (EMsgComposer *composer);
-void			 e_msg_composer_insert_paragraph_before 	 (EMsgComposer *composer);
-void			 e_msg_composer_insert_paragraph_after		 (EMsgComposer *composer);
-void			 e_msg_composer_delete				 (EMsgComposer *composer);
-gchar*			 e_msg_composer_resolve_image_url 		 (EMsgComposer *composer, gchar *url);
-CamelMimePart*		 e_msg_composer_url_requested 			 (EMsgComposer *composer, gchar *url);
-
-void			 e_msg_composer_link_clicked			 (EMsgComposer *composer, const gchar *url);
-
-EMsgComposerHdrs*	 e_msg_composer_get_hdrs			 (EMsgComposer *composer);
-void			 e_msg_composer_set_saved			 (EMsgComposer *composer);
-void			 e_msg_composer_set_send_options		 (EMsgComposer *composer,
-									  gboolean      send_enable);
-GByteArray *            e_msg_composer_get_raw_message_text              (EMsgComposer *composer);
-
-struct _EAttachmentBar*          e_msg_composer_get_attachment_bar                (EMsgComposer *composer);
-
-void                     e_msg_composer_set_attach_path                  (EMsgComposer *composer, const gchar *path);
-const gchar *            e_msg_composer_get_attach_path                  (EMsgComposer *composer);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
 
-#endif /* ___E_MSG_COMPOSER_H__ */
+#endif /* E_MSG_COMPOSER_H */

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Wed Apr  2 19:37:22 2008
@@ -13,7 +13,7 @@
 # Required Packages
 m4_define([glib_minimum_version], [2.15.3])
 m4_define([gtk_minimum_version], [2.12.0])
-m4_define([eds_minimum_version], [2.21.92])
+m4_define([eds_minimum_version], [2.23.1])
 m4_define([gnome_icon_theme_minimum_version], [2.19.91])
 m4_define([gnome_vfs_minimum_version], [2.4.0])
 m4_define([libbonobo_minimum_version], [2.20.3])
@@ -1495,7 +1495,7 @@
 
 dnl --- evolution-addressbook flags
 
-EVOLUTION_ADDRESSBOOK_DEPS="libbonoboui-2.0 libglade-2.0 libgnomeui-2.0 gnome-vfs-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE camel-$EDS_PACKAGE"
+EVOLUTION_ADDRESSBOOK_DEPS="libbonoboui-2.0 libglade-2.0 libgnomeui-2.0 gnome-vfs-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE camel-$EDS_PACKAGE gtkhtml-editor"
 
 EVO_SET_COMPILE_FLAGS(EVOLUTION_ADDRESSBOOK, $EVOLUTION_ADDRESSBOOK_DEPS)
 AC_SUBST(EVOLUTION_ADDRESSBOOK_CFLAGS)
@@ -1524,7 +1524,7 @@
 AC_SUBST(LIBSOUP_CFLAGS)
 AC_SUBST(LIBSOUP_LIBS)
 
-EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gnome-vfs-module-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libecal-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE $HAL_REQUIREMENT $libnotify)
+EVO_SET_COMPILE_FLAGS(EVOLUTION_CALENDAR, libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gnome-vfs-module-2.0 libgtkhtml-$GTKHTML_PACKAGE libebook-$EDS_PACKAGE libecal-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE $HAL_REQUIREMENT $libnotify gtkhtml-editor)
 AC_SUBST(EVOLUTION_CALENDAR_CFLAGS)
 AC_SUBST(EVOLUTION_CALENDAR_LIBS)
 
@@ -1536,7 +1536,7 @@
 
 dnl --- evolution-mail flags
 
-EVO_SET_COMPILE_FLAGS(EVOLUTION_MAIL, camel-provider-$EDS_PACKAGE libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gnome-vfs-module-2.0 libgtkhtml-$GTKHTML_PACKAGE bonobo-activation-2.0 $mozilla_nss libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE)
+EVO_SET_COMPILE_FLAGS(EVOLUTION_MAIL, camel-provider-$EDS_PACKAGE libgnomeui-2.0 libbonoboui-2.0 libglade-2.0 gnome-vfs-module-2.0 libgtkhtml-$GTKHTML_PACKAGE gtkhtml-editor bonobo-activation-2.0 $mozilla_nss libebook-$EDS_PACKAGE libedataserverui-$EDS_PACKAGE)
 AC_SUBST(EVOLUTION_MAIL_CFLAGS)
 AC_SUBST(EVOLUTION_MAIL_LIBS)
 
@@ -1685,7 +1685,7 @@
 	      [enable_plugins="$enableval"],[enable_plugins=all])
 
 dnl Add any new plugins here
-plugins_base_always="calendar-file calendar-http calendar-weather itip-formatter plugin-manager default-source addressbook-file startup-wizard print-message mark-all-read groupwise-features groupwise-account-setup hula-account-setup mail-account-disable publish-calendar caldav imap-features google-account-setup"
+plugins_base_always="calendar-file calendar-http calendar-weather itip-formatter plugin-manager default-source addressbook-file startup-wizard mark-all-read groupwise-features groupwise-account-setup hula-account-setup mail-account-disable publish-calendar caldav imap-features google-account-setup"
 plugins_base="$plugins_base_always $SA_JUNK_PLUGIN $BF_JUNK_PLUGIN $EXCHANGE_PLUGIN $MONO_PLUGIN" 
 all_plugins_base="$plugins_base_always sa-junk-plugin bogo-junk-plugin exchange-operations mono"
 
@@ -1979,7 +1979,6 @@
 plugins/default-mailer/Makefile
 plugins/addressbook-file/Makefile
 plugins/startup-wizard/Makefile
-plugins/print-message/Makefile
 plugins/groupwise-account-setup/Makefile
 plugins/hula-account-setup/Makefile
 plugins/groupwise-features/Makefile

Modified: trunk/mail/em-composer-prefs.c
==============================================================================
--- trunk/mail/em-composer-prefs.c	(original)
+++ trunk/mail/em-composer-prefs.c	Wed Apr  2 19:37:22 2008
@@ -298,16 +298,24 @@
 	gtk_tree_model_get (model, &iter, 1, &sig, -1);
 
 	if (!sig->script) {
+		GtkWidget *editor;
+
 		/* normal signature */
 		if (!sig->filename || *sig->filename == '\0') {
 			g_free (sig->filename);
 			sig->filename = g_strdup (_("Unnamed"));
 		}
 
+		editor = e_signature_editor_new ();
+		e_signature_editor_set_signature (
+			E_SIGNATURE_EDITOR (editor), sig);
+
 		parent = gtk_widget_get_toplevel ((GtkWidget *) prefs);
-		parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+		if (GTK_WIDGET_TOPLEVEL (parent))
+			gtk_window_set_transient_for (
+				GTK_WINDOW (editor), GTK_WINDOW (parent));
 
-		mail_signature_editor (sig, (GtkWindow *) parent, FALSE);
+		gtk_widget_show (editor);
 	} else {
 		/* signature script */
 		GtkWidget *entry;
@@ -327,10 +335,11 @@
 void
 em_composer_prefs_new_signature (GtkWindow *parent, gboolean html)
 {
-	ESignature *sig;
+	GtkWidget *editor;
 
-	sig = mail_config_signature_new (NULL, FALSE, html);
-	mail_signature_editor (sig, parent, TRUE);
+	editor = e_signature_editor_new ();
+	gtk_window_set_transient_for (GTK_WINDOW (editor), parent);
+	gtk_widget_show (editor);
 }
 
 static void

Modified: trunk/mail/em-composer-utils.c
==============================================================================
--- trunk/mail/em-composer-utils.c	(original)
+++ trunk/mail/em-composer-utils.c	Wed Apr  2 19:37:22 2008
@@ -251,7 +251,7 @@
 {
 	CamelMimeMessage *message = NULL;
 	EDestination **recipients, **recipients_bcc;
-	gboolean send_html, confirm_html;
+	gboolean html_mode, send_html, confirm_html;
 	CamelInternetAddress *cia;
 	int hidden = 0, shown = 0;
 	int num = 0, num_bcc = 0, num_post = 0;
@@ -262,15 +262,17 @@
 	GList *postlist;
 	EMEvent *eme;
 	EMEventTargetComposer *target;
+	EComposerHeaderTable *table;
 
 	gconf = mail_config_get_gconf_client ();
+	table = e_msg_composer_get_header_table (composer);
 
 	/* We should do all of the validity checks based on the composer, and not on
 	   the created message, as extra interaction may occur when we get the message
 	   (e.g. to get a passphrase to sign a message) */
 
 	/* get the message recipients */
-	recipients = e_msg_composer_get_recipients (composer);
+	recipients = e_composer_header_table_get_destinations (table);
 
 	cia = camel_internet_address_new ();
 
@@ -295,7 +297,7 @@
 		}
 	}
 
-	recipients_bcc = e_msg_composer_get_bcc (composer);
+	recipients_bcc = e_composer_header_table_get_destinations_bcc (table);
 	if (recipients_bcc) {
 		for (i = 0; recipients_bcc[i] != NULL; i++) {
 			const char *addr = e_destination_get_address (recipients_bcc[i]);
@@ -314,7 +316,7 @@
 
 	camel_object_unref (cia);
 
-	postlist = e_msg_composer_hdrs_get_post_to(e_msg_composer_get_hdrs (composer));
+	postlist = e_composer_header_table_get_post_to (table);
 	num_post = g_list_length(postlist);
 	g_list_foreach(postlist, (GFunc)g_free, NULL);
 	g_list_free(postlist);
@@ -331,13 +333,15 @@
 			goto finished;
 	}
 
+	html_mode = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (composer));
 	send_html = gconf_client_get_bool (gconf, "/apps/evolution/mail/composer/send_html", NULL);
 	confirm_html = gconf_client_get_bool (gconf, "/apps/evolution/mail/prompts/unwanted_html", NULL);
 
 	/* Only show this warning if our default is to send html.  If it isn't, we've
 	   manually switched into html mode in the composer and (presumably) had a good
 	   reason for doing this. */
-	if (e_msg_composer_get_send_html (composer) && send_html && confirm_html) {
+	if (html_mode && send_html && confirm_html) {
+
 		gboolean html_problem = FALSE;
 
 		if (recipients) {
@@ -355,7 +359,7 @@
 	}
 
 	/* Check for no subject */
-	subject = e_msg_composer_get_subject (composer);
+	subject = e_composer_header_table_get_subject (table);
 	if (subject == NULL || subject[0] == '\0') {
 		if (!ask_confirm_for_empty_subject (composer))
 			goto finished;
@@ -384,7 +388,7 @@
 		goto finished;
 
 	/* Add info about the sending account */
-	account = e_msg_composer_get_preferred_account (composer);
+	account = e_composer_header_table_get_account (table);
 
 	if (account) {
 		/* FIXME: Why isn't this crap just in e_msg_composer_get_message? */
@@ -411,13 +415,15 @@
 void
 em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data)
 {
+	EComposerHeaderTable *table;
 	CamelMimeMessage *message;
 	CamelMessageInfo *info;
 	struct _send_data *send;
 	CamelFolder *mail_folder;
 	EAccount *account;
 
-	account = e_msg_composer_get_preferred_account (composer);
+	table = e_msg_composer_get_header_table (composer);
+	account = e_composer_header_table_get_account (table);
 	if (!account || !account->enabled) {
 		e_error_run((GtkWindow *)composer, "mail:send-no-account-enabled", NULL);
 		return;
@@ -466,7 +472,7 @@
 	if (!ok)
 		goto done;
 
-	e_msg_composer_set_saved (sdi->composer);
+	gtkhtml_editor_set_changed (GTKHTML_EDITOR (sdi->composer), FALSE);
 
 	if ((emcs = sdi->emcs) == NULL) {
 		emcs = emcs_new ();
@@ -532,6 +538,7 @@
 {
 	const char *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS);
 	CamelFolder *drafts_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS);
+	EComposerHeaderTable *table;
 	struct _save_draft_info *sdi;
 	CamelFolder *folder = NULL;
 	CamelMimeMessage *msg;
@@ -544,7 +551,8 @@
 
 	g_object_ref(composer);
 	msg = e_msg_composer_get_message_draft (composer);
-	account = e_msg_composer_get_preferred_account (composer);
+	table = e_msg_composer_get_header_table (composer);
+	account = e_composer_header_table_get_account (table);
 
 	sdi = g_malloc(sizeof(struct _save_draft_info));
 	sdi->composer = composer;
@@ -587,8 +595,13 @@
 }
 
 void
-em_composer_utils_setup_callbacks (EMsgComposer *composer, CamelFolder *folder, const char *uid,
-				   guint32 flags, guint32 set, CamelFolder *drafts, const char *drafts_uid)
+em_composer_utils_setup_callbacks (EMsgComposer *composer,
+                                   CamelFolder *folder,
+                                   const char *uid,
+				   guint32 flags,
+                                   guint32 set,
+                                   CamelFolder *drafts,
+                                   const char *drafts_uid)
 {
 	struct emcs_t *emcs;
 
@@ -620,6 +633,7 @@
 create_new_composer (const char *subject, const char *fromuri)
 {
 	EMsgComposer *composer;
+	EComposerHeaderTable *table;
 	EAccount *account = NULL;
 
 	composer = e_msg_composer_new ();
@@ -629,14 +643,9 @@
 	if (fromuri)
 		account = mail_config_get_account_by_source_url(fromuri);
 
-	/* If the account corresponding to the fromuri is not enabled.
-	 * We get the preffered account from the composer and use that
-	 * as the account to send the mail.
-	 */
-	if (!account)
-		account = e_msg_composer_get_preferred_account (composer);
-
-	e_msg_composer_set_headers (composer, account?account->name:NULL, NULL, NULL, NULL, subject);
+	table = e_msg_composer_get_header_table (composer);
+	e_composer_header_table_set_account (table, account);
+	e_composer_header_table_set_subject (table, subject);
 
 	em_composer_utils_setup_default_callbacks (composer);
 
@@ -653,13 +662,15 @@
 em_utils_compose_new_message (const char *fromuri)
 {
 	GtkWidget *composer;
+	GtkhtmlEditor *editor;
 
 	composer = (GtkWidget *) create_new_composer ("", fromuri);
 	if (composer == NULL)
 		return;
 
-	e_msg_composer_unset_changed ((EMsgComposer *)composer);
-	e_msg_composer_drop_editor_undo ((EMsgComposer *)composer);
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 
 	gtk_widget_show (composer);
 }
@@ -676,6 +687,8 @@
 em_utils_compose_new_message_with_mailto (const char *url, const char *fromuri)
 {
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
+	EComposerHeaderTable *table;
 	EAccount *account = NULL;
 
 	if (url != NULL)
@@ -683,14 +696,16 @@
 	else
 		composer = e_msg_composer_new ();
 
+	table = e_msg_composer_get_header_table (composer);
 	em_composer_utils_setup_default_callbacks (composer);
 
 	if (fromuri
 	    && (account = mail_config_get_account_by_source_url(fromuri)))
-		e_msg_composer_hdrs_set_from_account(e_msg_composer_get_hdrs(composer), account->name);
+		e_composer_header_table_set_account_name (table, account->name);
 
-	e_msg_composer_unset_changed (composer);
-	e_msg_composer_drop_editor_undo (composer);
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 
 	gtk_widget_show ((GtkWidget *) composer);
 	gdk_window_raise (((GtkWidget *) composer)->window);
@@ -708,14 +723,20 @@
 em_utils_post_to_folder (CamelFolder *folder)
 {
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
+	EComposerHeaderTable *table;
 	EAccount *account;
 
 	composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
+	table = e_msg_composer_get_header_table (composer);
 
 	if (folder != NULL) {
 		char *url = mail_tools_folder_to_url (folder);
+		GList *list = g_list_prepend (NULL, url);
+
+		e_composer_header_table_set_post_to_list (table, list);
 
-		e_msg_composer_hdrs_set_post_to (e_msg_composer_get_hdrs (composer), url);
+		g_list_free (list);
 		g_free (url);
 
 		url = camel_url_to_string (CAMEL_SERVICE (folder->parent_store)->url, CAMEL_URL_HIDE_ALL);
@@ -723,13 +744,15 @@
 		g_free (url);
 
 		if (account)
-			e_msg_composer_hdrs_set_from_account (e_msg_composer_get_hdrs(composer), account->name);
+			e_composer_header_table_set_account_name (
+				table, account->name);
 	}
 
 	em_composer_utils_setup_default_callbacks (composer);
 
-	e_msg_composer_unset_changed (composer);
-	e_msg_composer_drop_editor_undo (composer);
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 
 	gtk_widget_show ((GtkWidget *) composer);
 	gdk_window_raise (((GtkWidget *) composer)->window);
@@ -747,16 +770,25 @@
 em_utils_post_to_url (const char *url)
 {
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
+	EComposerHeaderTable *table;
 
 	composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_POST);
+	table = e_msg_composer_get_header_table (composer);
 
-	if (url != NULL)
-		e_msg_composer_hdrs_set_post_to (e_msg_composer_get_hdrs (composer), url);
+	if (url != NULL) {
+		GList *list = NULL;
+
+		list = g_list_prepend (list, (gpointer) url);
+		e_composer_header_table_set_post_to_list (table, list);
+		g_list_free (list);
+	}
 
 	em_composer_utils_setup_default_callbacks (composer);
 
-	e_msg_composer_unset_changed (composer);
-	e_msg_composer_drop_editor_undo (composer);
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 
 	gtk_widget_show ((GtkWidget *) composer);
 }
@@ -767,11 +799,14 @@
 edit_message (CamelMimeMessage *message, CamelFolder *drafts, const char *uid)
 {
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
 
 	composer = e_msg_composer_new_with_message (message);
 	em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, drafts, uid);
-	e_msg_composer_unset_changed (composer);
-	e_msg_composer_drop_editor_undo (composer);
+
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 
 	gtk_widget_show (GTK_WIDGET (composer));
 }
@@ -832,14 +867,17 @@
 forward_attached (CamelFolder *folder, GPtrArray *messages, CamelMimePart *part, char *subject, const char *fromuri)
 {
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
 
 	composer = create_new_composer (subject, fromuri);
 	if (composer == NULL)
 		return;
 
 	e_msg_composer_attach (composer, part);
-	e_msg_composer_unset_changed (composer);
-	e_msg_composer_drop_editor_undo (composer);
+
+	editor = GTKHTML_EDITOR (editor);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 
 	gtk_widget_show (GTK_WIDGET (composer));
 }
@@ -878,6 +916,7 @@
 {
 	CamelMimeMessage *message;
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
 	char *subject, *text;
 	int i;
 	guint32 flags;
@@ -905,8 +944,10 @@
 					e_msg_composer_add_message_attachments(composer, message, FALSE);
 
 				e_msg_composer_set_body_text (composer, text, len);
-				e_msg_composer_unset_changed (composer);
-				e_msg_composer_drop_editor_undo (composer);
+
+				editor = GTKHTML_EDITOR (composer);
+				gtkhtml_editor_set_changed (editor, FALSE);
+				gtkhtml_editor_drop_undo (editor);
 
 				gtk_widget_show (GTK_WIDGET (composer));
 			}
@@ -1076,14 +1117,17 @@
 em_utils_redirect_message (CamelMimeMessage *message)
 {
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
 
 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
 
 	composer = redirect_get_composer (message);
 
 	gtk_widget_show (GTK_WIDGET (composer));
-	e_msg_composer_unset_changed (composer);
-	e_msg_composer_drop_editor_undo (composer);
+
+	editor = GTKHTML_EDITOR (composer);
+	gtkhtml_editor_set_changed (editor, FALSE);
+	gtkhtml_editor_drop_undo (editor);
 }
 
 static void
@@ -1403,6 +1447,7 @@
 	const char *message_id, *references;
 	EDestination **tov, **ccv;
 	EMsgComposer *composer;
+	EComposerHeaderTable *table;
 	char *subject;
 
 	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
@@ -1431,7 +1476,11 @@
 		subject = g_strdup ("");
 	}
 
-	e_msg_composer_set_headers (composer, account ? account->name : NULL, tov, ccv, NULL, subject);
+	table = e_msg_composer_get_header_table (composer);
+	e_composer_header_table_set_account (table, account);
+	e_composer_header_table_set_subject (table, subject);
+	e_composer_header_table_set_destinations_to (table, tov);
+	e_composer_header_table_set_destinations_cc (table, ccv);
 
 	g_free (subject);
 
@@ -1447,7 +1496,8 @@
 		}
 
 		post = camel_address_encode((CamelAddress *)postto);
-		e_msg_composer_hdrs_set_post_to_base (e_msg_composer_get_hdrs(composer), store_url ? store_url : "", post);
+		e_composer_header_table_set_post_to_base (
+			table, store_url ? store_url : "", post);
 		g_free(post);
 		g_free (store_url);
 	}
@@ -1471,7 +1521,7 @@
 		e_msg_composer_add_header (composer, "References", references);
 	}
 
-	e_msg_composer_drop_editor_undo (composer);
+	gtkhtml_editor_drop_undo (GTKHTML_EDITOR (composer));
 
 	return composer;
 }
@@ -1904,7 +1954,7 @@
 		break;
 	}
 
-	e_msg_composer_drop_editor_undo (composer);
+	gtkhtml_editor_drop_undo (GTKHTML_EDITOR (composer));
 }
 
 struct _reply_data {
@@ -2019,7 +2069,8 @@
 	em_composer_utils_setup_callbacks (composer, folder, uid, flags, flags, NULL, NULL);
 
 	gtk_widget_show (GTK_WIDGET (composer));
-	e_msg_composer_unset_changed (composer);
+
+	gtkhtml_editor_set_changed (GTKHTML_EDITOR (composer), FALSE);
 }
 
 /* Posting replies... */
@@ -2033,10 +2084,13 @@
 	EDestination **tov = NULL;
 	CamelFolder *real_folder;
 	EMsgComposer *composer;
+	GtkhtmlEditor *editor;
+	EComposerHeaderTable *table;
 	char *subject, *url;
 	EAccount *account;
 	char *real_uid;
 	guint32 flags;
+	GList *list = NULL;
 
 	if (message == NULL)
 		return;
@@ -2060,6 +2114,7 @@
 	get_reply_sender (message, to, NULL);
 
 	composer = e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL_POST);
+	editor = GTKHTML_EDITOR (composer);
 
 	/* construct the tov/ccv */
 	tov = em_utils_camel_address_to_destination (to);
@@ -2074,12 +2129,19 @@
 		subject = g_strdup ("");
 	}
 
-	e_msg_composer_set_headers (composer, account ? account->name : NULL, tov, NULL, NULL, subject);
+	table = e_msg_composer_get_header_table (composer);
+	e_composer_header_table_set_account (table, account);
+	e_composer_header_table_set_subject (table, subject);
+	e_composer_header_table_set_destinations_to (table, tov);
 
 	g_free (subject);
 
 	url = mail_tools_folder_to_url (real_folder);
-	e_msg_composer_hdrs_set_post_to (e_msg_composer_get_hdrs(composer), url);
+	list = g_list_prepend (list, url);
+
+	e_composer_header_table_set_post_to_list (table, list);
+
+	g_list_free (list);
 	g_free (url);
 
 	/* Add In-Reply-To and References. */
@@ -2101,7 +2163,7 @@
 		e_msg_composer_add_header (composer, "References", references);
 	}
 
-	e_msg_composer_drop_editor_undo (composer);
+	gtkhtml_editor_drop_undo (editor);
 
 	e_msg_composer_add_message_attachments (composer, message, TRUE);
 
@@ -2110,7 +2172,8 @@
 	em_composer_utils_setup_callbacks (composer, real_folder, real_uid, flags, flags, NULL, NULL);
 
 	gtk_widget_show (GTK_WIDGET (composer));
-	e_msg_composer_unset_changed (composer);
+
+	gtkhtml_editor_set_changed (editor, FALSE);
 
 	camel_object_unref (real_folder);
 	camel_object_unref(to);

Modified: trunk/mail/mail-component-factory.c
==============================================================================
--- trunk/mail/mail-component-factory.c	(original)
+++ trunk/mail/mail-component-factory.c	Wed Apr  2 19:37:22 2008
@@ -24,8 +24,6 @@
 #include <config.h>
 #endif
 
-#include "em-composer-utils.h"
-#include "evolution-composer.h"
 #include "mail-component.h"
 #include "em-account-prefs.h"
 #include "em-mailer-prefs.h"
@@ -56,7 +54,6 @@
 
 #define FACTORY_ID	"OAFIID:GNOME_Evolution_Mail_Factory:" BASE_VERSION
 #define COMPONENT_ID	"OAFIID:GNOME_Evolution_Mail_Component:" BASE_VERSION
-#define COMPOSER_ID	"OAFIID:GNOME_Evolution_Mail_Composer:" BASE_VERSION
 #define FOLDER_INFO_ID	"OAFIID:GNOME_Evolution_FolderInfo:" BASE_VERSION
 
 static BonoboObject *
@@ -74,9 +71,6 @@
 		   || strcmp (component_id, EM_COMPOSER_PREFS_CONTROL_ID) == 0
 		   || strcmp (component_id, EM_NETWORK_PREFS_CONTROL_ID) == 0) {
 		return mail_config_control_factory_cb (factory, component_id, CORBA_OBJECT_NIL);
-	} else if (strcmp(component_id, COMPOSER_ID) == 0) {
-		/* FIXME: how to remove need for callbacks, probably make the composer more tightly integrated with mail */
-		return (BonoboObject *) evolution_composer_new (em_utils_composer_send_cb, em_utils_composer_save_draft_cb);
 	}
 
 	o = mail_importer_factory_cb(factory, component_id, NULL);

Modified: trunk/mail/mail-config.c
==============================================================================
--- trunk/mail/mail-config.c	(original)
+++ trunk/mail/mail-config.c	Wed Apr  2 19:37:22 2008
@@ -215,7 +215,7 @@
 	fprintf (rc, "widget \"*.EMFolderView.*.GtkHTML\" style \"evolution-mail-custom-fonts\"\n");
 	fprintf (rc, "widget \"*.EMFolderBrowser.*.GtkHTML\" style \"evolution-mail-custom-fonts\"\n");
 	fprintf (rc, "widget \"*.EMMessageBrowser.*.GtkHTML\" style \"evolution-mail-custom-fonts\"\n");
-	fprintf (rc, "widget \"*.BonoboPlug.*.GtkHTML\" style \"evolution-mail-custom-fonts\"\n");
+	fprintf (rc, "widget \"EMsgComposer.*.GtkHTML\" style \"evolution-mail-custom-fonts\"\n");
 	fprintf (rc, "widget \"*.EvolutionMailPrintHTMLWidget\" style \"evolution-mail-custom-fonts\"\n");
 	fflush (rc);
 	fclose (rc);

Modified: trunk/mail/mail-signature-editor.c
==============================================================================
--- trunk/mail/mail-signature-editor.c	(original)
+++ trunk/mail/mail-signature-editor.c	Wed Apr  2 19:37:22 2008
@@ -21,440 +21,478 @@
  *
  */
 
-#include <config.h>
+#include "mail-signature-editor.h"
 
 #include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include <gtk/gtk.h>
+#include <glib/gi18n.h>
 
-#include <bonobo.h>
-#include <bonobo/bonobo-stream-memory.h>
+#include <e-util/e-error.h>
+#include <e-util/e-signature-list.h>
+#include <composer/e-msg-composer.h>
 
-#include "e-util/e-error.h"
-#include "e-util/e-signature-list.h"
-#include "e-util/e-util-private.h"
-
-#include "e-msg-composer.h"
-#include "mail-signature-editor.h"
 #include "mail-config.h"
 
-#define d(x)
-
-#define GNOME_GTKHTML_EDITOR_CONTROL_ID "OAFIID:GNOME_GtkHTML_Editor:" GTKHTML_API_VERSION
-
-typedef struct _ESignatureEditor {
-	GtkWidget *win;
-	GtkWidget *control;
-	GtkWidget *name_entry;
-	GtkWidget *info_frame;
-
-	ESignature *sig;
-	gboolean is_new;
-	gboolean html;
-
-	GNOME_GtkHTML_Editor_Engine engine;
-} ESignatureEditor;
+#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorPrivate))
+
+enum {
+	PROP_0,
+	PROP_SIGNATURE
+};
 
-#define E_SIGNATURE_EDITOR(o) ((ESignatureEditor *) o)
+struct _ESignatureEditorPrivate {
+	GtkActionGroup *action_group;
+	ESignature *signature;
+	GtkWidget *entry;
+	gchar *original_name;
+};
 
-#define DEFAULT_WIDTH 600
-#define DEFAULT_HEIGHT 350
+static const gchar *ui =
+"<ui>\n"
+"  <menubar name='main-menu'>\n"
+"    <placeholder name='pre-edit-menu'>\n"
+"      <menu action='file-menu'>\n"
+"        <menuitem action='save-and-close'/>\n"
+"        <separator/>"
+"        <menuitem action='close'/>\n"
+"      </menu>\n"
+"    </placeholder>\n"
+"  </menubar>\n"
+"  <toolbar name='main-toolbar'>\n"
+"    <placeholder name='pre-main-toolbar'>\n"
+"      <toolitem action='save-and-close'/>\n"
+"    </placeholder>\n"
+"  </toolbar>\n"
+"</ui>";
 
-enum { REPLY_YES = 0, REPLY_NO, REPLY_CANCEL };
+static gpointer parent_class = NULL;
 
 static void
-destroy_editor (ESignatureEditor *editor)
+handle_error (GError **error)
 {
-	gtk_widget_destroy (editor->win);
-	g_free (editor);
+	if (*error != NULL) {
+		g_warning ("%s", (*error)->message);
+		g_clear_error (error);
+	}
 }
 
 static void
-menu_file_save_error (BonoboUIComponent *uic, CORBA_Environment *ev)
-{
-	char *err;
-
-	/* errno is set if the rename() fails in menu_file_save_cb */
-
-	err = ev->_major != CORBA_NO_EXCEPTION ? bonobo_exception_get_text (ev) : g_strdup (g_strerror (errno));
-
-	e_error_run(NULL, "mail:no-save-signature", err, NULL);
-	g_warning ("Exception while saving signature: %s", err);
-
-	g_free (err);
-}
-
-static GByteArray *
-get_text (Bonobo_PersistStream persist, const char *format, CORBA_Environment *ev)
-{
-	BonoboStream *stream;
-	BonoboStreamMem *stream_mem;
-	GByteArray *text;
-
-	stream = bonobo_stream_mem_create (NULL, 0, FALSE, TRUE);
-	Bonobo_PersistStream_save (persist, (Bonobo_Stream)bonobo_object_corba_objref (BONOBO_OBJECT (stream)),
-				   format, ev);
-
-	if (ev->_major != CORBA_NO_EXCEPTION)
-		return NULL;
-
-	stream_mem = BONOBO_STREAM_MEM (stream);
-
-	text = g_byte_array_new ();
-	g_byte_array_append (text, (unsigned char *)stream_mem->buffer, stream_mem->pos);
-	bonobo_object_unref (BONOBO_OBJECT (stream));
-
-	return text;
-}
-
-static ssize_t
-write_all (int fd, const char *buf, size_t n)
+action_close_cb (GtkAction *action,
+                 ESignatureEditor *editor)
 {
-	ssize_t w, nwritten = 0;
-
-	do {
-		do {
-			w = write (fd, buf + nwritten, n - nwritten);
-		} while (w == -1 && (errno == EINTR || errno == EAGAIN));
-
-		if (w > 0)
-			nwritten += w;
-	} while (nwritten < n && w != -1);
-
-	if (w == -1)
-		return -1;
+	gboolean something_changed = FALSE;
+	const gchar *original_name;
+	const gchar *signature_name;
+
+	original_name = editor->priv->original_name;
+	signature_name = gtk_entry_get_text (GTK_ENTRY (editor->priv->entry));
+
+	something_changed |= gtkhtml_editor_has_undo (GTKHTML_EDITOR (editor));
+	something_changed |= (strcmp (signature_name, original_name) != 0);
+
+	if (something_changed) {
+		gint response;
+
+		response = e_error_run (
+			GTK_WINDOW (editor),
+			"mail:ask-signature-changed", NULL);
+		if (response == GTK_RESPONSE_YES) {
+			GtkActionGroup *action_group;
+
+			action_group = editor->priv->action_group;
+			action = gtk_action_group_get_action (
+				action_group, "save-and-close");
+			gtk_action_activate (action);
+			return;
+		} else if (response == GTK_RESPONSE_CANCEL)
+			return;
+	}
 
-	return nwritten;
+	gtk_widget_destroy (GTK_WIDGET (editor));
 }
 
 static void
-menu_file_save_cb (BonoboUIComponent *uic, void *user_data, const char *path)
+action_save_and_close_cb (GtkAction *action,
+                          ESignatureEditor *editor)
 {
-	ESignatureEditor *editor = user_data;
+	GtkWidget *entry;
+	ESignatureList *signature_list;
 	ESignature *signature;
-	Bonobo_PersistStream pstream_iface;
-	char *dirname, *base, *filename, *name;
-	CORBA_Environment ev;
-	GByteArray *text;
-	int fd;
-
-	d(printf ("editor->sig->filename = %s\n", editor->sig->filename));
-	dirname = g_path_get_dirname (editor->sig->filename);
-	d(printf ("dirname = %s\n", dirname));
-	base = g_path_get_basename (editor->sig->filename);
-	d(printf ("basename = %s\n", base));
-	filename = g_strdup_printf ("%s/.#%s", dirname, base);
-	d(printf ("filename = %s\n", filename));
-	g_free (dirname);
-	g_free (base);
-
-	CORBA_exception_init (&ev);
-	pstream_iface = Bonobo_Unknown_queryInterface
-		(bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
-		 "IDL:Bonobo/PersistStream:1.0", &ev);
-
-	if (ev._major != CORBA_NO_EXCEPTION)
-		goto exception;
-
-	if ((fd = g_open (filename, O_WRONLY | O_TRUNC | O_CREAT, 0666)) == -1)
-		goto exception;
+	ESignature *same_name;
+	const gchar *filename;
+	gchar *signature_name;
+	gboolean html;
+	GError *error = NULL;
 
-	text = get_text (pstream_iface, editor->html ? "text/html" : "text/plain", &ev);
-	if (ev._major != CORBA_NO_EXCEPTION) {
-		close (fd);
-		goto exception;
-	}
+	entry = editor->priv->entry;
+	html = gtkhtml_editor_get_html_mode (GTKHTML_EDITOR (editor));
 
-	if (write_all (fd, (char *)text->data, text->len) == -1) {
-		g_byte_array_free (text, TRUE);
-		close (fd);
-		goto exception;
+	if (editor->priv->signature == NULL)
+		signature = mail_config_signature_new (NULL, FALSE, html);
+	else {
+		signature = g_object_ref (editor->priv->signature);
+		signature->html = html;
 	}
 
-	g_byte_array_free (text, TRUE);
-	close (fd);
-
-	if (g_rename (filename, editor->sig->filename) == -1)
-		goto exception;
+	filename = signature->filename;
+	gtkhtml_editor_save (GTKHTML_EDITOR (editor), filename, html, &error);
 
-	g_free (filename);
+	if (error != NULL) {
+		e_error_run (
+			GTK_WINDOW (editor),
+			"mail:no-save-signature",
+			error->message, NULL);
+		g_clear_error (&error);
+		return;
+	}
 
-	editor->sig->html = editor->html;
+	signature_list = mail_config_get_signatures ();
 
-	name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (editor->name_entry))));
+	signature_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+	g_strstrip (signature_name);
 
-	if (g_str_equal(name, "") ) {
-		e_error_run ((GtkWindow *)editor->win, "mail:blank-signature", NULL);
+	/* Make sure the signature name is not blank. */
+	if (*signature_name == '\0') {
+		e_error_run (
+			GTK_WINDOW (editor),
+			"mail:blank-signature", NULL);
+		gtk_widget_grab_focus (entry);
+		g_free (signature_name);
 		return;
 	}
 
-	if ( (signature = (ESignature *)e_signature_list_find (mail_config_get_signatures (), E_SIGNATURE_FIND_NAME, name)) && !g_str_equal(signature->uid, editor->sig->uid) ) {
-		e_error_run ((GtkWindow *)editor->win, "mail:signature-already-exists", name, NULL);
+	/* Don't overwrite an existing signature of the same name.
+	 * XXX ESignatureList misuses const. */
+	same_name = (ESignature *) e_signature_list_find (
+		signature_list, E_SIGNATURE_FIND_NAME, signature_name);
+	if (same_name != NULL && strcmp (signature->uid, same_name->uid) != 0) {
+		e_error_run (
+			GTK_WINDOW (editor),
+			"mail:signature-already-exists",
+			signature_name, NULL);
+		gtk_widget_grab_focus (entry);
+		g_free (signature_name);
 		return;
 	}
 
-	if (editor->sig->name)
-		g_free (editor->sig->name);
+	g_free (signature->name);
+	signature->name = signature_name;
 
-	editor->sig->name = name;
+	if (editor->priv->signature != NULL)
+		e_signature_list_change (signature_list, signature);
+	else
+		mail_config_add_signature (signature);
+
+	gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+static GtkActionEntry entries[] = {
+
+	{ "close",
+	  GTK_STOCK_CLOSE,
+	  N_("_Close"),
+	  "<Control>w",
+	  NULL,
+	  G_CALLBACK (action_close_cb) },
+
+	{ "save-and-close",
+	  GTK_STOCK_SAVE,
+	  N_("_Save and Close"),
+	  "<Control>Return",
+	  NULL,
+	  G_CALLBACK (action_save_and_close_cb) },
+
+	{ "file-menu",
+	  NULL,
+	  N_("_File"),
+	  NULL,
+	  NULL,
+	  NULL }
+};
 
-	/* if the signature isn't already saved in the config, save it there now... */
-	if (editor->is_new) {
-		mail_config_add_signature (editor->sig);
-		editor->is_new = FALSE;
-	} else {
-		e_signature_list_change (mail_config_get_signatures (), editor->sig);
-	}
+static gboolean
+signature_editor_delete_event_cb (ESignatureEditor *editor,
+                                  GdkEvent *event)
+{
+	GtkActionGroup *action_group;
+	GtkAction *action;
+
+	action_group = editor->priv->action_group;
+	action = gtk_action_group_get_action (action_group, "close");
+	gtk_action_activate (action);
 
-	destroy_editor (editor);
+	return TRUE;
+}
 
-	return;
+static void
+signature_editor_set_property (GObject *object,
+                               guint property_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SIGNATURE:
+			e_signature_editor_set_signature (
+				E_SIGNATURE_EDITOR (object),
+				g_value_get_object (value));
+			return;
+	}
 
-exception:
-	menu_file_save_error (uic, &ev);
-	CORBA_exception_free (&ev);
-	g_unlink (filename);
-	g_free (filename);
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
 static void
-exit_dialog_cb (int reply, ESignatureEditor *editor)
-{
-	switch (reply) {
-	case GTK_RESPONSE_YES:
-		menu_file_save_cb (NULL, editor, NULL);
-		break;
-	case GTK_RESPONSE_NO:
-		destroy_editor (editor);
-		break;
+signature_editor_get_property (GObject *object,
+                               guint property_id,
+                               GValue *value,
+                               GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_SIGNATURE:
+			g_value_set_object (
+				value, e_signature_editor_get_signature (
+				E_SIGNATURE_EDITOR (object)));
+			return;
 	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
 static void
-do_exit (ESignatureEditor *editor)
+signature_editor_dispose (GObject *object)
 {
-	CORBA_Environment ev;
-
-	CORBA_exception_init (&ev);
+	ESignatureEditorPrivate *priv;
 
-	if (GNOME_GtkHTML_Editor_Engine_hasUndo (editor->engine, &ev) || GPOINTER_TO_INT( g_object_get_data( G_OBJECT(editor->win), "name-changed"))) {
-		int button;
+	priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object);
 
-		button = e_error_run((GtkWindow *)editor->win, "mail:ask-signature-changed", NULL);
-		exit_dialog_cb (button, editor);
-	} else
-		destroy_editor (editor);
+	if (priv->action_group != NULL) {
+		g_object_unref (priv->action_group);
+		priv->action_group = NULL;
+	}
 
-	CORBA_exception_free (&ev);
-}
+	if (priv->signature != NULL) {
+		g_object_unref (priv->signature);
+		priv->signature = NULL;
+	}
 
-static int
-delete_event_cb (GtkWidget *w, GdkEvent *event, ESignatureEditor *editor)
-{
-	do_exit (editor);
+	if (priv->entry != NULL) {
+		g_object_unref (priv->entry);
+		priv->entry = NULL;
+	}
 
-	return TRUE;
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
-menu_file_close_cb (BonoboUIComponent *uic, gpointer data, const char *path)
+signature_editor_finalize (GObject *object)
 {
-	ESignatureEditor *editor;
+	ESignatureEditorPrivate *priv;
+
+	priv = E_SIGNATURE_EDITOR_GET_PRIVATE (object);
+
+	g_free (priv->original_name);
 
-	editor = E_SIGNATURE_EDITOR (data);
-	do_exit (editor);
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static void
-menu_file_save_close_cb (BonoboUIComponent *uic, gpointer data, const char *path)
+signature_editor_class_init (ESignatureEditorClass *class)
 {
-	ESignatureEditor *editor;
+	GObjectClass *object_class;
 
-	editor = E_SIGNATURE_EDITOR (data);
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (ESignatureEditorPrivate));
 
-	menu_file_save_cb (uic, editor, path);
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = signature_editor_set_property;
+	object_class->get_property = signature_editor_get_property;
+	object_class->dispose = signature_editor_dispose;
+	object_class->finalize = signature_editor_finalize;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SIGNATURE,
+		g_param_spec_object (
+			"signature",
+			NULL,
+			NULL,
+			E_TYPE_SIGNATURE,
+			G_PARAM_READWRITE));
 }
 
-static BonoboUIVerb verbs [] = {
-
-	BONOBO_UI_VERB ("FileSave",       menu_file_save_cb),
-	BONOBO_UI_VERB ("FileClose",      menu_file_close_cb),
-	BONOBO_UI_VERB ("FileSaveClose",  menu_file_save_close_cb),
-
-	BONOBO_UI_VERB_END
-};
-
 static void
-load_signature (ESignatureEditor *editor)
+signature_editor_init (ESignatureEditor *editor)
 {
-	CORBA_Environment ev;
-
-	if (editor->html) {
-		Bonobo_PersistFile pfile_iface;
-
-		CORBA_exception_init (&ev);
-		pfile_iface = Bonobo_Unknown_queryInterface (bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),"IDL:Bonobo/PersistFile:1.0", &ev);
-		Bonobo_PersistFile_load (pfile_iface, editor->sig->filename, &ev);
-		CORBA_exception_free (&ev);
-	} else {
-		Bonobo_PersistStream pstream_iface;
-		BonoboStream *stream;
-		char *data, *html;
-
-		data = e_msg_composer_get_sig_file_content (editor->sig->filename, FALSE);
-		html = g_strdup_printf ("<PRE>\n%s", data);
-		g_free (data);
-
-		CORBA_exception_init (&ev);
-		pstream_iface = Bonobo_Unknown_queryInterface
-			(bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)),
-			 "IDL:Bonobo/PersistStream:1.0",&ev);
-		stream = bonobo_stream_mem_create (html, strlen (html), TRUE, FALSE);
-
-		if (stream == NULL) {
-			g_warning ("Couldn't create memory stream\n");
-		} else {
-			BonoboObject *stream_object;
-			Bonobo_Stream corba_stream;
-
-			stream_object = BONOBO_OBJECT (stream);
-			corba_stream = bonobo_object_corba_objref (stream_object);
-			Bonobo_PersistStream_load (pstream_iface, corba_stream,
-						   "text/html", &ev);
-		}
-
-		Bonobo_Unknown_unref (pstream_iface, &ev);
-		CORBA_Object_release (pstream_iface, &ev);
-		CORBA_exception_free (&ev);
-		bonobo_object_unref (BONOBO_OBJECT (stream));
-
-		g_free (html);
+	GtkActionGroup *action_group;
+	GtkUIManager *manager;
+	GtkWidget *container;
+	GtkWidget *widget;
+	GtkWidget *vbox;
+	GError *error = NULL;
+
+	editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor);
+	vbox = GTKHTML_EDITOR (editor)->vbox;
+
+	manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor));
+
+	gtk_ui_manager_add_ui_from_string (manager, ui, -1, &error);
+	handle_error (&error);
+
+	action_group = gtk_action_group_new ("signature");
+	gtk_action_group_set_translation_domain (
+		action_group, GETTEXT_PACKAGE);
+	gtk_action_group_add_actions (
+		action_group, entries,
+		G_N_ELEMENTS (entries), editor);
+	gtk_ui_manager_insert_action_group (manager, action_group, 0);
+	editor->priv->action_group = g_object_ref (action_group);
+
+	gtk_ui_manager_ensure_update (manager);
+
+	gtk_window_set_title (GTK_WINDOW (editor), _("Edit Signature"));
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
+	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
+	/* Position 2 should be between the main and style toolbars. */
+	gtk_box_reorder_child (GTK_BOX (vbox), widget, 2);
+	gtk_widget_show (widget);
+	container = widget;
+
+	widget = gtk_entry_new ();
+	gtk_box_pack_end (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	editor->priv->entry = g_object_ref_sink (widget);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new_with_mnemonic (_("_Signature Name:"));
+	gtk_label_set_mnemonic_widget (GTK_LABEL (widget), editor->priv->entry);
+	gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		editor, "delete-event",
+		G_CALLBACK (signature_editor_delete_event_cb), NULL);
+
+	e_signature_editor_set_signature (editor, NULL);
+}
+
+GType
+e_signature_editor_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (ESignatureEditorClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) signature_editor_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (ESignatureEditor),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) signature_editor_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTKHTML_TYPE_EDITOR, "ESignatureEditor",
+			&type_info, 0);
 	}
+
+	return type;
 }
 
-static void
-sig_name_changed (GtkWidget *w, ESignatureEditor *editor)
+GtkWidget *
+e_signature_editor_new (void)
 {
-	g_object_set_data ( G_OBJECT(editor->win), "name-changed", GINT_TO_POINTER(1));
+	return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL);
 }
 
-static void
-format_html_cb (BonoboUIComponent           *component,
-		const char                  *path,
-		Bonobo_UIComponent_EventType type,
-		const char                  *state,
-		gpointer                     data)
-
+ESignature *
+e_signature_editor_get_signature (ESignatureEditor *editor)
 {
-	ESignatureEditor *editor = (ESignatureEditor *) data;
+	g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL);
 
-	if (type != Bonobo_UIComponent_STATE_CHANGED)
-		return;
-
-	editor->html = atoi (state);
-	bonobo_widget_set_property (BONOBO_WIDGET (editor->control), "FormatHTML", TC_CORBA_boolean, editor->html, NULL);
+	return editor->priv->signature;
 }
 
 void
-mail_signature_editor (ESignature *sig, GtkWindow *parent, gboolean is_new)
+e_signature_editor_set_signature (ESignatureEditor *editor,
+                                  ESignature *signature)
 {
-	CORBA_Environment ev;
-	ESignatureEditor *editor;
-	BonoboUIComponent *component;
-	BonoboUIContainer *container;
-	GtkWidget *vbox, *hbox, *label, *frame, *vbox1;
-	char *xmlfile;
+	const gchar *filename;
+	const gchar *signature_name;
+	gchar *contents;
+	gsize length;
+	GError *error = NULL;
+
+	g_return_if_fail (E_IS_SIGNATURE_EDITOR (editor));
+
+	if (signature != NULL)
+		g_return_if_fail (E_SIGNATURE (signature));
+
+	if (editor->priv->signature != NULL) {
+		g_object_unref (editor->priv->signature);
+		editor->priv->signature = NULL;
+	}
 
-	if (!sig->filename || !*sig->filename)
-		return;
+	if (signature == NULL)
+		goto exit;
 
-	editor = g_new0 (ESignatureEditor, 1);
+	editor->priv->signature = g_object_ref (signature);
 
-	editor->sig = sig;
-	editor->html = sig->html;
-	editor->is_new = is_new;
-
-	editor->win = bonobo_window_new ("e-sig-editor", _("Edit signature"));
-	gtk_window_set_type_hint (GTK_WINDOW (editor->win), GDK_WINDOW_TYPE_HINT_DIALOG);
-	gtk_window_set_default_size (GTK_WINDOW (editor->win), DEFAULT_WIDTH, DEFAULT_HEIGHT);
-	if (parent != NULL)
-		gtk_window_set_transient_for (GTK_WINDOW (editor->win), parent);
-	g_object_set (editor->win, "allow_shrink", FALSE, "allow_grow", TRUE, NULL);
-
-	g_object_set_data (G_OBJECT(editor->win), "name-changed", GINT_TO_POINTER(0));
-
-	container = bonobo_window_get_ui_container (BONOBO_WINDOW(editor->win));
-
-	component = bonobo_ui_component_new_default ();
-	bonobo_ui_component_set_container (component, bonobo_object_corba_objref (BONOBO_OBJECT (container)), NULL);
-	bonobo_ui_component_add_verb_list_with_data (component, verbs, editor);
-
-	xmlfile = g_build_filename (EVOLUTION_UIDIR,
-				    "evolution-signature-editor.xml",
-				    NULL);
-	bonobo_ui_util_set_ui (component, PREFIX,
-			       xmlfile,
-			       "evolution-signature-editor", NULL);
-	g_free (xmlfile);
+	/* Load signature content. */
 
-	editor->control = bonobo_widget_new_control (GNOME_GTKHTML_EDITOR_CONTROL_ID,
-						     bonobo_ui_component_get_container (component));
+	filename = signature->filename;
 
-	if (editor->control == NULL) {
-		g_warning ("Cannot get '" GNOME_GTKHTML_EDITOR_CONTROL_ID "'.");
+	if (signature->html)
+		g_file_get_contents (filename, &contents, &length, &error);
+	else {
+		gchar *data;
 
-		destroy_editor (editor);
-		return;
+		data = e_msg_composer_get_sig_file_content (filename, FALSE);
+		contents = g_strdup_printf ("<PRE>\n%s", data);
+		length = -1;
+		g_free (data);
 	}
 
-	editor->engine = (GNOME_GtkHTML_Editor_Engine) Bonobo_Unknown_queryInterface
-		(bonobo_widget_get_objref (BONOBO_WIDGET (editor->control)), "IDL:GNOME/GtkHTML/Editor/Engine:1.0", &ev);
-	CORBA_exception_free(&ev);
-	load_signature (editor);
-
-	bonobo_ui_component_set_prop (component, "/commands/FormatHtml", "state", editor->html ? "1" : "0", NULL);
-	bonobo_ui_component_add_listener (component, "FormatHtml", format_html_cb, editor);
-
-	g_signal_connect (editor->win, "delete_event", G_CALLBACK (delete_event_cb), editor);
-
-	vbox = gtk_vbox_new (FALSE, 0);
-	hbox = gtk_hbox_new (FALSE, 4);
-	vbox1 = gtk_vbox_new (FALSE, 3);
-	gtk_container_set_border_width (GTK_CONTAINER (vbox1), 3);
-	label = gtk_label_new (_("Enter a name for this signature."));
-	gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
-	gtk_box_pack_start (GTK_BOX (vbox1), label, FALSE, TRUE, 0);
-	label = gtk_label_new (_("Name:"));
-	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
-	editor->name_entry = gtk_entry_new ();
-	gtk_entry_set_text (GTK_ENTRY (editor->name_entry), sig->name);
-	g_signal_connect (editor->name_entry, "changed", G_CALLBACK (sig_name_changed), editor);
-	gtk_box_pack_start_defaults (GTK_BOX (hbox), editor->name_entry);
-	frame = gtk_frame_new (NULL);
-	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
-	gtk_box_pack_start (GTK_BOX (vbox1), hbox, FALSE, TRUE, 0);
-	gtk_container_add (GTK_CONTAINER (frame), vbox1);
-	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
-	gtk_widget_show_all (vbox);
-	gtk_box_pack_start_defaults (GTK_BOX (vbox), editor->control);
-
-	bonobo_window_set_contents (BONOBO_WINDOW (editor->win), vbox);
-	bonobo_widget_set_property (BONOBO_WIDGET (editor->control), "FormatHTML", TC_CORBA_boolean, editor->html, NULL);
-	gtk_widget_show (GTK_WIDGET (editor->win));
-	gtk_widget_show (GTK_WIDGET (editor->control));
+	if (error == NULL) {
+		gtkhtml_editor_set_html_mode (
+			GTKHTML_EDITOR (editor), signature->html);
+		gtkhtml_editor_set_text_html (
+			GTKHTML_EDITOR (editor), contents, length);
+		g_free (contents);
+	} else {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+	}
 
-	if (is_new)
-		gtk_widget_grab_focus (editor->name_entry);
+exit:
+	if (signature != NULL)
+		signature_name = signature->name;
+	else
+		signature_name = _("Unnamed");
+
+	/* Set the entry text before we grab focus. */
+	g_free (editor->priv->original_name);
+	editor->priv->original_name = g_strdup (signature_name);
+	gtk_entry_set_text (GTK_ENTRY (editor->priv->entry), signature_name);
+
+	/* Set the focus appropriately.  If this is a new signature, draw
+	 * the user's attention to the signature name entry.  Otherwise go
+	 * straight to the editing area. */
+	if (signature == NULL)
+		gtk_widget_grab_focus (editor->priv->entry);
 	else {
-		CORBA_exception_init (&ev);
-		GNOME_GtkHTML_Editor_Engine_runCommand (editor->engine, "grab-focus", &ev);
-		CORBA_exception_free (&ev);
+		GtkHTML *html;
+
+		html = gtkhtml_editor_get_html (GTKHTML_EDITOR (editor));
+		gtk_widget_grab_focus (GTK_WIDGET (html));
 	}
+
+	g_object_notify (G_OBJECT (editor), "signature");
 }

Modified: trunk/mail/mail-signature-editor.h
==============================================================================
--- trunk/mail/mail-signature-editor.h	(original)
+++ trunk/mail/mail-signature-editor.h	Wed Apr  2 19:37:22 2008
@@ -24,18 +24,49 @@
 #ifndef MAIL_SIGNATURE_EDITOR_H
 #define MAIL_SIGNATURE_EDITOR_H
 
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
+#include <gtkhtml-editor.h>
+#include <e-util/e-signature.h>
 
-struct _ESignature;
-struct _GtkWindow;
+/* Standard GObject macros */
+#define E_TYPE_SIGNATURE_EDITOR \
+	(e_signature_editor_get_type ())
+#define E_SIGNATURE_EDITOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditor))
+#define E_SIGNATURE_EDITOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
+#define E_IS_SIGNATURE_EDITOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SIGNATURE_EDITOR))
+#define E_IS_SIGNATURE_EDITOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SIGNATURE_EDITOR))
+#define E_SIGNATURE_EDITOR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SIGNATURE_EDITOR, ESignatureEditorClass))
 
-void mail_signature_editor (struct _ESignature *sig, struct _GtkWindow *parent, int is_new);
+G_BEGIN_DECLS
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+typedef struct _ESignatureEditor ESignatureEditor;
+typedef struct _ESignatureEditorClass ESignatureEditorClass;
+typedef struct _ESignatureEditorPrivate ESignatureEditorPrivate;
 
-#endif
+struct _ESignatureEditor {
+	GtkhtmlEditor parent;
+	ESignatureEditorPrivate *priv;
+};
+
+struct _ESignatureEditorClass {
+	GtkhtmlEditorClass parent_class;
+};
+
+GType		e_signature_editor_get_type	 (void);
+GtkWidget *	e_signature_editor_new		 (void);
+ESignature *	e_signature_editor_get_signature (ESignatureEditor *editor);
+void		e_signature_editor_set_signature (ESignatureEditor *editor,
+						  ESignature *signature);
+
+G_END_DECLS
+
+#endif /* MAIL_SIGNATURE_EDITOR_H */

Modified: trunk/plugins/exchange-operations/Makefile.am
==============================================================================
--- trunk/plugins/exchange-operations/Makefile.am	(original)
+++ trunk/plugins/exchange-operations/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -5,6 +5,7 @@
 	-I$(top_builddir)/composer			\
 	-I$(top_builddir)/mail				\
 	$(CAMEL_EXCHANGE_CFLAGS)                        \
+	$(EVOLUTION_MAIL_CFLAGS)			\
 	-DEVOLUTION_GLADEDIR=\""$(gladedir)"\"          \
 	-DCONNECTOR_GLADEDIR=\""$(gladedir)"\"
 
@@ -54,7 +55,8 @@
 	$(top_builddir)/calendar/gui/libevolution-calendar.la 	\
 	$(top_builddir)/mail/libevolution-mail.la 		\
 	$(top_builddir)/addressbook/gui/component/libevolution-addressbook.la \
-	$(CAMEL_EXCHANGE_LIBS)
+	$(CAMEL_EXCHANGE_LIBS)					\
+	$(EVOLUTION_MAIL_LIBS)
 
 liborg_gnome_exchange_operations_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
 

Modified: trunk/plugins/exchange-operations/exchange-mail-send-options.c
==============================================================================
--- trunk/plugins/exchange-operations/exchange-mail-send-options.c	(original)
+++ trunk/plugins/exchange-operations/exchange-mail-send-options.c	Wed Apr  2 19:37:22 2008
@@ -30,7 +30,6 @@
 #include "mail/em-event.h"
 
 #include "composer/e-msg-composer.h"
-#include "composer/e-msg-composer-hdrs.h"
 #include "libedataserver/e-account.h"
 
 #include "exchange-send-options.h"
@@ -43,7 +42,6 @@
 append_to_header (ExchangeSendOptionsDialog *dialog, gint state, gpointer data)
 {
 	EMsgComposer *composer;
-	EMsgComposerHdrs *hdrs;
 	CamelAddress *sender_address;
 	const char *sender_id, *recipient_id;
 	struct _camel_header_address *addr;
@@ -86,8 +84,7 @@
 		else
 			e_msg_composer_remove_header (composer, "Sensitivity");
 
-		hdrs = e_msg_composer_get_hdrs (composer);
-		sender_address = (CamelAddress *) e_msg_composer_hdrs_get_from (hdrs);
+		sender_address = (CamelAddress *) e_msg_composer_get_from (composer);
 		sender_id = (const char*) camel_address_encode (sender_address);
 
 		addr = camel_header_address_decode (dialog->options->delegate_address, NULL);
@@ -122,11 +119,12 @@
 		}
 
 		if (dialog->options->delivery_enabled) {
-			EMsgComposerHdrs *hdrs = e_msg_composer_get_hdrs(composer);
+			EComposerHeaderTable *table;
 			EAccount *account;
 			char *mdn_address;
 
-			account = e_msg_composer_hdrs_get_from_account (hdrs);
+			table = e_msg_composer_get_header_table (composer);
+			account = e_composer_header_table_get_account (table);
 			mdn_address = account->id->reply_to;
 			if (!mdn_address || !*mdn_address)
 				mdn_address = account->id->address;
@@ -136,11 +134,12 @@
 			e_msg_composer_remove_header (composer, "Return-Receipt-To");
 
 		if (dialog->options->read_enabled) {
-			EMsgComposerHdrs *hdrs = e_msg_composer_get_hdrs(composer);
+			EComposerHeaderTable *table;
 			EAccount *account;
 			char *mdn_address;
 
-			account = e_msg_composer_hdrs_get_from_account (hdrs);
+			table = e_msg_composer_get_header_table (composer);
+			account = e_composer_header_table_get_account (table);
 			mdn_address = account->id->reply_to;
 			if (!mdn_address || !*mdn_address)
 				mdn_address = account->id->address;
@@ -169,10 +168,12 @@
 org_gnome_exchange_send_options (EPlugin *ep, EMEventTargetComposer *target)
 {
 	EMsgComposer *composer = target->composer;
+	EComposerHeaderTable *table;
 	EAccount *account = NULL;
 	char *temp = NULL;
 
-	account = e_msg_composer_get_preferred_account (composer);
+	table = e_msg_composer_get_header_table (composer);
+	account = e_composer_header_table_get_account (table);
 	if (!account)
 		return;
 

Modified: trunk/plugins/groupwise-features/mail-send-options.c
==============================================================================
--- trunk/plugins/groupwise-features/mail-send-options.c	(original)
+++ trunk/plugins/groupwise-features/mail-send-options.c	Wed Apr  2 19:37:22 2008
@@ -142,10 +142,12 @@
 {
 
 	EMsgComposer *comp = (struct _EMsgComposer *)t->composer ;
+	EComposerHeaderTable *table;
 	EAccount *account = NULL;
 	char *temp = NULL;
 
-	account = e_msg_composer_get_preferred_account (comp) ;
+	table = e_msg_composer_get_header_table (comp);
+	account = e_composer_header_table_get_account (table);
 	if (!account)
 		return;
 

Modified: trunk/plugins/mailing-list-actions/mailing-list-actions.c
==============================================================================
--- trunk/plugins/mailing-list-actions/mailing-list-actions.c	(original)
+++ trunk/plugins/mailing-list-actions/mailing-list-actions.c	Wed Apr  2 19:37:22 2008
@@ -150,7 +150,9 @@
 				/* directly send message */
 				composer = e_msg_composer_new_from_url (url);
 				if ((account = mail_config_get_account_by_source_url (action_data->uri)))
-					e_msg_composer_hdrs_set_from_account (e_msg_composer_get_hdrs(composer), account->name);
+					e_composer_header_table_set_account (
+						e_msg_composer_get_header_table (composer),
+						account);
 				em_utils_composer_send_cb (composer, NULL);
 			} else if (send_message_response == GTK_RESPONSE_NO) {
 				/* show composer */

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Wed Apr  2 19:37:22 2008
@@ -174,12 +174,14 @@
 calendar/gui/weekday-picker.c
 calendar/importers/icalendar-importer.c
 calendar/zones.h
+composer/e-composer-autosave.c
+composer/e-composer-actions.c
+composer/e-composer-header-table.c
 composer/e-composer-name-header.c
 composer/e-composer-post-header.c
-composer/e-msg-composer-hdrs.c
-composer/e-msg-composer-select-file.c
+composer/e-composer-private.c
 composer/e-msg-composer.c
-composer/evolution-composer.c
+composer/gconf-bridge.c
 composer/mail-composer.error.xml
 data/evolution.desktop.in.in
 data/evolution.keys.in.in
@@ -304,6 +306,7 @@
 plugins/exchange-operations/exchange-passwd-expiry.glade
 plugins/exchange-operations/exchange-permissions-dialog.c
 plugins/exchange-operations/exchange-permissions-dialog.glade
+plugins/exchange-operations/exchange-send-options.c
 plugins/exchange-operations/exchange-send-options.glade
 plugins/exchange-operations/exchange-user-dialog.c
 plugins/exchange-operations/org-gnome-exchange-ab-subscription.xml
@@ -380,9 +383,6 @@
 plugins/plugin-manager/plugin-manager.c
 plugins/prefer-plain/org-gnome-prefer-plain.eplug.xml
 plugins/prefer-plain/prefer-plain.c
-plugins/print-message/org-gnome-print-message.eplug.xml
-plugins/print-message/org-gnome-print-message.xml
-plugins/print-message/print-message.c
 plugins/profiler/org-gnome-evolution-profiler.eplug.xml
 plugins/publish-calendar/org-gnome-publish-calendar.eplug.xml
 plugins/publish-calendar/org-gnome-publish-calendar.xml
@@ -437,7 +437,6 @@
 tools/killev.c
 ui/evolution-addressbook.xml
 ui/evolution-calendar.xml
-ui/evolution-composer-entries.xml
 ui/evolution-editor.xml
 ui/evolution-event-editor.xml
 ui/evolution-mail-global.xml
@@ -446,7 +445,6 @@
 ui/evolution-mail-messagedisplay.xml
 ui/evolution-memo-editor.xml
 ui/evolution-memos.xml
-ui/evolution-message-composer.xml
 ui/evolution-signature-editor.xml
 ui/evolution-subscribe.xml
 ui/evolution-task-editor.xml

Modified: trunk/tools/Makefile.am
==============================================================================
--- trunk/tools/Makefile.am	(original)
+++ trunk/tools/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -20,20 +20,6 @@
 
 EXTRA_DIST = verify-evolution-install.sh
 
-CORBA_SOURCE =                          \
-        Evolution-Composer.h            \
-        Evolution-Composer-common.c     \
-        Evolution-Composer-skels.c      \
-        Evolution-Composer-stubs.c
-
-BUILT_SOURCES = $(CORBA_SOURCE)
-
-idls =                                                          \
-        $(top_srcdir)/composer/Evolution-Composer.idl
-
-$(CORBA_SOURCE): $(idls)
-	$(ORBIT_IDL) -I $(srcdir) $(IDL_INCLUDES) $(idls)
-
 killev_SOURCES =						\
 	killev.c
 

Modified: trunk/ui/Makefile.am
==============================================================================
--- trunk/ui/Makefile.am	(original)
+++ trunk/ui/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -2,13 +2,11 @@
 	evolution.xml				\
 	evolution-addressbook.xml		\
 	evolution-calendar.xml			\
-	evolution-composer-entries.xml		\
 	evolution-mail-message.xml		\
 	evolution-mail-list.xml			\
 	evolution-mail-global.xml		\
 	evolution-mail-messagedisplay.xml	\
 	evolution-memos.xml			\
-	evolution-message-composer.xml		\
 	evolution-signature-editor.xml		\
 	evolution-subscribe.xml			\
 	evolution-event-editor.xml		\

Modified: trunk/widgets/misc/Makefile.am
==============================================================================
--- trunk/widgets/misc/Makefile.am	(original)
+++ trunk/widgets/misc/Makefile.am	Wed Apr  2 19:37:22 2008
@@ -138,6 +138,7 @@
 	$(top_builddir)/a11y/libevolution-a11y.la			\
 	$(EVOLUTION_MAIL_LIBS)						\
 	$(GNOME_PLATFORM_LIBS)						\
+	$(EVOLUTON_MAIL_LIBS)						\
 	$(ICONV_LIBS)
 
 libefilterbar_la_SOURCES =	\

Modified: trunk/widgets/misc/e-account-combo-box.c
==============================================================================
--- trunk/widgets/misc/e-account-combo-box.c	(original)
+++ trunk/widgets/misc/e-account-combo-box.c	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-account-combo-box.h"
 
 #include <string.h>
@@ -12,12 +31,19 @@
 	COLUMN_ACCOUNT
 };
 
+enum {
+	REFRESHED,
+	LAST_SIGNAL
+};
+
 struct _EAccountComboBoxPrivate {
 	EAccountList *account_list;
+	GHashTable *index;
 };
 
 static gpointer parent_class;
 static CamelSession *camel_session;
+static guint signal_ids[LAST_SIGNAL];
 
 static gboolean
 account_combo_box_has_dupes (GList *list,
@@ -86,15 +112,9 @@
 
 	store = gtk_list_store_new (2, G_TYPE_STRING, E_TYPE_ACCOUNT);
 	model = GTK_TREE_MODEL (store);
+	index = combo_box->priv->index;
 
-	/* Embed a reverse-lookup index into the list store. */
-	index = g_hash_table_new_full (
-		g_direct_hash, g_direct_equal,
-		(GDestroyNotify) g_object_unref,
-		(GDestroyNotify) gtk_tree_row_reference_free);
-	g_object_set_data_full (
-		G_OBJECT (combo_box), "index", index,
-		(GDestroyNotify) g_hash_table_destroy);
+	g_hash_table_remove_all (index);
 
 	if (account_list == NULL)
 		goto skip;
@@ -161,6 +181,8 @@
 	e_account_combo_box_set_active (combo_box, account);
 	if (account != NULL)
 		g_object_unref (account);
+
+	g_signal_emit (combo_box, signal_ids[REFRESHED], 0);
 }
 
 static GObject *
@@ -200,11 +222,26 @@
 		priv->account_list = NULL;
 	}
 
+	g_hash_table_remove_all (priv->index);
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
+account_combo_box_finalize (GObject *object)
+{
+	EAccountComboBoxPrivate *priv;
+
+	priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (object);
+
+	g_hash_table_destroy (priv->index);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
 account_combo_box_class_init (EAccountComboBoxClass *class)
 {
 	GObjectClass *object_class;
@@ -215,12 +252,30 @@
 	object_class = G_OBJECT_CLASS (class);
 	object_class->constructor = account_combo_box_constructor;
 	object_class->dispose = account_combo_box_dispose;
+	object_class->finalize = account_combo_box_finalize;
+
+	signal_ids[REFRESHED] = g_signal_new (
+		"refreshed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		0, NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
 }
 
 static void
 account_combo_box_init (EAccountComboBox *combo_box)
 {
+	GHashTable *index;
+
+	/* Reverse-lookup index */
+	index = g_hash_table_new_full (
+		g_direct_hash, g_direct_equal,
+		(GDestroyNotify) g_object_unref,
+		(GDestroyNotify) gtk_tree_row_reference_free);
+
 	combo_box->priv = E_ACCOUNT_COMBO_BOX_GET_PRIVATE (combo_box);
+	combo_box->priv->index = index;
 }
 
 GType
@@ -273,6 +328,14 @@
 	camel_session = session;
 }
 
+EAccountList *
+e_account_combo_box_get_account_list (EAccountComboBox *combo_box)
+{
+	g_return_val_if_fail (E_IS_ACCOUNT_COMBO_BOX (combo_box), NULL);
+
+	return combo_box->priv->account_list;
+}
+
 void
 e_account_combo_box_set_account_list (EAccountComboBox *combo_box,
                                       EAccountList *account_list)
@@ -337,7 +400,6 @@
 e_account_combo_box_set_active (EAccountComboBox *combo_box,
                                 EAccount *account)
 {
-	GHashTable *index;
 	EAccountList *account_list;
 	GtkTreeRowReference *reference;
 	GtkTreeModel *model;
@@ -353,10 +415,6 @@
 	account_list = combo_box->priv->account_list;
 	g_return_val_if_fail (account_list != NULL, FALSE);
 
-	/* Failure here indicates a programming error. */
-	index = g_object_get_data (G_OBJECT (combo_box), "index");
-	g_assert (index != NULL);
-
 	/* NULL means select the default account. */
 	/* XXX EAccountList misuses const. */
 	if (account == NULL)
@@ -364,7 +422,7 @@
 			e_account_list_get_default (account_list);
 
 	/* Lookup the tree row reference for the account. */
-	reference = g_hash_table_lookup (index, account);
+	reference = g_hash_table_lookup (combo_box->priv->index, account);
 	if (reference == NULL)
 		return FALSE;
 

Modified: trunk/widgets/misc/e-account-combo-box.h
==============================================================================
--- trunk/widgets/misc/e-account-combo-box.h	(original)
+++ trunk/widgets/misc/e-account-combo-box.h	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_ACCOUNT_COMBO_BOX_H
 #define E_ACCOUNT_COMBO_BOX_H
 
@@ -43,6 +62,8 @@
 GType		e_account_combo_box_get_type	(void);
 GtkWidget *	e_account_combo_box_new		(void);
 void		e_account_combo_box_set_session	(CamelSession *session);
+EAccountList *	e_account_combo_box_get_account_list
+						(EAccountComboBox *combo_box);
 void		e_account_combo_box_set_account_list
 						(EAccountComboBox *combo_box,
 						 EAccountList *account_list);

Modified: trunk/widgets/misc/e-charset-picker.c
==============================================================================
--- trunk/widgets/misc/e-charset-picker.c	(original)
+++ trunk/widgets/misc/e-charset-picker.c	Wed Apr  2 19:37:22 2008
@@ -28,15 +28,6 @@
 #include <string.h>
 #include <iconv.h>
 
-#include <gtk/gtkhbox.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkstock.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtkoptionmenu.h>
-#include <gtk/gtksignal.h>
-
 #include <glib/gi18n.h>
 
 #include <bonobo/bonobo-ui-node.h>
@@ -446,6 +437,127 @@
 }
 
 /**
+ * e_charset_add_radio_actions:
+ * @action_group: a #GtkActionGroup
+ * @default_charset: the default character set, or %NULL to use the
+ *                   locale character set
+ * @callback: a callback function for actions in the group, or %NULL
+ * @user_data: user data to be passed to @callback, or %NULL
+ * 
+ * Adds a set of #GtkRadioActions for available character sets to
+ * @action_group.  The @default_charset (or locale character set if
+ * @default_charset is %NULL) will be added first, and selected by
+ * default (except that iso-8859-1 will always be used instead of
+ * US-ASCII).  Any other character sets of the same language class as
+ * the default will be added next, followed by the remaining character
+ * sets.
+ **/
+void
+e_charset_add_radio_actions (GtkActionGroup *action_group,
+                             const gchar *default_charset,
+                             GCallback callback,
+                             gpointer user_data)
+{
+	GtkRadioAction *action = NULL;
+	GSList *group = NULL;
+	const gchar *locale_charset;
+	gint def, ii;
+
+	g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
+
+	/* XXX I could try to factor out code common to this
+	 *     function and e_charset_picker_bonobo_ui_populate()
+	 *     instead of duplicating it, but I expect the latter
+	 *     function to be obsolete in the foreseeable future. */
+
+	g_get_charset (&locale_charset);
+	if (!g_ascii_strcasecmp (locale_charset, "US-ASCII"))
+		locale_charset = "iso-8859-1";
+
+	if (default_charset == NULL)
+		default_charset = locale_charset;
+	for (def = 0; def < G_N_ELEMENTS (charsets); def++)
+		if (!g_ascii_strcasecmp (charsets[def].name, default_charset))
+			break;
+
+	for (ii = 0; ii < G_N_ELEMENTS (charsets); ii++) {
+		gchar *escaped_name;
+		gchar *charset_label;
+		gchar **str_array;
+
+		/* Escape underlines in the character set name so
+		 * they're not treated as GtkLabel mnemonics. */
+		str_array = g_strsplit (charsets[ii].name, "_", -1);
+		escaped_name = g_strjoinv ("__", str_array);
+		g_strfreev (str_array);
+
+		if (charsets[ii].subclass != NULL)
+			charset_label = g_strdup_printf (
+				"%s, %s (%s)",
+				gettext (classnames[charsets[ii].class]),
+				gettext (charsets[ii].subclass),
+				escaped_name);
+		else if (charsets[ii].class != E_CHARSET_UNKNOWN)
+			charset_label = g_strdup_printf (
+				"%s (%s)",
+				gettext (classnames[charsets[ii].class]),
+				escaped_name);
+		else
+			charset_label = g_strdup (escaped_name);
+
+		action = gtk_radio_action_new (
+			charsets[ii].name, charset_label, NULL, NULL, ii);
+
+		gtk_radio_action_set_group (action, group);
+		group = gtk_radio_action_get_group (action);
+
+		if (callback != NULL)
+			g_signal_connect (
+				action, "changed", callback, user_data);
+
+		gtk_action_group_add_action (
+			action_group, GTK_ACTION (action));
+
+		g_object_unref (action);
+
+		g_free (escaped_name);
+		g_free (charset_label);
+	}
+
+	if (def == G_N_ELEMENTS (charsets)) {
+		gchar *charset_label;
+		gchar **str_array;
+
+		/* Escape underlines in the character set name so
+		 * they're not treated as GtkLabel mnemonics. */
+		str_array = g_strsplit (default_charset, "_", -1);
+		charset_label = g_strjoinv ("__", str_array);
+		g_strfreev (str_array);
+
+		action = gtk_radio_action_new (
+			default_charset, charset_label, NULL, NULL, def);
+
+		gtk_radio_action_set_group (action, group);
+		group = gtk_radio_action_get_group (action);
+
+		if (callback != NULL)
+			g_signal_connect (
+				action, "changed", callback, user_data);
+
+		gtk_action_group_add_action (
+			action_group, GTK_ACTION (action));
+
+		g_object_unref (action);
+
+		g_free (charset_label);
+	}
+
+	/* Any of the actions in the action group will do. */
+	if (action != NULL)
+		gtk_radio_action_set_current_value (action, def);
+}
+
+/**
  * e_charset_picker_bonobo_ui_populate:
  * @uic: Bonobo UI Component
  * @path: menu path

Modified: trunk/widgets/misc/e-charset-picker.h
==============================================================================
--- trunk/widgets/misc/e-charset-picker.h	(original)
+++ trunk/widgets/misc/e-charset-picker.h	Wed Apr  2 19:37:22 2008
@@ -18,31 +18,33 @@
  *
  */
 
-#ifndef _E_CHARSETPICKER_H_
-#define _E_CHARSETPICKER_H_
+#ifndef E_CHARSETPICKER_H
+#define E_CHARSETPICKER_H
 
-#include <gtk/gtkwindow.h>
+#include <gtk/gtk.h>
 #include <bonobo/bonobo-ui-component.h>
 
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-GtkWidget *e_charset_picker_new (const char *default_charset);
-char      *e_charset_picker_get_charset (GtkWidget *picker);
-
-char      *e_charset_picker_dialog (const char *title, const char *prompt,
-				    const char *default_charset,
-				    GtkWindow *parent);
-
-/* bonobo equivalents */
-void       e_charset_picker_bonobo_ui_populate (BonoboUIComponent *uic, const char *path,
-						const char *default_charset,
-						BonoboUIListenerFn cb, gpointer user_data);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_BEGIN_DECLS
 
-#endif /* _E_CHARSETPICKER_H_ */
+GtkWidget *	e_charset_picker_new		(const char *default_charset);
+char *		e_charset_picker_get_charset	(GtkWidget *picker);
+char *		e_charset_picker_dialog		(const char *title,
+						 const char *prompt,
+						 const char *default_charset,
+						 GtkWindow *parent);
+
+void		e_charset_add_radio_actions	(GtkActionGroup *action_group,
+						 const gchar *default_charset,
+						 GCallback callback,
+						 gpointer user_data);
+
+void		e_charset_picker_bonobo_ui_populate
+						(BonoboUIComponent *uic,
+						 const char *path,
+						 const char *default_charset,
+						 BonoboUIListenerFn cb,
+						 gpointer user_data);
+
+G_END_DECLS
+
+#endif /* E_CHARSETPICKER_H */

Modified: trunk/widgets/misc/e-signature-combo-box.c
==============================================================================
--- trunk/widgets/misc/e-signature-combo-box.c	(original)
+++ trunk/widgets/misc/e-signature-combo-box.c	Wed Apr  2 19:37:22 2008
@@ -1,3 +1,22 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #include "e-signature-combo-box.h"
 
 #include <glib/gi18n.h>
@@ -233,6 +252,14 @@
 	return g_object_new (E_TYPE_SIGNATURE_COMBO_BOX, NULL);
 }
 
+ESignatureList *
+e_signature_combo_box_get_signature_list (ESignatureComboBox *combo_box)
+{
+	g_return_val_if_fail (E_IS_SIGNATURE_COMBO_BOX (combo_box), NULL);
+
+	return combo_box->priv->signature_list;
+}
+
 void
 e_signature_combo_box_set_signature_list (ESignatureComboBox *combo_box,
                                           ESignatureList *signature_list)

Modified: trunk/widgets/misc/e-signature-combo-box.h
==============================================================================
--- trunk/widgets/misc/e-signature-combo-box.h	(original)
+++ trunk/widgets/misc/e-signature-combo-box.h	Wed Apr  2 19:37:22 2008
@@ -1,9 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
 #ifndef E_SIGNATURE_COMBO_BOX_H
 #define E_SIGNATURE_COMBO_BOX_H
 
 #include <gtk/gtk.h>
-#include "e-util/e-signature.h"
-#include "e-util/e-signature-list.h"
+#include <e-util/e-signature.h>
+#include <e-util/e-signature-list.h>
 
 /* Standard GObject macros */
 #define E_TYPE_SIGNATURE_COMBO_BOX \
@@ -41,6 +60,8 @@
 
 GType		e_signature_combo_box_get_type	(void);
 GtkWidget *	e_signature_combo_box_new	(void);
+ESignatureList *e_signature_combo_box_get_signature_list
+					(ESignatureComboBox *combo_box);
 void		e_signature_combo_box_set_signature_list
 					(ESignatureComboBox *combo_box,
 					 ESignatureList *signature_list);



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