Index: ui/evolution-message-composer.xml
===================================================================
RCS file: /cvs/gnome/evolution/ui/evolution-message-composer.xml,v
retrieving revision 1.35
diff -u -d -r1.35 evolution-message-composer.xml
--- ui/evolution-message-composer.xml	8 Mar 2002 23:02:22 -0000	1.35
+++ ui/evolution-message-composer.xml	19 Jun 2002 04:34:26 -0000
@@ -23,6 +23,9 @@
                 accel="*Ctrl**Alt*f"
 		_tip="Insert a file as text into the message"/>
 		
+		<cmd name="InsertHeader" _label="Insert message header..."
+		_tip="Add a new header to the message"/>
+
 		<cmd name="FileSend" _label="Send" _tip="Send this message now"
 		accel="*Ctrl*Return"
                 pixtype="pixbuf"/>
@@ -130,6 +133,8 @@
 	                _label="_Attachment..." pixtype="pixbuf"/>
 			<menuitem name="FileInsertFile" verb="" 
                         _label="Inline Text _File..."/>
+			<menuitem name="InsertHeader" verb="" 
+                        _label="Message _Header..."/>			
                 	<placeholder name="Component"/>
                 </submenu>
 		
Index: composer/e-msg-composer.h
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.h,v
retrieving revision 1.70
diff -u -d -r1.70 e-msg-composer.h
--- composer/e-msg-composer.h	5 Jun 2002 21:16:41 -0000	1.70
+++ composer/e-msg-composer.h	19 Jun 2002 04:34:27 -0000
@@ -57,7 +57,6 @@
 	BonoboUIComponent *uic;
 	
 	GtkWidget *hdrs;
-	GPtrArray *extra_hdr_names, *extra_hdr_values;
 	
 	GtkWidget *editor;
 	
Index: composer/e-msg-composer.c
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer.c,v
retrieving revision 1.295
diff -u -d -r1.295 e-msg-composer.c
--- composer/e-msg-composer.c	10 Jun 2002 21:26:18 -0000	1.295
+++ composer/e-msg-composer.c	19 Jun 2002 04:34:28 -0000
@@ -350,11 +350,6 @@
 	
 	new = camel_mime_message_new ();
 	e_msg_composer_hdrs_to_message (hdrs, new);
-	for (i = 0; i < composer->extra_hdr_names->len; i++) {
-		camel_medium_add_header (CAMEL_MEDIUM (new),
-					 composer->extra_hdr_names->pdata[i],
-					 composer->extra_hdr_values->pdata[i]);
-	}
 	
 	if (composer->mime_body) {
 		plain_encoding = CAMEL_MIME_PART_ENCODING_7BIT;
@@ -1540,6 +1535,16 @@
 }
 
 static void
+menu_insert_header_cb (BonoboUIComponent *uic,
+		       void *data,
+		       const char *path)
+{
+	EMsgComposer *composer = E_MSG_COMPOSER (data);
+	
+	e_msg_composer_hdrs_add_dynamic_header (E_MSG_COMPOSER_HDRS (composer->hdrs));
+}
+
+static void
 menu_file_insert_file_cb (BonoboUIComponent *uic,
 			  void *data,
 			  const char *path)
@@ -1726,6 +1731,8 @@
 	BONOBO_UI_VERB ("FileInsertFile", menu_file_insert_file_cb),
 	BONOBO_UI_VERB ("FileAttach",     menu_file_add_attachment_cb),
 	
+	BONOBO_UI_VERB ("InsertHeader", menu_insert_header_cb),
+
 	BONOBO_UI_VERB ("FileSend",       menu_file_send_cb),
 	BONOBO_UI_VERB ("FileSendLater",  menu_file_send_later_cb),
 	
@@ -2299,17 +2306,6 @@
 	if (composer->hdrs != NULL)
 		gtk_widget_destroy (composer->hdrs);
 	
-	if (composer->extra_hdr_names) {
-		int i;
-		
-		for (i = 0; i < composer->extra_hdr_names->len; i++) {
-			g_free (composer->extra_hdr_names->pdata[i]);
-			g_free (composer->extra_hdr_values->pdata[i]);
-		}
-		g_ptr_array_free (composer->extra_hdr_names, TRUE);
-		g_ptr_array_free (composer->extra_hdr_values, TRUE);
-	}
-	
 	e_msg_composer_clear_inlined_table (composer);
 	g_hash_table_destroy (composer->inline_images);
 	g_hash_table_destroy (composer->inline_images_by_url);
@@ -2525,8 +2521,6 @@
 	composer->uic                      = NULL;
 	
 	composer->hdrs                     = NULL;
-	composer->extra_hdr_names          = g_ptr_array_new ();
-	composer->extra_hdr_values         = g_ptr_array_new ();
 	
 	composer->editor                   = NULL;
 	
@@ -2621,33 +2615,6 @@
 	CORBA_exception_free (&ev);
 }
 
