fixes for custom headers and displaying of headers
[claws.git] / src / compose.c
index 9a0a68631d95b15ce5c613f7625263c9a5c61cf7..674e16f4aa6139ab4ce725f14579be4f6feef19e 100644 (file)
@@ -35,7 +35,6 @@
 #include <gtk/gtkclist.h>
 #include <gtk/gtkctree.h>
 #include <gtk/gtkvpaned.h>
-#include <gtk/gtktext.h>
 #include <gtk/gtkentry.h>
 #include <gtk/gtkeditable.h>
 #include <gtk/gtkwindow.h>
@@ -67,6 +66,9 @@
 #  include <wctype.h>
 #endif
 
+
+#include "gtkstext.h"
+
 #include "intl.h"
 #include "main.h"
 #include "mainwindow.h"
@@ -95,6 +97,7 @@
 #include "gtkshruler.h"
 #include "folder.h"
 #include "addr_compl.h"
+#include "customheader.h"
 
 #if USE_GPGME
 #  include "rfc2015.h"
@@ -200,7 +203,7 @@ static void compose_input_cb                        (gpointer           data,
 static void compose_set_ext_editor_sensitive   (Compose           *compose,
                                                 gboolean           sensitive);
 
-static gint calc_cursor_xpos   (GtkText        *text,
+static gint calc_cursor_xpos   (GtkSText       *text,
                                 gint            extra,
                                 gint            char_width);
 
@@ -441,7 +444,7 @@ void compose_new_with_recipient(PrefsAccount *account, const gchar *to)
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
        gtk_editable_set_position(GTK_EDITABLE(compose->text), 0);
-       gtk_text_set_point(GTK_TEXT(compose->text), 0);
+       gtk_stext_set_point(GTK_STEXT(compose->text), 0);
 
        if (account->protocol != A_NNTP) {
                if (to) {
@@ -457,7 +460,7 @@ void compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all)
 {
        Compose *compose;
        PrefsAccount *account;
-       GtkText *text;
+       GtkSText *text;
 
        g_return_if_fail(msginfo != NULL);
        g_return_if_fail(msginfo->folder != NULL);
@@ -475,8 +478,8 @@ void compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all)
        if (compose_parse_header(compose, msginfo) < 0) return;
        compose_reply_set_entry(compose, msginfo, to_all);
 
-       text = GTK_TEXT(compose->text);
-       gtk_text_freeze(text);
+       text = GTK_STEXT(compose->text);
+       gtk_stext_freeze(text);
 
        if (quote) {
                FILE *fp;
@@ -487,7 +490,7 @@ void compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all)
                else {
                        quote_str = compose_quote_parse_fmt
                                (compose, msginfo, prefs_common.quotefmt);
-                       gtk_text_insert(text, NULL, NULL, NULL, quote_str, -1);
+                       gtk_stext_insert(text, NULL, NULL, NULL, quote_str, -1);
                        g_free(quote_str);
                        compose_quote_file(compose, msginfo, fp);
                        fclose(fp);
@@ -497,24 +500,24 @@ void compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all)
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
        gtk_editable_set_position(GTK_EDITABLE(text), 0);
-       gtk_text_set_point(text, 0);
+       gtk_stext_set_point(text, 0);
 
-       gtk_text_thaw(text);
+       gtk_stext_thaw(text);
        gtk_widget_grab_focus(compose->text);
 }
 
 #define INSERT_FW_HEADER(var, hdr) \
 if (msginfo->var && *msginfo->var) { \
-       gtk_text_insert(text, NULL, NULL, NULL, hdr, -1); \
-       gtk_text_insert(text, NULL, NULL, NULL, msginfo->var, -1); \
-       gtk_text_insert(text, NULL, NULL, NULL, "\n", 1); \
+       gtk_stext_insert(text, NULL, NULL, NULL, hdr, -1); \
+       gtk_stext_insert(text, NULL, NULL, NULL, msginfo->var, -1); \
+       gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1); \
 }
 
 void compose_forward(MsgInfo *msginfo, gboolean as_attach)
 {
        Compose *compose;
        PrefsAccount *account;
-       GtkText *text;
+       GtkSText *text;
        FILE *fp;
        gchar buf[BUFFSIZE];
 
@@ -537,8 +540,8 @@ void compose_forward(MsgInfo *msginfo, gboolean as_attach)
                                      msginfo->subject);
        }
 
