Hello,
The Debian bug tracking system uses a number of additional message
headers like X-Debbugs-CC which I need to be able to set. Currently
Evolution doesn't give me a way to add these when sending a message.
Attached is a patch which fixes this bug. I'm not totally satisfied
with the UI; currently, there is no way to remove an added header from
the interface, although if you clear out the header name field, the
header will not be added (of course). But overall I think it works
quite well.
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 15 Jun 2002 17:36:19 -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 15 Jun 2002 17:36:19 -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 15 Jun 2002 17:36:20 -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 15 Jun 2002 17:36:20 -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 15 Jun 2002 17:36:20 -0000
@@ -2,6 +2,7 @@
/* msg-composer-hdrs.c
*
* Copyright (C) 1999 Ximian, Inc.
+ * Copyright (C) 2002 Colin Walters <[EMAIL PROTECTED]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -58,11 +59,20 @@
#define LINE_CC 3
#define LINE_BCC 4
#define LINE_SUBJECT 5
+/* The line at which user-added extra headers start at. Put static
+ headers before this. */
+#define LINE_EXTRA 6
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 +82,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 +182,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 +336,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 +379,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 +533,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 +643,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 +746,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 +813,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 +849,7 @@
e_msg_composer_hdrs_set_from_account (EMsgComposerHdrs *hdrs,
const char *account_name)
{
+ EMsgComposerHeader *header;
GtkOptionMenu *omenu;
GtkWidget *item;
GSList *l;
@@ -809,7 +858,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 +903,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 +935,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 +953,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 +970,111 @@
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)
+{
+ static gint line = LINE_EXTRA;
+ 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_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 +1100,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 +1126,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 +1149,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 +1172,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 +1240,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"));
}