-static gint
-e_msg_composer_get_visible_flags (EMsgComposer *composer)
-{
-	int flags = 0;
-	
-	if (composer->view_from)
-		flags |= E_MSG_COMPOSER_VISIBLE_FROM;
-	if (composer->view_replyto)
-		flags |= E_MSG_COMPOSER_VISIBLE_REPLYTO;
-	if (composer->view_cc)
-		flags |= E_MSG_COMPOSER_VISIBLE_CC;
-	if (composer->view_bcc)
-		flags |= E_MSG_COMPOSER_VISIBLE_BCC;
-	if (composer->view_subject)
-		flags |= E_MSG_COMPOSER_VISIBLE_SUBJECT;
-	
-	/*
-	 * 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;
-}
-
-
 static void
 map_default_cb (EMsgComposer *composer, gpointer user_data)
 {
@@ -2707,7 +2674,6 @@
 	EMsgComposer *composer;
 	GtkWidget *vbox;
 	BonoboObject *editor_server;
-	gint vis;
 	
 	g_return_val_if_fail (gtk_main_level () > 0, NULL);
 
@@ -2737,8 +2703,7 @@
 	
 	vbox = gtk_vbox_new (FALSE, 0);
 	
-	vis = e_msg_composer_get_visible_flags (composer);
-	composer->hdrs = e_msg_composer_hdrs_new (vis);
+	composer->hdrs = e_msg_composer_hdrs_new ();
 	if (!composer->hdrs) {
 		e_activation_failure_dialog (GTK_WINDOW (composer),
 					     _("Could not create composer window:\n"
@@ -2748,6 +2713,23 @@
 		gtk_object_destroy (GTK_OBJECT (composer));
 		return NULL;
 	}
+
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "From", composer->view_from);
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Reply-To", composer->view_replyto);
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Cc", composer->view_cc);
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Bcc", composer->view_bcc);
+	/*
+	 * 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).
+	 */
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Subject", composer->view_subject);
 	
 	gtk_box_pack_start (GTK_BOX (vbox), composer->hdrs, FALSE, FALSE, 0);
 	gtk_signal_connect (GTK_OBJECT (composer->hdrs), "subject_changed",
@@ -2843,8 +2825,9 @@
 static void
 set_editor_signature (EMsgComposer *composer)
 {
+	EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (composer->hdrs);
 	/* printf ("set_editor_signature\n"); */
-	if (E_MSG_COMPOSER_HDRS (composer->hdrs)->account->id) {
+	if (hdrs->account && hdrs->account->id) {
 		MailConfigIdentity *id;
 		
 		id = E_MSG_COMPOSER_HDRS (composer->hdrs)->account->id;
@@ -3122,6 +3105,7 @@
 	CamelContentType *content_type;
 	struct _header_raw *headers;
 	EMsgComposer *new;
+	EMsgComposerHdrs *hdrs;
 	XEvolution *xev;
 	guint len, i;
 	
@@ -3130,6 +3114,8 @@
 	new = create_composer ();
 	if (!new)
 		return NULL;
+
+	hdrs = E_MSG_COMPOSER_HDRS (new->hdrs);
 	
 	subject = camel_mime_message_get_subject (message);
 	
@@ -3215,11 +3201,9 @@
 	/* set extra headers */
 	headers = CAMEL_MIME_PART (message)->headers;
 	while (headers) {
-		if (!is_special_header (headers->name)) {
-			g_ptr_array_add (new->extra_hdr_names, g_strdup (headers->name));
-			g_ptr_array_add (new->extra_hdr_values, g_strdup (headers->value));
-		}
-		
+		if (!is_special_header (headers->name))
+			e_msg_composer_hdrs_add_raw_header(hdrs, headers->name,
+							   headers->value, FALSE);
 		headers = headers->next;
 	}
 	
@@ -3553,9 +3537,9 @@
  * @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.
+ * Adds a header with @name and @value to the message. This header may
+ * not be displayed by default by the composer, but will be included
+ * in the message it outputs.
  **/
 void
 e_msg_composer_add_header (EMsgComposer *composer, const char *name,
@@ -3565,8 +3549,8 @@
 	g_return_if_fail (name != NULL);
 	g_return_if_fail (value != NULL);
 	
-	g_ptr_array_add (composer->extra_hdr_names, g_strdup (name));
-	g_ptr_array_add (composer->extra_hdr_values, g_strdup (value));
+	e_msg_composer_hdrs_add_raw_header(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					   name, value, FALSE);
 }
 
 
@@ -4080,10 +4064,8 @@
 		composer->uic, "/commands/ViewBCC",
 		"state", composer->view_bcc ? "1" : "0", NULL);
 	set_config (composer, "ViewBCC", composer->view_bcc);
-	e_msg_composer_set_hdrs_visible
-		(E_MSG_COMPOSER_HDRS (composer->hdrs),
-		 e_msg_composer_get_visible_flags (composer));
-		 
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Bcc", composer->view_bcc);
 }
 
 /**
@@ -4125,9 +4107,8 @@
 		composer->uic, "/commands/ViewCC",
 		"state", composer->view_cc ? "1" : "0", NULL);
 	set_config (composer, "ViewCC", composer->view_cc);
-	e_msg_composer_set_hdrs_visible
-		(E_MSG_COMPOSER_HDRS (composer->hdrs),
-		 e_msg_composer_get_visible_flags (composer));
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Cc", composer->view_cc);
 }
 
 EDestination **
@@ -4209,9 +4190,8 @@
 		composer->uic, "/commands/ViewFrom",
 		"state", composer->view_from ? "1" : "0", NULL);
 	set_config (composer, "ViewFrom", composer->view_from);
-	e_msg_composer_set_hdrs_visible
-		(E_MSG_COMPOSER_HDRS (composer->hdrs),
-		 e_msg_composer_get_visible_flags (composer));
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "From", composer->view_from);
 }
 
 /**
@@ -4253,9 +4233,8 @@
 		composer->uic, "/commands/ViewReplyTo",
 		"state", composer->view_replyto ? "1" : "0", NULL);
 	set_config (composer, "ViewReplyTo", composer->view_replyto);
-	e_msg_composer_set_hdrs_visible
-		(E_MSG_COMPOSER_HDRS (composer->hdrs),
-		 e_msg_composer_get_visible_flags (composer));
+	e_msg_composer_hdrs_set_header_visible(E_MSG_COMPOSER_HDRS(composer->hdrs),
+					       "Reply-To", composer->view_replyto);
 }
 
 /**
Index: composer/e-msg-composer-hdrs.h
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer-hdrs.h,v
retrieving revision 1.23
diff -u -d -r1.23 e-msg-composer-hdrs.h
--- composer/e-msg-composer-hdrs.h	10 Jun 2002 21:26:18 -0000	1.23
+++ composer/e-msg-composer-hdrs.h	19 Jun 2002 04:34:28 -0000
@@ -69,17 +69,9 @@
 	void (* from_changed) (EMsgComposerHdrs *hdrs);
 };
 
-typedef enum {
-	E_MSG_COMPOSER_VISIBLE_FROM    = 1,
-	E_MSG_COMPOSER_VISIBLE_REPLYTO = 2,
-	E_MSG_COMPOSER_VISIBLE_CC      = 4,
-	E_MSG_COMPOSER_VISIBLE_BCC     = 8,
-	E_MSG_COMPOSER_VISIBLE_SUBJECT = 16
-} EMsgComposerHeaderVisibleFlags;
-
 
 GtkType     e_msg_composer_hdrs_get_type           (void);
-GtkWidget  *e_msg_composer_hdrs_new                (gint visible_flags);
+GtkWidget  *e_msg_composer_hdrs_new                ();
 
 void        e_msg_composer_hdrs_to_message         (EMsgComposerHdrs *hdrs,
 						    CamelMimeMessage *msg);
@@ -109,16 +101,33 @@
 EDestination **e_msg_composer_hdrs_get_recipients  (EMsgComposerHdrs *hdrs);
 char          *e_msg_composer_hdrs_get_subject     (EMsgComposerHdrs *hdrs);
 
+GPtrArray *e_msg_composer_hdrs_get_extra_header_names(EMsgComposerHdrs *hdrs);
+
 GtkWidget  *e_msg_composer_hdrs_get_reply_to_entry (EMsgComposerHdrs *hdrs);
 GtkWidget  *e_msg_composer_hdrs_get_to_entry       (EMsgComposerHdrs *hdrs);
 GtkWidget  *e_msg_composer_hdrs_get_cc_entry       (EMsgComposerHdrs *hdrs);
 GtkWidget  *e_msg_composer_hdrs_get_bcc_entry      (EMsgComposerHdrs *hdrs);
 GtkWidget  *e_msg_composer_hdrs_get_subject_entry  (EMsgComposerHdrs *hdrs);
 GtkWidget  *e_msg_composer_hdrs_get_from_hbox      (EMsgComposerHdrs *hdrs);
-GtkWidget  *e_msg_composer_hdrs_get_from_omenu     (EMsgComposerHdrs *hdrs);
+gboolean    e_msg_composer_hdrs_set_header_visible (EMsgComposerHdrs *hdrs,
+						    const gchar *name,
+						    gboolean visible);
 
-void        e_msg_composer_set_hdrs_visible        (EMsgComposerHdrs *hdrs,
-						    gint flags);
+char *e_msg_composer_hdrs_get_header_value (EMsgComposerHdrs *hdrs,
+					    const char *name);
+
+char *
+e_msg_composer_hdrs_add_raw_header (EMsgComposerHdrs *hdrs,
+				    const char *name,
+				    const char *value,
+				    gboolean visible);
+
+gboolean e_msg_composer_hdrs_remove_header (EMsgComposerHdrs *hdrs,
+					    const char *name);
+
+gboolean e_msg_composer_hdrs_add_dynamic_header (EMsgComposerHdrs *hdrs);
+
+GtkWidget  *e_msg_composer_hdrs_get_from_omenu     (EMsgComposerHdrs *hdrs);
 
 #ifdef _cplusplus
 }
Index: composer/e-msg-composer-hdrs.c
===================================================================
RCS file: /cvs/gnome/evolution/composer/e-msg-composer-hdrs.c,v
retrieving revision 1.86
diff -u -d -r1.86 e-msg-composer-hdrs.c
--- composer/e-msg-composer-hdrs.c	10 Jun 2002 21:26:18 -0000	1.86
+++ composer/e-msg-composer-hdrs.c	19 Jun 2002 04:34:28 -0000
@@ -2,6 +2,7 @@
 /* msg-composer-hdrs.c
  *
  * Copyright (C) 1999 Ximian, Inc.
+ * Copyright (C) 2002 Colin Walters <walters@gnu.org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -60,9 +61,15 @@
 #define LINE_SUBJECT 5
 
 typedef struct {
+	const char *name;
 	GtkWidget *label;
 	GtkWidget *entry;
-} EMsgComposerHdrPair;
+} EMsgComposerHeader;
+
+typedef struct {
+	GtkWidget *label;
+	GtkWidget *entry;
+} EMsgComposerDynamicHeader;
 
 struct _EMsgComposerHdrsPrivate {
 	GNOME_Evolution_Addressbook_SelectNames corba_select_names;
@@ -72,8 +79,12 @@
 	
 	GSList *from_options;
 	
-	/* Standard headers.  */
-	EMsgComposerHdrPair from, reply_to, to, cc, bcc, subject;
+	/* The headers. */
+	GHashTable  *headers;
+
+	/* Headers which were added by the user; both their name and
+	   value are editable. */
+	GList *dynamic_headers;
 };
 
 
@@ -168,14 +179,18 @@
 from_changed (GtkWidget *item, gpointer data)
 {
 	EMsgComposerHdrs *hdrs = E_MSG_COMPOSER_HDRS (data);
+	EMsgComposerHeader *header = g_hash_table_lookup(hdrs->priv->headers,
+							 "Reply-To");
 	const char *reply_to;
+
+	g_return_if_fail(header != NULL);
 	
 	hdrs->account = gtk_object_get_data (GTK_OBJECT (item), "account");
 	
 	/* we do this rather than calling e_msg_composer_hdrs_set_reply_to()
 	   because we don't want to change the visibility of the header */
 	reply_to = hdrs->account->id->reply_to;
-	e_entry_set_text (E_ENTRY (hdrs->priv->reply_to.entry), reply_to ? reply_to : "");
+	e_entry_set_text (E_ENTRY (header->entry), reply_to ? reply_to : "");
 	
 	gtk_signal_emit (GTK_OBJECT (hdrs), signals [FROM_CHANGED]);
 }
@@ -318,29 +333,31 @@
 	return control_widget;
 }
 
-static EMsgComposerHdrPair 
-header_new_recipient (EMsgComposerHdrs *hdrs, const gchar *name, const gchar *tip)
+static EMsgComposerHeader *
+header_new_recipient (EMsgComposerHdrs *hdrs, const gchar *name,
+		      const gchar *trans_name, const gchar *tip)
 {
 	EMsgComposerHdrsPrivate *priv;
-	EMsgComposerHdrPair ret;
+	EMsgComposerHeader *ret = g_new0(EMsgComposerHeader, 1);
 	
 	priv = hdrs->priv;
-	
-	ret.label = gtk_button_new_with_label (name);
-	GTK_OBJECT_UNSET_FLAGS (ret.label, GTK_CAN_FOCUS);
+
+	ret->name = name;
+	ret->label = gtk_button_new_with_label (trans_name);
+	GTK_OBJECT_UNSET_FLAGS (ret->label, GTK_CAN_FOCUS);
 	gtk_signal_connect_full (
-		GTK_OBJECT (ret.label), "clicked",
+		GTK_OBJECT (ret->label), "clicked",
 		GTK_SIGNAL_FUNC (address_button_clicked_cb), NULL,
-		e_msg_composer_hdrs_and_string_create(hdrs, name),
+		e_msg_composer_hdrs_and_string_create(hdrs, trans_name),
 		(GtkDestroyNotify) e_msg_composer_hdrs_and_string_free,
 		FALSE, FALSE);
 	
 	gtk_tooltips_set_tip (
-		hdrs->priv->tooltips, ret.label,
+		hdrs->priv->tooltips, ret->label,
 		_("Click here for the address book"),
 		NULL);
 	
-	ret.entry = create_addressbook_entry (hdrs, name);
+	ret->entry = create_addressbook_entry (hdrs, trans_name);
 	
 	return ret;
 }
@@ -359,153 +376,142 @@
 	gtk_signal_emit (GTK_OBJECT (hdrs), signals[HDRS_CHANGED]);
 }
 