-       text = GTK_TEXT(compose->text);
-       gtk_text_freeze(text);
+       text = GTK_STEXT(compose->text);
+       gtk_stext_freeze(text);
 
        if (as_attach) {
                gchar *msgfile;
@@ -556,18 +559,18 @@ void compose_forward(MsgInfo *msginfo, gboolean as_attach)
                        g_warning(_("Can't get text part\n"));
                else {
                        /* insert header */
-                       gtk_text_insert(text, NULL, NULL, NULL,
+                       gtk_stext_insert(text, NULL, NULL, NULL,
                                        _("\n\nBegin forwarded message:\n\n"), -1);
                        INSERT_FW_HEADER(date,       "Date: ");
                        INSERT_FW_HEADER(from,       "From: ");
                        INSERT_FW_HEADER(to,         "To: ");
                        INSERT_FW_HEADER(newsgroups, "Newsgroups: ");
                        INSERT_FW_HEADER(subject,    "Subject: ");
-                       gtk_text_insert(text, NULL, NULL, NULL, "\n\n", 2);
+                       gtk_stext_insert(text, NULL, NULL, NULL, "\n\n", 2);
 
                        /* forward body */
                        while (fgets(buf, sizeof(buf), fp) != NULL)
-                               gtk_text_insert(text, NULL, NULL, NULL,
+                               gtk_stext_insert(text, NULL, NULL, NULL,
                                                buf, -1);
                        fclose(fp);
                }
@@ -576,9 +579,9 @@ void compose_forward(MsgInfo *msginfo, gboolean as_attach)
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
        gtk_editable_set_position(GTK_EDITABLE(compose->text), 0);
-       gtk_text_set_point(GTK_TEXT(compose->text), 0);
+       gtk_stext_set_point(GTK_STEXT(compose->text), 0);
 
-       gtk_text_thaw(text);
+       gtk_stext_thaw(text);
        if (account->protocol != A_NNTP)
                gtk_widget_grab_focus(compose->to_entry);
        else
@@ -589,7 +592,7 @@ void compose_reedit(MsgInfo *msginfo)
 {
        Compose *compose;
        PrefsAccount *account;
-       GtkText *text;
+       GtkSText *text;
        FILE *fp;
        gchar buf[BUFFSIZE];
 
@@ -607,18 +610,18 @@ void compose_reedit(MsgInfo *msginfo)
        if (compose_parse_header(compose, msginfo) < 0) return;
        compose_reedit_set_entry(compose, msginfo);
 
-       text = GTK_TEXT(compose->text);
-       gtk_text_freeze(text);
+       text = GTK_STEXT(compose->text);
+       gtk_stext_freeze(text);
 
        if ((fp = procmime_get_text_part(msginfo)) == NULL)
                g_warning(_("Can't get text part\n"));
        else {
                while (fgets(buf, sizeof(buf), fp) != NULL)
-                       gtk_text_insert(text, NULL, NULL, NULL, buf, -1);
+                       gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
                fclose(fp);
        }
 
-       gtk_text_thaw(text);
+       gtk_stext_thaw(text);
        gtk_widget_grab_focus(compose->text);
 }
 
@@ -794,7 +797,7 @@ static gchar *compose_parse_references(const gchar *ref, const gchar *msgid)
 
 static void compose_quote_file(Compose *compose, MsgInfo *msginfo, FILE *fp)
 {
-       GtkText *text = GTK_TEXT(compose->text);
+       GtkSText *text = GTK_STEXT(compose->text);
        gchar *qmark;
        gchar *quote_str;
        GdkColor *qcolor = NULL;
@@ -818,9 +821,9 @@ static void compose_quote_file(Compose *compose, MsgInfo *msginfo, FILE *fp)
        if (!prefs_common.linewrap_quote ||
            prefs_common.linewrap_len <= qlen) {
                while (fgets(buf, sizeof(buf), fp) != NULL) {
-                       gtk_text_insert(text, NULL, qcolor, NULL,
+                       gtk_stext_insert(text, NULL, qcolor, NULL,
                                        quote_str, -1);
-                       gtk_text_insert(text, NULL, qcolor, NULL, buf, -1);
+                       gtk_stext_insert(text, NULL, qcolor, NULL, buf, -1);
                }
                g_free(quote_str);
                return;
@@ -833,10 +836,10 @@ static void compose_quote_file(Compose *compose, MsgInfo *msginfo, FILE *fp)
                str_len = strlen(buf);
 
                if (str_len <= wrap_len) {
-                       gtk_text_insert(text, NULL, qcolor, NULL,
+                       gtk_stext_insert(text, NULL, qcolor, NULL,
                                        quote_str, -1);
-                       gtk_text_insert(text, NULL, qcolor, NULL, buf, -1);
-                       gtk_text_insert(text, NULL, NULL, NULL, "\n", 1);
+                       gtk_stext_insert(text, NULL, qcolor, NULL, buf, -1);
+                       gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
                        continue;
                }
 
@@ -853,18 +856,18 @@ static void compose_quote_file(Compose *compose, MsgInfo *msginfo, FILE *fp)
                        }
 
                        if (cur_len + ch_len > wrap_len && line_len > 0) {
-                               gtk_text_insert(text, NULL, qcolor, NULL,
+                               gtk_stext_insert(text, NULL, qcolor, NULL,
                                                quote_str, -1);
 
                                if (isspace(*(linep - 1)))
-                                       gtk_text_insert(text, NULL,
+                                       gtk_stext_insert(text, NULL,
                                                        qcolor, NULL,
                                                        leftp, line_len - 1);
                                else
-                                       gtk_text_insert(text, NULL,
+                                       gtk_stext_insert(text, NULL,
                                                        qcolor, NULL,
                                                        leftp, line_len);
-                               gtk_text_insert(text, NULL, NULL, NULL,
+                               gtk_stext_insert(text, NULL, NULL, NULL,
                                                "\n", 1);
 
                                leftp = linep;
@@ -883,10 +886,10 @@ static void compose_quote_file(Compose *compose, MsgInfo *msginfo, FILE *fp)
                }
 
                if (*leftp) {
-                       gtk_text_insert(text, NULL, qcolor, NULL,
+                       gtk_stext_insert(text, NULL, qcolor, NULL,
                                        quote_str, -1);
-                       gtk_text_insert(text, NULL, qcolor, NULL, leftp, -1);
-                       gtk_text_insert(text, NULL, NULL, NULL, "\n", 1);
+                       gtk_stext_insert(text, NULL, qcolor, NULL, leftp, -1);
+                       gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
                }
        }
 
@@ -1168,7 +1171,7 @@ static void compose_insert_sig(Compose *compose)
        if (compose->account && compose->account->sig_path)
                sigfile = g_strdup(compose->account->sig_path);
        else {
-               sigfile = g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S,
+               sigfile = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S,
                                      DEFAULT_SIGNATURE, NULL);
        }
 
@@ -1177,11 +1180,11 @@ static void compose_insert_sig(Compose *compose)
                return;
        }
 
-       gtk_text_insert(GTK_TEXT(compose->text), NULL, NULL, NULL, "\n\n", 2);
+       gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL, "\n\n", 2);
        if (prefs_common.sig_sep) {
-               gtk_text_insert(GTK_TEXT(compose->text), NULL, NULL, NULL,
+               gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL,
                                prefs_common.sig_sep, -1);
-               gtk_text_insert(GTK_TEXT(compose->text), NULL, NULL, NULL,
+               gtk_stext_insert(GTK_STEXT(compose->text), NULL, NULL, NULL,
                                "\n", 1);
        }
 
@@ -1191,7 +1194,7 @@ static void compose_insert_sig(Compose *compose)
 
 static void compose_insert_file(Compose *compose, const gchar *file)
 {
-       GtkText *text = GTK_TEXT(compose->text);
+       GtkSText *text = GTK_STEXT(compose->text);
        gchar buf[BUFFSIZE];
        FILE *fp;
 
@@ -1202,12 +1205,12 @@ static void compose_insert_file(Compose *compose, const gchar *file)
                return;
        }
 
-       gtk_text_freeze(text);
+       gtk_stext_freeze(text);
 
        while (fgets(buf, sizeof(buf), fp) != NULL)
-               gtk_text_insert(text, NULL, NULL, NULL, buf, -1);
+               gtk_stext_insert(text, NULL, NULL, NULL, buf, -1);
 
-       gtk_text_thaw(text);
+       gtk_stext_thaw(text);
 
        fclose(fp);
 }
@@ -1275,23 +1278,23 @@ static void compose_attach_append(Compose *compose, const gchar *file,
 
 static void compose_wrap_line(Compose *compose)
 {
-       GtkText *text = GTK_TEXT(compose->text);
+       GtkSText *text = GTK_STEXT(compose->text);
        guint text_len;
        guint line_pos = 0, cur_pos = 0;
        gint line_len = 0, cur_len = 0;
        gint ch_len;
        gchar cbuf[MB_CUR_MAX];
 
-       gtk_text_freeze(text);
+       gtk_stext_freeze(text);
 
-       text_len = gtk_text_get_length(text);
+       text_len = gtk_stext_get_length(text);
 
        for (; cur_pos < text_len; cur_pos++) {
                if (text->use_wchar)
                        ch_len = wctomb
-                               (cbuf, (wchar_t)GTK_TEXT_INDEX(text, cur_pos));
+                               (cbuf, (wchar_t)GTK_STEXT_INDEX(text, cur_pos));
                else {
-                       cbuf[0] = GTK_TEXT_INDEX(text, cur_pos);
+                       cbuf[0] = GTK_STEXT_INDEX(text, cur_pos);
                        ch_len = 1;
                }
 
@@ -1316,14 +1319,14 @@ static void compose_wrap_line(Compose *compose)
                        gint tlen;
 
                        if (text->use_wchar)
-                               tlen = wctomb(cbuf, (wchar_t)GTK_TEXT_INDEX(text, line_pos - 1));
+                               tlen = wctomb(cbuf, (wchar_t)GTK_STEXT_INDEX(text, line_pos - 1));
                        else {
-                               cbuf[0] = GTK_TEXT_INDEX(text, line_pos - 1);
+                               cbuf[0] = GTK_STEXT_INDEX(text, line_pos - 1);
                                tlen = 1;
                        }
                        if (tlen == 1 && isspace(*cbuf)) {
-                               gtk_text_set_point(text, line_pos);
-                               gtk_text_backward_delete(text, 1);
+                               gtk_stext_set_point(text, line_pos);
+                               gtk_stext_backward_delete(text, 1);
                                text_len--;
                                cur_pos--;
                                line_pos--;
@@ -1331,8 +1334,8 @@ static void compose_wrap_line(Compose *compose)
                                line_len--;
                        }
 
-                       gtk_text_set_point(text, line_pos);
-                       gtk_text_insert(text, NULL, NULL, NULL, "\n", 1);
+                       gtk_stext_set_point(text, line_pos);
+                       gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
                        text_len++;
                        cur_pos++;
                        line_pos++;
@@ -1348,7 +1351,7 @@ static void compose_wrap_line(Compose *compose)
                cur_len += ch_len;
        }
 
-       gtk_text_thaw(text);
+       gtk_stext_thaw(text);
 }
 
 static void compose_set_title(Compose *compose)
@@ -1588,7 +1591,7 @@ static gint compose_write_to_file(Compose *compose, const gchar *file,
 
 #if USE_GPGME
        if (compose->use_signing) {
-               if (rfc2015_sign(file) < 0) {
+               if (rfc2015_sign(file, compose->account) < 0) {
                        unlink(file);
                        return -1;
                }
@@ -1780,6 +1783,9 @@ static gint compose_queue(Compose *compose, const gchar *file)
        }
        g_free(queue_path);
 
+       folder_item_scan(queue);
+       folderview_update_item(queue, TRUE);
+
        return 0;
 }
 
@@ -1852,6 +1858,21 @@ static void compose_write_attach(Compose *compose, FILE *fp)
        fprintf(fp, "\n--%s--\n", compose->boundary);
 }
 
+static gint is_in_custom_headers(Compose *compose, gchar * header)
+{
+       GSList * cur;
+
+       if (compose->account->add_customhdr) {
+               for (cur = compose->account->customhdr_list;
+                    cur != NULL; cur = cur->next) {
+                       CustomHeader * ch = (CustomHeader *) cur->data;
+                       if (strcasecmp(ch->name, header) == 0)
+                               return 1;
+               }
+       }
+       return 0;
+}
+
 static gint compose_write_headers(Compose *compose, FILE *fp,
                                  const gchar *charset, EncodingType encoding,
                                  gboolean is_draft)
@@ -1859,6 +1880,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        gchar buf[BUFFSIZE];
        gchar *str;
        /* struct utsname utsbuf; */
+       GSList * cur;
 
        g_return_val_if_fail(fp != NULL, -1);
        g_return_val_if_fail(charset != NULL, -1);
@@ -1866,19 +1888,23 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        g_return_val_if_fail(compose->account->address != NULL, -1);
 
        /* Date */
-       if (compose->account->add_date) {
-               get_rfc822_date(buf, sizeof(buf));
-               fprintf(fp, "Date: %s\n", buf);
+       if (!is_in_custom_headers(compose, "Date")) {
+               if (compose->account->add_date) {
+                       get_rfc822_date(buf, sizeof(buf));
+                       fprintf(fp, "Date: %s\n", buf);
+               }
        }
 
        /* From */
-       if (compose->account->name && *compose->account->name) {
-               compose_convert_header
-                       (buf, sizeof(buf), compose->account->name,
-                        strlen("From: "));
-               fprintf(fp, "From: %s <%s>\n", buf, compose->account->address);
-       } else
-               fprintf(fp, "From: %s\n", compose->account->address);
+       if (!is_in_custom_headers(compose, "From")) {
+               if (compose->account->name && *compose->account->name) {
+                       compose_convert_header
+                               (buf, sizeof(buf), compose->account->name,
+                                strlen("From: "));
+                       fprintf(fp, "From: %s <%s>\n", buf, compose->account->address);
+               } else
+                       fprintf(fp, "From: %s\n", compose->account->address);
+       }
 
        slist_free_strings(compose->to_list);
        g_slist_free(compose->to_list);
@@ -1895,7 +1921,9 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                                        (compose->to_list, str);
                                compose_convert_header(buf, sizeof(buf), str,
                                                       strlen("To: "));
-                               fprintf(fp, "To: %s\n", buf);
+                               if (!is_in_custom_headers(compose, "To")) {
+                                       fprintf(fp, "To: %s\n", buf);
+                               }
                        }
                }
        }
@@ -1916,7 +1944,9 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                                                      str);
                        compose_convert_header(buf, sizeof(buf), str,
                                               strlen("Newsgroups: "));
-                       fprintf(fp, "Newsgroups: %s\n", buf);
+                       if (!is_in_custom_headers(compose, "Newsgroups")) {
+                               fprintf(fp, "Newsgroups: %s\n", buf);
+                       }
                }
        }
 
@@ -1934,7 +1964,9 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                                        (compose->to_list, str);
                                compose_convert_header(buf, sizeof(buf), str,
                                                       strlen("Cc: "));
-                               fprintf(fp, "Cc: %s\n", buf);
+                               if (!is_in_custom_headers(compose, "Cc")) {
+                                       fprintf(fp, "Cc: %s\n", buf);
+                               }
                        }
                }
        }