+/* static GtkDirectionType */
+/* focus_cb (GtkContainer *contain, GtkDirectionType dir, gpointer closure) */
+/* { */
+/* 	g_message ("FOCUS: %d", dir); */
+/* 	return dir; */
+/* } */
+
 static void
-create_headers (EMsgComposerHdrs *hdrs)
+attach_header (EMsgComposerHdrs *hdrs, EMsgComposerHeader *header, int line)
 {
-	EMsgComposerHdrsPrivate *priv = hdrs->priv;
+	int pad;
+	
+	if (GTK_IS_LABEL (header->label))
+		pad = GNOME_PAD;
+	else
+		pad = 2;
 	
+	gtk_table_attach (GTK_TABLE (hdrs),
+			  header->label, 0, 1,
+			  line, line + 1,
+			  GTK_FILL, GTK_FILL, pad, pad);
+	
+	gtk_table_attach (GTK_TABLE (hdrs),
+			  header->entry, 1, 2,
+			  line, line + 1,
+			  GTK_FILL | GTK_EXPAND, 0, 2, 2);
+}
+
+gboolean
+e_msg_composer_hdrs_set_header_visible (EMsgComposerHdrs *hdrs,
+					const gchar *name,
+					gboolean visible)
+{
+	EMsgComposerHeader *header;
+	g_return_val_if_fail (hdrs != NULL, FALSE);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), FALSE);
+	header = g_hash_table_lookup(hdrs->priv->headers, name);
+	g_return_val_if_fail (header != NULL, FALSE);
+
+	if (visible) {
+		gtk_widget_show(GTK_WIDGET (header->label));
+		gtk_widget_show(GTK_WIDGET (header->entry));
+	} else {
+		gtk_widget_hide(GTK_WIDGET (header->label));
+		gtk_widget_hide(GTK_WIDGET (header->entry));
+	}
+	
+	gtk_widget_queue_resize (GTK_WIDGET (hdrs));
+	return TRUE;
+}
+
+static void
+setup_normal_headers (EMsgComposerHdrs *hdrs)
+{
+	EMsgComposerHdrsPrivate *priv = hdrs->priv;
+	EMsgComposerHeader *header;
+
 	/*
 	 * From:
 	 */
-	priv->from.label = gtk_label_new (_("From:"));
-	priv->from.entry = create_from_optionmenu (hdrs);
+	header = g_new(EMsgComposerHeader, 1);
+	header->name = "From";
+	header->label = gtk_label_new (_("From:"));
+	header->entry = create_from_optionmenu (hdrs);
+	g_hash_table_insert (priv->headers, (gpointer) header->name, header);
+	attach_header (hdrs, header, LINE_FROM);
 	
 	/*
 	 * Reply-To:
 	 */
-	priv->reply_to.label = gtk_label_new (_("Reply-To:"));
-	priv->reply_to.entry = e_entry_new ();
-	gtk_object_set (GTK_OBJECT (priv->reply_to.entry),
+	header = g_new(EMsgComposerHeader, 1);
+	header->name = "Reply-To";
+	header->label = gtk_label_new (_("Reply-To:"));
+	header->entry = e_entry_new ();
+	gtk_object_set (GTK_OBJECT (header->entry),
 			"editable", TRUE,
 			"use_ellipsis", TRUE,
 			"allow_newlines", FALSE,
 			NULL);
+	g_hash_table_insert (priv->headers, (gpointer) header->name, header);
+	attach_header (hdrs, header, LINE_REPLYTO);
 	
 	/*
 	 * Subject:
 	 */
-	priv->subject.label = gtk_label_new (_("Subject:"));
-	priv->subject.entry = e_entry_new ();
-	gtk_object_set (GTK_OBJECT (priv->subject.entry),
+	header = g_new(EMsgComposerHeader, 1);
+	header->name = "Subject";
+	header->label = gtk_label_new (_("Subject:"));
+	header->entry = e_entry_new ();
+	gtk_object_set (GTK_OBJECT (header->entry),
 			"editable", TRUE,
 			"use_ellipsis", TRUE,
 			"allow_newlines", FALSE,
 			NULL);
-	gtk_signal_connect (GTK_OBJECT (priv->subject.entry), "changed",
+	gtk_signal_connect (GTK_OBJECT (header->entry), "changed",
 			    GTK_SIGNAL_FUNC (entry_changed), hdrs);
+	g_hash_table_insert (priv->headers, (gpointer) header->name, header);
+	attach_header (hdrs, header, LINE_SUBJECT);
 	
 	/*
 	 * To: CC: and Bcc:
 	 */
-	priv->to = header_new_recipient (
-		hdrs, _("To:"),
-		_("Enter the recipients of the message"));
-	
-	priv->cc = header_new_recipient (
-		hdrs, _("Cc:"),
-		_("Enter the addresses that will receive a carbon copy of the message"));
-	
-	priv->bcc = header_new_recipient (
-		hdrs, _("Bcc:"),
-		 _("Enter the addresses that will receive a carbon copy of "
-		   "the message without appearing in the recipient list of "
-		   "the message."));
-}
-
-static GtkDirectionType
-focus_cb (GtkContainer *contain, GtkDirectionType dir, gpointer closure)
-{
-	g_message ("FOCUS: %d", dir);
-	return dir;
-}
-
-static void
-attach_couple (EMsgComposerHdrs *hdrs, EMsgComposerHdrPair *pair, int line)
-{
-	int pad;
-	
-	if (GTK_IS_LABEL (pair->label))
-		pad = GNOME_PAD;
-	else
-		pad = 2;
-	
-	gtk_table_attach (GTK_TABLE (hdrs),
-			  pair->label, 0, 1,
-			  line, line + 1,
-			  GTK_FILL, GTK_FILL, pad, pad);
-	
-	gtk_table_attach (GTK_TABLE (hdrs),
-			  pair->entry, 1, 2,
-			  line, line + 1,
-			  GTK_FILL | GTK_EXPAND, 0, 2, 2);
-}
-
-static void
-attach_headers (EMsgComposerHdrs *hdrs)
-{
-	EMsgComposerHdrsPrivate *p = hdrs->priv;
-	
-	attach_couple (hdrs, &p->from, LINE_FROM);
-	attach_couple (hdrs, &p->reply_to, LINE_REPLYTO);
-	attach_couple (hdrs, &p->to, LINE_TO);
-	attach_couple (hdrs, &p->cc, LINE_CC);
-	attach_couple (hdrs, &p->bcc, LINE_BCC);
-	attach_couple (hdrs, &p->subject, LINE_SUBJECT);
-}
-
-static void
-set_pair_visibility (EMsgComposerHdrs *h, EMsgComposerHdrPair *pair, gboolean visible)
-{
-	if (visible){
-		gtk_widget_show (pair->label);
-		gtk_widget_show (pair->entry);
-	} else {
-		gtk_widget_hide (pair->label);
-		gtk_widget_hide (pair->entry);
-	}
-}
-
-static void
-headers_set_visibility (EMsgComposerHdrs *h, int visible_flags)
-{
-	EMsgComposerHdrsPrivate *p = h->priv;
+	header = header_new_recipient (hdrs, "To", _("To:"),
+				       _("Enter the recipients of the message"));
+	g_hash_table_insert (priv->headers, (gpointer) header->name, header);
+	attach_header (hdrs, header, LINE_TO);
 	
-	set_pair_visibility (h, &p->from, visible_flags & E_MSG_COMPOSER_VISIBLE_FROM);
-	set_pair_visibility (h, &p->reply_to, visible_flags & E_MSG_COMPOSER_VISIBLE_REPLYTO);
-	set_pair_visibility (h, &p->cc, visible_flags & E_MSG_COMPOSER_VISIBLE_CC);
-	set_pair_visibility (h, &p->bcc, visible_flags & E_MSG_COMPOSER_VISIBLE_BCC);
-	set_pair_visibility (h, &p->subject, visible_flags & E_MSG_COMPOSER_VISIBLE_SUBJECT);
-}
-
-void
-e_msg_composer_set_hdrs_visible (EMsgComposerHdrs *hdrs, int visible_flags)
-{
-	g_return_if_fail (hdrs != NULL);
-	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
+	header = header_new_recipient (hdrs, "Cc", _("Cc:"),
+				       _("Enter the addresses that will receive a carbon copy of the message"));
+	g_hash_table_insert (priv->headers, (gpointer) header->name, header);
+	attach_header (hdrs, header, LINE_CC);
 	
-	headers_set_visibility (hdrs, visible_flags);
-	gtk_widget_queue_resize (GTK_WIDGET (hdrs));
-}
+	header = header_new_recipient (hdrs, "Bcc", _("Bcc:"),
+				       _("Enter the addresses that will receive a carbon copy of "
+					 "the message without appearing in the recipient list of "
+					 "the message."));
+	g_hash_table_insert (priv->headers, (gpointer) header->name, header);
+	attach_header (hdrs, header, LINE_BCC);
 
-static void
-setup_headers (EMsgComposerHdrs *hdrs, int visible_flags)
-{
-	create_headers (hdrs);
-	attach_headers (hdrs);
-	
 	/*
 	 * To: is always visible
 	 */
-	gtk_widget_show (hdrs->priv->to.label);
-	gtk_widget_show (hdrs->priv->to.entry);
-	
-	headers_set_visibility (hdrs, visible_flags);
+	e_msg_composer_hdrs_set_header_visible(hdrs, "To", TRUE);
 }
 		
 
 /* GtkObject methods.  */
 
 static void
+free_header (const gchar *name, EMsgComposerHeader *header, gpointer data)
+{
+	gtk_object_destroy (GTK_OBJECT (header->label));
+	gtk_object_unref (GTK_OBJECT (header->entry));
+}
+
+static void
 destroy (GtkObject *object)
 {
 	EMsgComposerHdrs *hdrs;
@@ -524,6 +530,9 @@
 	
 	gtk_object_destroy (GTK_OBJECT (priv->tooltips));
 	gtk_object_unref (GTK_OBJECT (priv->tooltips));
+
+	g_hash_table_foreach(priv->headers, (GHFunc) free_header, NULL);
+	g_hash_table_destroy(priv->headers);
 	
 	l = priv->from_options;
 	while (l) {
@@ -631,20 +640,22 @@
 }
 
 GtkWidget *
-e_msg_composer_hdrs_new (int visible_flags)
+e_msg_composer_hdrs_new ()
 {
 	EMsgComposerHdrs *new;
 	EMsgComposerHdrsPrivate *priv;
 	
 	new = gtk_type_new (e_msg_composer_hdrs_get_type ());
 	priv = new->priv;
+	priv->headers = g_hash_table_new(g_str_hash, g_str_equal);
+	priv->dynamic_headers = NULL;
 	
 	if (!setup_corba (new)) {
 		gtk_widget_destroy (GTK_WIDGET (new));
 		return NULL;
 	}
 	
-	setup_headers (new, visible_flags);
+	setup_normal_headers (new);
 	
 	return GTK_WIDGET (new);
 }
@@ -732,11 +743,33 @@
 	camel_object_unref (CAMEL_OBJECT (bcc_addr));
 }
 
+static gboolean
+is_builtin_header (const gchar *name)
+{
+	return g_strcasecmp(name, "To") == 0
+		|| g_strcasecmp(name, "Cc") == 0
+		|| g_strcasecmp(name, "Bcc") == 0
+		|| g_strcasecmp(name, "From") == 0
+		|| g_strcasecmp(name, "Reply-To") == 0
+		|| g_strcasecmp(name, "Subject") == 0;
+}
+     
+static void
+push_extra_header (gpointer key, gpointer val, gpointer data)
+{
+	const gchar *name = (const gchar *) key;
+	const gchar *value = (const gchar *) val;
+	CamelMimeMessage *msg = (CamelMimeMessage *) data;
+	if (!is_builtin_header(name))
+		camel_medium_add_header(CAMEL_MEDIUM(msg), key, value);
+}
+
 static void
 e_msg_composer_hdrs_to_message_internal (EMsgComposerHdrs *hdrs,
 					 CamelMimeMessage *msg,
 					 gboolean redirect)
 {
+	GList *cur;
 	CamelInternetAddress *addr;
 	char *subject, *header;
 	EDestination **to_destv, **cc_destv, **bcc_destv;
@@ -777,6 +810,18 @@
 	e_destination_freev (to_destv);
 	e_destination_freev (cc_destv);
 	e_destination_freev (bcc_destv);
+
+	/* Include additional headers. */
+	g_hash_table_foreach(hdrs->priv->headers, push_extra_header, msg);
+
+	for (cur = hdrs->priv->dynamic_headers; cur; cur = cur->next) {
+		EMsgComposerDynamicHeader *header = (EMsgComposerDynamicHeader *) cur->data;
+		const char *key = e_entry_get_text (E_ENTRY (header->label));
+		const char *val = e_entry_get_text (E_ENTRY (header->entry));
+		if (key && key[0] != '\0' && val && val[0] != '\0'
+		    && !is_builtin_header(key))
+			camel_medium_add_header(CAMEL_MEDIUM(msg), key, val);
+	}
 }
 
 
@@ -801,6 +846,7 @@
 e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
 				      const char *account_name)
 {
+	EMsgComposerHeader *header;
 	GtkOptionMenu *omenu;
 	GtkWidget *item;
 	GSList *l;
@@ -809,7 +855,12 @@
 	
 	g_return_if_fail (hdrs != NULL);
 	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
+
+	header = g_hash_table_lookup(hdrs->priv->headers, "From");
+	g_return_if_fail (header != NULL);
 	
+	omenu = GTK_OPTION_MENU (gtk_object_get_data (GTK_OBJECT (header->entry),
+						      "from_menu"));
 	omenu = GTK_OPTION_MENU (e_msg_composer_hdrs_get_from_omenu (hdrs));
 	
 	if (account_name)
@@ -849,24 +900,30 @@
 e_msg_composer_hdrs_set_reply_to (EMsgComposerHdrs *hdrs,
 				  const char *reply_to)
 {
+	EMsgComposerHeader *header;
 	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
+	header = g_hash_table_lookup(hdrs->priv->headers, "Reply-To");
+	g_return_if_fail (header != NULL);
 	
-	e_entry_set_text (E_ENTRY (hdrs->priv->reply_to.entry), reply_to ? reply_to : "");
+	e_entry_set_text (E_ENTRY (header->entry), reply_to ? reply_to : "");
 	
 	if (reply_to && *reply_to)
-		set_pair_visibility (hdrs, &hdrs->priv->cc, TRUE);
+		e_msg_composer_hdrs_set_header_visible(hdrs, "Reply-To", TRUE);
 }
 
 void
 e_msg_composer_hdrs_set_to (EMsgComposerHdrs *hdrs,
 			    EDestination **to_destv)
 {
+	EMsgComposerHeader *header;
 	char *str;
-	
 	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
+	header = g_hash_table_lookup(hdrs->priv->headers, "To");
+	g_return_if_fail (header != NULL);
 	
 	str = e_destination_exportv (to_destv);
-	bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->to.entry), "destinations", str, NULL); 
+	bonobo_widget_set_property (BONOBO_WIDGET (header->entry), "destinations",
+				    str, NULL); 
 	g_free (str);
 }
 
@@ -875,13 +932,16 @@
 			    EDestination **cc_destv)
 {
 	char *str;
-	
+	EMsgComposerHeader *header;
 	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
+	header = g_hash_table_lookup(hdrs->priv->headers, "Cc");
+	g_return_if_fail (header != NULL);
 	
 	str = e_destination_exportv (cc_destv);
-	bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->cc.entry), "destinations", str, NULL);
+	bonobo_widget_set_property (BONOBO_WIDGET (header->entry), "destinations",
+				    str, NULL);
 	if (str && *str)
-		set_pair_visibility (hdrs, &hdrs->priv->cc, TRUE);
+		e_msg_composer_hdrs_set_header_visible(hdrs, "Cc", TRUE);
 	g_free (str);
 }
 
@@ -890,13 +950,16 @@
 			     EDestination **bcc_destv)
 {
 	char *str;
-	
+	EMsgComposerHeader *header;
 	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
+	header = g_hash_table_lookup(hdrs->priv->headers, "Bcc");
+	g_return_if_fail (header != NULL);
 	
 	str = e_destination_exportv (bcc_destv);
-	bonobo_widget_set_property (BONOBO_WIDGET (hdrs->priv->bcc.entry), "destinations", str, NULL); 
+	bonobo_widget_set_property (BONOBO_WIDGET (header->entry), "destinations",
+				    str, NULL); 
 	if (str && *str)
-		set_pair_visibility (hdrs, &hdrs->priv->bcc, TRUE);
+		e_msg_composer_hdrs_set_header_visible(hdrs, "Bcc", TRUE);
 	g_free (str);
 }
 
@@ -904,15 +967,112 @@
 e_msg_composer_hdrs_set_subject (EMsgComposerHdrs *hdrs,
 				 const char *subject)
 {
+	EMsgComposerHeader *header;
 	g_return_if_fail (hdrs != NULL);
 	g_return_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs));
 	g_return_if_fail (subject != NULL);