@@ -1952,110 +1984,151 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                                        compose_convert_header
                                                (buf, sizeof(buf), str,
                                                 strlen("Bcc: "));
-                                       fprintf(fp, "Bcc: %s\n", buf);
+                                       if (!is_in_custom_headers(compose,
+                                                                 "Bcc")) {
+                                               fprintf(fp, "Bcc: %s\n", buf);
+                                       }
                                }
                        }
                }
        }
 
        /* Subject */
-       str = gtk_entry_get_text(GTK_ENTRY(compose->subject_entry));
-       if (*str != '\0') {
-               Xstrdup_a(str, str, return -1);
-               g_strstrip(str);
+       if (!is_in_custom_headers(compose, "Subject")) {
+               str = gtk_entry_get_text(GTK_ENTRY(compose->subject_entry));
                if (*str != '\0') {
-                       compose_convert_header(buf, sizeof(buf), str,
-                                              strlen("Subject: "));
-                       fprintf(fp, "Subject: %s\n", buf);
+                       Xstrdup_a(str, str, return -1);
+                       g_strstrip(str);
+                       if (*str != '\0') {
+                               compose_convert_header(buf, sizeof(buf), str,
+                                                      strlen("Subject: "));
+                               fprintf(fp, "Subject: %s\n", buf);
+                       }
                }
        }
 
        /* Message-ID */
-       if (compose->account->gen_msgid) {
-               compose_generate_msgid(compose, buf, sizeof(buf));
-               fprintf(fp, "Message-Id: <%s>\n", buf);
-               compose->msgid = g_strdup(buf);
+       if (!is_in_custom_headers(compose, "Message-Id")) {
+               if (compose->account->gen_msgid) {
+                       compose_generate_msgid(compose, buf, sizeof(buf));
+                       fprintf(fp, "Message-Id: <%s>\n", buf);
+                       compose->msgid = g_strdup(buf);
+               }
        }
 
        /* In-Reply-To */
-       if (compose->inreplyto && compose->to_list)
-               fprintf(fp, "In-Reply-To: <%s>\n", compose->inreplyto);
+       if (!is_in_custom_headers(compose, "In-Reply-To")) {
+               if (compose->inreplyto && compose->to_list)
+                       fprintf(fp, "In-Reply-To: <%s>\n", compose->inreplyto);
+       }
 
        /* References */
-       if (compose->references)
-               fprintf(fp, "References: %s\n", compose->references);
+       if (!is_in_custom_headers(compose, "References")) {
+               if (compose->references)
+                       fprintf(fp, "References: %s\n", compose->references);
+       }
 
        /* Followup-To */
-       if (compose->use_followupto) {
-               str = gtk_entry_get_text(GTK_ENTRY(compose->followup_entry));
-               if (*str != '\0') {
-                       Xstrdup_a(str, str, return -1);
-                       g_strstrip(str);
-                       remove_space(str);
+       if (!is_in_custom_headers(compose, "Followup-To")) {
+               if (compose->use_followupto) {
+                       str = gtk_entry_get_text(GTK_ENTRY(compose->followup_entry));
                        if (*str != '\0') {
-                               compose_convert_header(buf, sizeof(buf), str,
-                                                      strlen("Followup-To: "));
-                               fprintf(fp, "Followup-To: %s\n", buf);
+                               Xstrdup_a(str, str, return -1);
+                               g_strstrip(str);
+                               remove_space(str);
+                               if (*str != '\0') {
+                                       compose_convert_header(buf, sizeof(buf), str,
+                                                              strlen("Followup-To: "));
+                                       fprintf(fp, "Followup-To: %s\n", buf);
+                               }
                        }
                }
        }
 
        /* Reply-To */
-       if (compose->use_replyto) {
-               str = gtk_entry_get_text(GTK_ENTRY(compose->reply_entry));
-               if (*str != '\0') {
-                       Xstrdup_a(str, str, return -1);
-                       g_strstrip(str);
+       if (!is_in_custom_headers(compose, "Reply-To")) {
+               if (compose->use_replyto) {
+                       str = gtk_entry_get_text(GTK_ENTRY(compose->reply_entry));
                        if (*str != '\0') {
-                               compose_convert_header(buf, sizeof(buf), str,
-                                                      strlen("Reply-To: "));
-                               fprintf(fp, "Reply-To: %s\n", buf);
+                               Xstrdup_a(str, str, return -1);
+                               g_strstrip(str);
+                               if (*str != '\0') {
+                                       compose_convert_header(buf, sizeof(buf), str,
+                                                              strlen("Reply-To: "));
+                                       fprintf(fp, "Reply-To: %s\n", buf);
+                               }
                        }
                }
        }
 
        /* Program version and system info */
        /* uname(&utsbuf); */
-       str = gtk_entry_get_text(GTK_ENTRY(compose->to_entry));
-       if (*str != '\0') {
-               fprintf(fp, "X-Mailer: %s (GTK+ %d.%d.%d; %s)\n",
-                       prog_version,
-                       gtk_major_version, gtk_minor_version, gtk_micro_version,
-                       HOST_ALIAS);
+       if (!is_in_custom_headers(compose, "X-Mailer")) {
+               str = gtk_entry_get_text(GTK_ENTRY(compose->to_entry));
+               if (*str != '\0') {
+                       fprintf(fp, "X-Mailer: %s (GTK+ %d.%d.%d; %s)\n",
+                               prog_version,
+                               gtk_major_version, gtk_minor_version, gtk_micro_version,
+                               HOST_ALIAS);
                        /* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
+               }
        }
-       str = gtk_entry_get_text(GTK_ENTRY(compose->newsgroups_entry));
-       if (*str != '\0') {
+
+       if (!is_in_custom_headers(compose, "X-Newsreader")) {
+               str = gtk_entry_get_text(GTK_ENTRY(compose->newsgroups_entry));
+               if (*str != '\0') {
                fprintf(fp, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
                        HOST_ALIAS);
                        /* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
+               }
        }
 
        /* Organization */
-       if (compose->account->organization) {
-               compose_convert_header(buf, sizeof(buf),
-                                      compose->account->organization,
-                                      strlen("Organization: "));
-               fprintf(fp, "Organization: %s\n", buf);
+       if (!is_in_custom_headers(compose, "Organization")) {
+               if (compose->account->organization) {
+                       compose_convert_header(buf, sizeof(buf),
+                                              compose->account->organization,
+                                              strlen("Organization: "));
+                       fprintf(fp, "Organization: %s\n", buf);
+               }
        }
 
        /* MIME */
-       fprintf(fp, "Mime-Version: 1.0\n");
+       if (!is_in_custom_headers(compose, "Mime-Version")) {
+               fprintf(fp, "Mime-Version: 1.0\n");
+       }
+
        if (compose->use_attach) {
                get_rfc822_date(buf, sizeof(buf));
                subst_char(buf, ' ', '_');
                subst_char(buf, ',', '_');
                compose->boundary = g_strdup_printf("Multipart_%s_%08x",
                                                    buf, (guint)compose);
-               fprintf(fp,
-                       "Content-Type: multipart/mixed;\n"
-                       " boundary=\"%s\"\n", compose->boundary);
+               if (!is_in_custom_headers(compose, "Content-Type")) {
+                       fprintf(fp,
+                               "Content-Type: multipart/mixed;\n"
+                               " boundary=\"%s\"\n", compose->boundary);
+               }
        } else {
-               fprintf(fp, "Content-Type: text/plain; charset=%s\n", charset);
-               fprintf(fp, "Content-Transfer-Encoding: %s\n",
-                       procmime_get_encoding_str(encoding));
+               if (!is_in_custom_headers(compose, "Content-Type")) {
+                       fprintf(fp, "Content-Type: text/plain; charset=%s\n", charset);
+               }
+               if (!is_in_custom_headers(compose,
+                                         "Content-Transfer-Encoding")) {
+                       fprintf(fp, "Content-Transfer-Encoding: %s\n",
+                               procmime_get_encoding_str(encoding));
+               }
+       }
+
+       /* Custom Headers */
+       if (compose->account->add_customhdr) {
+               for (cur = compose->account->customhdr_list; cur != NULL;
+                    cur = cur->next) {
+                       CustomHeader * ch = (CustomHeader *) cur->data;
+                       fprintf(fp, "%s: %s\n", ch->name, ch->value);
+               }
        }
 
        /* separator between header and body */
@@ -2364,12 +2437,14 @@ static Compose *compose_create(PrefsAccount *account)
        gtk_box_pack_start(GTK_BOX(edit_vbox), scrolledwin, TRUE, TRUE, 0);
        gtk_widget_set_usize(scrolledwin, prefs_common.compose_width, -1);
 
-       text = gtk_text_new(gtk_scrolled_window_get_hadjustment
+       text = gtk_stext_new(gtk_scrolled_window_get_hadjustment
                            (GTK_SCROLLED_WINDOW(scrolledwin)),
                            gtk_scrolled_window_get_vadjustment
                            (GTK_SCROLLED_WINDOW(scrolledwin)));
-       gtk_text_set_editable(GTK_TEXT(text), TRUE);
-       gtk_text_set_word_wrap(GTK_TEXT(text), TRUE);
+       gtk_stext_set_editable(GTK_STEXT(text), TRUE);
+       gtk_stext_set_word_wrap(GTK_STEXT(text), TRUE);
+       gtk_stext_set_wrap_rmargin(GTK_STEXT(text), prefs_common.linewrap_len);
+
        gtk_container_add(GTK_CONTAINER(scrolledwin), text);
 
        gtk_signal_connect(GTK_OBJECT(text), "changed",
@@ -2399,7 +2474,7 @@ static Compose *compose_create(PrefsAccount *account)
 
        style = gtk_widget_get_style(text);
 
-       /* workaround for the slow down of GtkText when using Pixmap theme */
+       /* workaround for the slow down of GtkSText when using Pixmap theme */
        if (style->engine) {
                GtkThemeEngine *engine;
 
@@ -3160,20 +3235,20 @@ static void compose_exec_ext_editor(Compose *compose)
                close(pipe_fds[0]);
 
                if (compose_write_body_to_file(compose, tmp) < 0) {
-                       sock_write(pipe_fds[1], "2\n", 2);
+                       fd_write(pipe_fds[1], "2\n", 2);
                        _exit(1);
                }
 
                pid_ed = compose_exec_ext_editor_real(tmp);
                if (pid_ed < 0) {
-                       sock_write(pipe_fds[1], "1\n", 2);
+                       fd_write(pipe_fds[1], "1\n", 2);
                        _exit(1);
                }
 
                /* wait until editor is terminated */
                waitpid(pid_ed, NULL, 0);
 
-               sock_write(pipe_fds[1], "0\n", 2);
+               fd_write(pipe_fds[1], "0\n", 2);
 
                close(pipe_fds[1]);
                _exit(0);
@@ -3293,14 +3368,14 @@ static void compose_input_cb(gpointer data, gint source,
        waitpid(compose->exteditor_pid, NULL, 0);
 
        if (buf[0] == '0') {            /* success */
-               GtkText *text = GTK_TEXT(compose->text);
+               GtkSText *text = GTK_STEXT(compose->text);
 
-               gtk_text_freeze(text);
-               gtk_text_set_point(text, 0);
-               gtk_text_forward_delete(text, gtk_text_get_length(text));
+               gtk_stext_freeze(text);
+               gtk_stext_set_point(text, 0);
+               gtk_stext_forward_delete(text, gtk_stext_get_length(text));
                compose_insert_file(compose, compose->exteditor_file);
                compose_changed_cb(NULL, compose);
-               gtk_text_thaw(text);
+               gtk_stext_thaw(text);
 
                if (unlink(compose->exteditor_file) < 0)
                        FILE_OP_ERROR(compose->exteditor_file, "unlink");
@@ -3352,7 +3427,7 @@ static void compose_set_ext_editor_sensitive(Compose *compose,
        gtk_widget_set_sensitive(compose->linewrap_btn,  sensitive);
 }
 
-static gint calc_cursor_xpos(GtkText *text, gint extra, gint char_width)
+static gint calc_cursor_xpos(GtkSText *text, gint extra, gint char_width)
 {
        gint cursor_pos;
 
@@ -3384,7 +3459,7 @@ static gboolean compose_edit_size_alloc(GtkEditable *widget,
                /* got the maximum */
                gtk_ruler_set_range(GTK_RULER(shruler),
                                    0.0, line_width_in_chars,
-                                   calc_cursor_xpos(GTK_TEXT(widget),
+                                   calc_cursor_xpos(GTK_STEXT(widget),
                                                     allocation->x,
                                                     char_width),
                                    /*line_width_in_chars*/ char_width);
@@ -3720,7 +3795,7 @@ static void compose_changed_cb(GtkEditable *editable, Compose *compose)
 static void compose_button_press_cb(GtkWidget *widget, GdkEventButton *event,
                                    Compose *compose)
 {
-       gtk_text_set_point(GTK_TEXT(widget),
+       gtk_stext_set_point(GTK_STEXT(widget),
                           gtk_editable_get_position(GTK_EDITABLE(widget)));
 }
 
@@ -3728,7 +3803,7 @@ static void compose_button_press_cb(GtkWidget *widget, GdkEventButton *event,
 static void compose_key_press_cb(GtkWidget *widget, GdkEventKey *event,
                                 Compose *compose)
 {
-       gtk_text_set_point(GTK_TEXT(widget),
+       gtk_stext_set_point(GTK_STEXT(widget),
                           gtk_editable_get_position(GTK_EDITABLE(widget)));
 }
 #endif