+	header = g_hash_table_lookup(hdrs->priv->headers, "Subject");
+	g_return_if_fail (header != NULL);
 	
-	gtk_object_set (GTK_OBJECT (hdrs->priv->subject.entry),
-			"text", subject,
+	gtk_object_set (GTK_OBJECT (header->entry), "text", subject, NULL);
+}
+
+char *e_msg_composer_hdrs_get_header_value (EMsgComposerHdrs *hdrs,
+					    const char *name)
+{
+	EMsgComposerHeader *header;
+
+	g_return_val_if_fail (hdrs != NULL, NULL);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	header = (EMsgComposerHeader *) g_hash_table_lookup(hdrs->priv->headers,
+							    name);
+	if (header)
+		return (gchar *) gtk_object_get_data (GTK_OBJECT(header->entry),
+						      "label");
+	return NULL;
+}
+
+gboolean e_msg_composer_hdrs_add_dynamic_header (EMsgComposerHdrs *hdrs)
+{
+	gint line;
+	GList *cur;
+	EMsgComposerDynamicHeader *header;
+	for (cur = hdrs->priv->dynamic_headers; cur; cur = cur->next) {
+		const char *key, *val;
+		header = (EMsgComposerDynamicHeader *) cur->data;
+		key = e_entry_get_text (E_ENTRY (header->label));
+		val = e_entry_get_text (E_ENTRY (header->entry));
+		if ((!key || key[0] == '\0')
+		    && (!val || val[0] == '\0'))
+			return FALSE;
+	}
+	header = g_new(EMsgComposerDynamicHeader, 1);
+	header->label = e_entry_new();
+	header->entry = e_entry_new();
+	hdrs->priv->dynamic_headers = g_list_prepend(hdrs->priv->dynamic_headers,
+						     header);
+	gtk_object_get(GTK_OBJECT(hdrs), "n_rows", &line, NULL);
+	gtk_table_attach (GTK_TABLE (hdrs),
+			  header->label, 0, 1,
+			  line, line + 1,
+			  GTK_FILL, GTK_FILL, GNOME_PAD, GNOME_PAD);
+	
+	gtk_table_attach (GTK_TABLE (hdrs),
+			  header->entry, 1, 2,
+			  line, line + 1,
+			  GTK_FILL | GTK_EXPAND, 0, 2, 2);
+	gtk_widget_show(header->label);
+	gtk_widget_show(header->entry);
+	line++;
+
+	return TRUE;
+}
+
+
+char *e_msg_composer_hdrs_add_raw_header (EMsgComposerHdrs *hdrs,
+					  const char *name,
+					  const char *value,
+					  gboolean visible)
+{
+	EMsgComposerHeader *header;
+	char *ovalue = NULL;
+
+	g_return_val_if_fail (hdrs != NULL, NULL);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	ovalue = e_msg_composer_hdrs_get_header_value(hdrs, name);
+
+	header = g_new(EMsgComposerHeader, 1);
+
+	header->label = gtk_label_new (name);
+	header->entry = e_entry_new ();
+	e_entry_set_text (E_ENTRY (header->entry), value);
+	gtk_object_set (GTK_OBJECT (header->entry),
+			"editable", TRUE,
+			"use_ellipsis", TRUE,
+			"allow_newlines", FALSE,
 			NULL);
+	g_hash_table_insert (hdrs->priv->headers, (gpointer) header->name, header);
+	return ovalue;
 }
 
+gboolean e_msg_composer_hdrs_remove_header (EMsgComposerHdrs *hdrs,
+					    const char *name)
+{
+	EMsgComposerHeader *header;
+
+	g_return_val_if_fail (hdrs != NULL, FALSE);
+	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), FALSE);
+
+	header = (EMsgComposerHeader *) g_hash_table_lookup(hdrs->priv->headers,
+							    name);
+	if (header) {
+		free_header(header->name, header, NULL);
+		return TRUE;
+	}
+	return FALSE;
+}
 
 CamelInternetAddress *
 e_msg_composer_hdrs_get_from (EMsgComposerHdrs *hdrs)
@@ -938,12 +1098,16 @@
 CamelInternetAddress *
 e_msg_composer_hdrs_get_reply_to (EMsgComposerHdrs *hdrs)
 {
+	EMsgComposerHeader *header;
 	CamelInternetAddress *addr;
 	const char *reply_to;
 	
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	header = g_hash_table_lookup(hdrs->priv->headers, "Reply-To");
+	g_return_val_if_fail (header != NULL, NULL);
 	
-	reply_to = e_entry_get_text (E_ENTRY (hdrs->priv->reply_to.entry));
+	reply_to = e_entry_get_text (E_ENTRY (header->entry));
 	
 	if (!reply_to || *reply_to == '\0')
 		return NULL;
@@ -960,12 +1124,17 @@
 EDestination **
 e_msg_composer_hdrs_get_to (EMsgComposerHdrs *hdrs)
 {
+	EMsgComposerHeader *header;
 	char *str = NULL;
 	EDestination **destv = NULL;
 	
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	header = g_hash_table_lookup(hdrs->priv->headers, "To");
+	g_return_val_if_fail (header != NULL, FALSE);
 	
-	bonobo_widget_get_property (BONOBO_WIDGET (hdrs->priv->to.entry), "destinations", &str, NULL); 
+	bonobo_widget_get_property (BONOBO_WIDGET (header->entry), "destinations",
+				    &str, NULL); 
 	
 	if (str != NULL) {
 		destv = e_destination_importv (str);
@@ -978,12 +1147,17 @@
 EDestination **
 e_msg_composer_hdrs_get_cc (EMsgComposerHdrs *hdrs)
 {
+	EMsgComposerHeader *header;
 	char *str = NULL;
 	EDestination **destv = NULL;
 	
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	header = g_hash_table_lookup(hdrs->priv->headers, "Cc");
+	g_return_val_if_fail (header != NULL, FALSE);
 	
-	bonobo_widget_get_property (BONOBO_WIDGET (hdrs->priv->cc.entry), "destinations", &str, NULL); 
+	bonobo_widget_get_property (BONOBO_WIDGET (header->entry), "destinations",
+				    &str, NULL); 
 	
 	if (str != NULL) {
 		destv = e_destination_importv (str);
@@ -996,12 +1170,17 @@
 EDestination **
 e_msg_composer_hdrs_get_bcc (EMsgComposerHdrs *hdrs)
 {
+	EMsgComposerHeader *header;
 	char *str = NULL;
 	EDestination **destv = NULL;
 	
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
 	
-	bonobo_widget_get_property (BONOBO_WIDGET (hdrs->priv->bcc.entry), "destinations", &str, NULL); 
+	header = g_hash_table_lookup(hdrs->priv->headers, "Bcc");
+	g_return_val_if_fail (header != NULL, FALSE);
+	
+	bonobo_widget_get_property (BONOBO_WIDGET (header->entry), "destinations",
+				    &str, NULL); 
 	
 	if (str != NULL) {
 		destv = e_destination_importv (str);
@@ -1059,77 +1238,82 @@
 char *
 e_msg_composer_hdrs_get_subject (EMsgComposerHdrs *hdrs)
 {
+	EMsgComposerHeader *header;
 	char *subject;
 	
 	g_return_val_if_fail (hdrs != NULL, NULL);
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	header = g_hash_table_lookup(hdrs->priv->headers, "Subject");
+	g_return_val_if_fail (header != NULL, FALSE);
 	
-	gtk_object_get (GTK_OBJECT (hdrs->priv->subject.entry),
+	gtk_object_get (GTK_OBJECT (header->entry),
 			"text", &subject, NULL);
 	
 	return subject;
 }
 
 
-GtkWidget *
-e_msg_composer_hdrs_get_reply_to_entry (EMsgComposerHdrs *hdrs)
+
+static GtkWidget *
+generic_get_header_entry (EMsgComposerHdrs *hdrs,
+			  const gchar *name)
 {
+	EMsgComposerHeader *header;
 	g_return_val_if_fail (hdrs != NULL, NULL);
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
 	
-	return hdrs->priv->reply_to.entry;
+	header = g_hash_table_lookup(hdrs->priv->headers, name);
+	g_return_val_if_fail (header != NULL, NULL);
+
+	return header->entry;
+}
+
+GtkWidget *
+e_msg_composer_hdrs_get_reply_to_entry (EMsgComposerHdrs *hdrs)
+{
+	return generic_get_header_entry(hdrs, "Reply-To");
 }
 
 GtkWidget *
 e_msg_composer_hdrs_get_to_entry (EMsgComposerHdrs *hdrs)
 {
-	g_return_val_if_fail (hdrs != NULL, NULL);
-	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
-	
-	return hdrs->priv->to.entry;
+	return generic_get_header_entry(hdrs, "To");
 }
 
 GtkWidget *
 e_msg_composer_hdrs_get_cc_entry (EMsgComposerHdrs *hdrs)
 {
-	g_return_val_if_fail (hdrs != NULL, NULL);
-	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
-	
-	return hdrs->priv->cc.entry;
+	return generic_get_header_entry(hdrs, "Cc");
 }
 
 GtkWidget *
 e_msg_composer_hdrs_get_bcc_entry (EMsgComposerHdrs *hdrs)
 {
-	g_return_val_if_fail (hdrs != NULL, NULL);
-	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
-	
-	return hdrs->priv->bcc.entry;
+	return generic_get_header_entry(hdrs, "Bcc");
 }
 
 GtkWidget *
 e_msg_composer_hdrs_get_subject_entry (EMsgComposerHdrs *hdrs)
 {
-	g_return_val_if_fail (hdrs != NULL, NULL);
-	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
-	
-	return hdrs->priv->subject.entry;
+	return generic_get_header_entry(hdrs, "Subject");
 }
 
 GtkWidget *
 e_msg_composer_hdrs_get_from_hbox (EMsgComposerHdrs *hdrs)
 {
-	g_return_val_if_fail (hdrs != NULL, NULL);
-	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
-	
-	return hdrs->priv->from.entry;
+	return generic_get_header_entry(hdrs, "From");
 }
 
 GtkWidget *
 e_msg_composer_hdrs_get_from_omenu (EMsgComposerHdrs *hdrs)
 {
+	GtkWidget *wid;
 	g_return_val_if_fail (hdrs != NULL, NULL);
 	g_return_val_if_fail (E_IS_MSG_COMPOSER_HDRS (hdrs), NULL);
+
+	wid = e_msg_composer_hdrs_get_from_hbox(hdrs);
+	g_return_val_if_fail (wid != NULL, NULL);
 	
-	return GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (hdrs->priv->from.entry), "from_menu"));
+	return GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (wid), "from_menu"));
 }
