0.9.5claws19
[claws.git] / src / compose.c
index 8910d1043c6c9251d2dda2c79763e91bcc19abaf..2e5dcb012bd9916885116bf7ebc6fdec57c0cb27 100644 (file)
@@ -415,6 +415,8 @@ static void activate_gnupg_mode     (Compose *compose,
 #endif
 static void compose_toggle_return_receipt_cb(gpointer data, guint action,
                                             GtkWidget *widget);
+static void compose_toggle_remove_refs_cb(gpointer data, guint action,
+                                            GtkWidget *widget);
 static void compose_set_priority_cb    (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
@@ -482,6 +484,7 @@ static void compose_check_forwards_go          (Compose *compose);
 #endif
 
 static gboolean compose_send_control_enter     (Compose        *compose);
+static gint compose_defer_auto_save_draft      (Compose        *compose);
 
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
@@ -657,6 +660,7 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Message/Priority/_Lowest"),  NULL, compose_set_priority_cb, PRIORITY_LOWEST, "/Message/Priority/Highest"},
        {N_("/_Message/---"),           NULL,           NULL,   0, "<Separator>"},
        {N_("/_Message/_Request Return Receipt"),       NULL, compose_toggle_return_receipt_cb, 0, "<ToggleItem>"},
+       {N_("/_Message/Remo_ve references"),    NULL, compose_toggle_remove_refs_cb, 0, "<ToggleItem>"},
        {N_("/_Tools"),                 NULL, NULL, 0, "<Branch>"},
        {N_("/_Tools/Show _ruler"),     NULL, compose_toggle_ruler_cb, 0, "<ToggleItem>"},
        {N_("/_Tools/_Address book"),   "<shift><control>A", compose_address_cb , 0, NULL},
@@ -705,6 +709,13 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        text = GTK_STEXT(compose->text);
        gtk_stext_freeze(text);
 
+#ifdef USE_ASPELL
+       if (item && item->prefs && item->prefs->enable_default_dictionary &&
+           compose->gtkaspell) 
+               gtkaspell_change_dict(compose->gtkaspell, 
+                   item->prefs->default_dictionary);
+#endif
+
        if (account->auto_sig)
                compose_insert_sig(compose, FALSE);
        gtk_editable_set_position(GTK_EDITABLE(text), 0);
@@ -900,6 +911,7 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                                  gboolean followup_and_reply_to,
                                  const gchar *body)
 {
+       GtkItemFactory *ifactory;
        Compose *compose;
        PrefsAccount *account = NULL;
        PrefsAccount *reply_account;
@@ -924,17 +936,17 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                reply_account = account;
 
        compose = compose_create(account, COMPOSE_REPLY);
+       ifactory = gtk_item_factory_from_widget(compose->menubar);
+
+       menu_set_toggle(ifactory, "/Message/Remove references", FALSE);
+       menu_set_sensitive(ifactory, "/Message/Remove references", TRUE);
 
        compose->replyinfo = procmsg_msginfo_get_full_info(msginfo);
        if (!compose->replyinfo)
                compose->replyinfo = procmsg_msginfo_copy(msginfo);
 
-       if (msginfo->folder && msginfo->folder->ret_rcpt) {
-               GtkItemFactory *ifactory;
-       
-               ifactory = gtk_item_factory_from_widget(compose->menubar);
+       if (msginfo->folder && msginfo->folder->ret_rcpt)
                menu_set_toggle(ifactory, "/Message/Request Return Receipt", TRUE);
-       }
 
        /* Set save folder */
        if (msginfo->folder && msginfo->folder->prefs && msginfo->folder->prefs->save_copy_to_folder) {
@@ -954,18 +966,26 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        text = GTK_STEXT(compose->text);
        gtk_stext_freeze(text);
 
+#ifdef USE_ASPELL
+       if (msginfo->folder && msginfo->folder->prefs && 
+           msginfo->folder->prefs && 
+           msginfo->folder->prefs->enable_default_dictionary &&
+           compose->gtkaspell)
+               gtkaspell_change_dict(compose->gtkaspell, 
+                   msginfo->folder->prefs->default_dictionary);
+#endif
+
        if (quote) {
                gchar *qmark;
-               gchar *quote_str;
 
                if (prefs_common.quotemark && *prefs_common.quotemark)
                        qmark = prefs_common.quotemark;
                else
                        qmark = "> ";
 
-               quote_str = compose_quote_fmt(compose, compose->replyinfo,
-                                             prefs_common.quotefmt,
-                                             qmark, body);
+               compose_quote_fmt(compose, compose->replyinfo,
+                                 prefs_common.quotefmt,
+                                 qmark, body);
        }
 
        if (account->auto_sig)
@@ -1035,48 +1055,54 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                compose->fwdinfo = procmsg_msginfo_copy(msginfo);
 
        if (msginfo->subject && *msginfo->subject) {
-               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), "Fw: ");
-               gtk_entry_append_text(GTK_ENTRY(compose->subject_entry),
-                                     msginfo->subject);
+               gchar *buf, *buf2, *p;
+
+               buf = p = g_strdup(msginfo->subject);
+               p += subject_get_prefix_length(p);
+               memmove(buf, p, strlen(p) + 1);
+
+               buf2 = g_strdup_printf("Fw: %s", buf);
+               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf2);
+               
+               g_free(buf);
+               g_free(buf2);
        }
 
        text = GTK_STEXT(compose->text);
        gtk_stext_freeze(text);
 
+       if (as_attach) {
+               gchar *msgfile;
 
-               if (as_attach) {
-                       gchar *msgfile;
-
-                       msgfile = procmsg_get_message_file_path(msginfo);
-                       if (!is_file_exist(msgfile))
-                               g_warning("%s: file not exist\n", msgfile);
-                       else
-                               compose_attach_append(compose, msgfile, msgfile,
-                                                     "message/rfc822");
+               msgfile = procmsg_get_message_file_path(msginfo);
+               if (!is_file_exist(msgfile))
+                       g_warning("%s: file not exist\n", msgfile);
+               else
+                       compose_attach_append(compose, msgfile, msgfile,
+                                             "message/rfc822");
 
-                       g_free(msgfile);
-               } else {
-                       gchar *qmark;
-                       gchar *quote_str;
-                       MsgInfo *full_msginfo;
+               g_free(msgfile);
+       } else {
+               gchar *qmark;
+               MsgInfo *full_msginfo;
 
-                       full_msginfo = procmsg_msginfo_get_full_info(msginfo);
-                       if (!full_msginfo)
-                               full_msginfo = procmsg_msginfo_copy(msginfo);
+               full_msginfo = procmsg_msginfo_get_full_info(msginfo);
+               if (!full_msginfo)
+                       full_msginfo = procmsg_msginfo_copy(msginfo);
 
-                       if (prefs_common.fw_quotemark &&
-                           *prefs_common.fw_quotemark)
-                               qmark = prefs_common.fw_quotemark;
-                       else
-                               qmark = "> ";
+               if (prefs_common.fw_quotemark &&
+                   *prefs_common.fw_quotemark)
+                       qmark = prefs_common.fw_quotemark;
+               else
+                       qmark = "> ";
 
-                       quote_str = compose_quote_fmt(compose, full_msginfo,
-                                                     prefs_common.fw_quotefmt,
-                                                     qmark, body);
-                       compose_attach_parts(compose, msginfo);
+               compose_quote_fmt(compose, full_msginfo,
+                                 prefs_common.fw_quotefmt,
+                                 qmark, body);
+               compose_attach_parts(compose, msginfo);
 
-                       procmsg_msginfo_free(full_msginfo);
-               }
+               procmsg_msginfo_free(full_msginfo);
+       }
 
        if (account->auto_sig)
                compose_insert_sig(compose, FALSE);
@@ -1277,7 +1303,8 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
        g_return_val_if_fail(msginfo != NULL, NULL);
 
        if (!account)
-               account = cur_account;
+               account = account_get_reply_account(msginfo,
+                                       prefs_common.reply_account_autosel);
        g_return_val_if_fail(account != NULL, NULL);
 
        compose = compose_create(account, COMPOSE_REDIRECT);
@@ -1673,7 +1700,7 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
        gchar *buf;
        gchar *p, *lastp;
        gint len;
-       gchar *trimmed_body = body;
+       const gchar *trimmed_body = body;
        
        if (!msginfo)
                msginfo = &dummyinfo;
@@ -1789,15 +1816,13 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
        if (msginfo->subject && *msginfo->subject) {
                gchar *buf, *buf2, *p;
 
-               buf = g_strdup(msginfo->subject);
-               while (!strncasecmp(buf, "Re:", 3)) {
-                       p = buf + 3;
-                       while (isspace(*p)) p++;
-                       memmove(buf, p, strlen(p) + 1);
-               }
+               buf = p = g_strdup(msginfo->subject);
+               p += subject_get_prefix_length(p);
+               memmove(buf, p, strlen(p) + 1);
 
                buf2 = g_strdup_printf("Re: %s", buf);
                gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf2);
+
                g_free(buf2);
                g_free(buf);
        } else
@@ -1852,6 +1877,7 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                slist_free_strings(cc_list);
                g_slist_free(cc_list);
        }
+
 }
 
 #define SET_ENTRY(entry, str) \
@@ -1893,6 +1919,7 @@ static void compose_insert_sig(Compose *compose, gboolean replace)
 {
        GtkSText *text = GTK_STEXT(compose->text);
        gint cur_pos;
+       gint len;
 
        g_return_if_fail(compose->account != NULL);
 
@@ -1900,39 +1927,32 @@ static void compose_insert_sig(Compose *compose, gboolean replace)
 
        gtk_stext_freeze(text);
 
+       if (replace) {
+               len = gtk_stext_get_length(text);
+               gtk_stext_set_point(text, len);
+       }
+
        if (replace && compose->sig_str) {
-               gchar *tmp;
                gint pos;
-               gint len;
 
-               if (compose->account->sig_sep)
-                       tmp = g_strconcat(compose->account->sig_sep, "\n",
-                                         compose->sig_str, NULL);
+               if (compose->sig_str[0] == '\0')
+                       pos = -1;
                else
-                       tmp = g_strdup(compose->sig_str);
+                       pos = gtkut_stext_find(text, 0, compose->sig_str, TRUE);
 
-               pos = gtkut_stext_find(text, 0, tmp, TRUE);
                if (pos != -1) {
-                       gtk_stext_set_point(text, pos);
-                       len = get_wcs_len(tmp);
-                       gtk_stext_forward_delete(text, len);
-               } else {
-                       len = gtk_stext_get_length(text);
-                       gtk_stext_set_point(text, len);
+                       len = get_mbs_len(compose->sig_str);
+                       if (len >= 0) {
+                               gtk_stext_set_point(text, pos);
+                               gtk_stext_forward_delete(text, len);
+                       }
                }
-
-               g_free(tmp);
-       } else
-               gtk_stext_insert(text, NULL, NULL, NULL, "\n\n", 2);
-
-       if (compose->account->sig_sep) {
-               gtk_stext_insert(text, NULL, NULL, NULL, 
-                                compose->account->sig_sep, -1);
-               gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
        }
 
        g_free(compose->sig_str);
        compose->sig_str = compose_get_signature_str(compose);
+       if (!compose->sig_str || (replace && !compose->account->auto_sig))
+               compose->sig_str = g_strdup("");
 
        gtk_stext_insert(text, NULL, NULL, NULL, compose->sig_str, -1);
 
@@ -1947,41 +1967,42 @@ static void compose_insert_sig(Compose *compose, gboolean replace)
 
 static gchar *compose_get_signature_str(Compose *compose)
 {
-       static gchar *default_sigfile;
-       gchar *sig_file = NULL;
+       gchar *sig_body = NULL;
        gchar *sig_str = NULL;
 
        g_return_val_if_fail(compose->account != NULL, NULL);
 
-       if (compose->account->sig_type == SIG_FILE) {
-               if (compose->account->sig_path)
-                       sig_file = compose->account->sig_path;
-               else {
-                       if (!default_sigfile)
-                               default_sigfile = g_strconcat
-                                       (get_home_dir(), G_DIR_SEPARATOR_S,
-                                        DEFAULT_SIGNATURE, NULL);
-                       sig_file = default_sigfile;
-               }
+       if (!compose->account->sig_path)
+               return NULL;
 
-               if (!is_file_or_fifo_exist(sig_file)) {
-                       g_warning("can't open signature file: %s\n", sig_file);
+       if (compose->account->sig_type == SIG_FILE) {
+               if (!is_file_or_fifo_exist(compose->account->sig_path)) {
+                       g_warning("can't open signature file: %s\n",
+                                 compose->account->sig_path);
                        return NULL;
                }
        }
 
-       if (compose->account->sig_type == SIG_COMMAND) {
-               if (compose->account->sig_path)
-                       sig_str = get_command_output
-                               (compose->account->sig_path);
-       } else {
+       if (compose->account->sig_type == SIG_COMMAND)
+               sig_body = get_command_output(compose->account->sig_path);
+       else {
                gchar *tmp;
 
-               tmp = file_read_to_str(sig_file);
-               sig_str = normalize_newlines(tmp);
+               tmp = file_read_to_str(compose->account->sig_path);
+               if (!tmp)
+                       return NULL;
+               sig_body = normalize_newlines(tmp);
                g_free(tmp);
        }
 
+       if (compose->account->sig_sep)
+               sig_str = g_strconcat("\n\n", compose->account->sig_sep, "\n", sig_body,
+                                     NULL);
+       else
+               sig_str = g_strconcat("\n\n", sig_body, NULL);
+
+       g_free(sig_body);
+       
        return sig_str;
 }
 
@@ -2064,13 +2085,24 @@ static void compose_attach_append(Compose *compose, const gchar *file,
        if (content_type) {
                ainfo->content_type = g_strdup(content_type);
                if (!strcasecmp(content_type, "message/rfc822")) {
+                       MsgInfo *msginfo;
+                       MsgFlags flags = {0, 0};
+                       gchar *name;
+
                        if (procmime_get_encoding_for_file(file) == ENC_7BIT)
                                ainfo->encoding = ENC_7BIT;
                        else
                                ainfo->encoding = ENC_8BIT;
-                       ainfo->name = g_strdup_printf
-                               (_("Message: %s"),
-                                g_basename(filename ? filename : file));
+
+                       msginfo = procheader_parse_file(file, flags, FALSE, FALSE);
+                       if (msginfo && msginfo->subject)
+                               name = msginfo->subject;
+                       else
+                               name = g_basename(filename ? filename : file);
+
+                       ainfo->name = g_strdup_printf(_("Message: %s"), name);
+
+                       procmsg_msginfo_free(msginfo);
                } else {
                        if (!g_strncasecmp(content_type, "text", 4))
                                ainfo->encoding =
@@ -2139,7 +2171,7 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
                        child = procmime_mimeinfo_next(child);
                        continue;
                }
-               if(child->parent && child->parent->parent
+               if (child->parent && child->parent->parent
                && !strcasecmp(child->parent->parent->content_type, "multipart/signed")
                && child->mime_type == MIME_TEXT) {
                        /* this is the main text part of a signed message */
@@ -2383,6 +2415,10 @@ static guint get_indent_length(GtkSText *text, guint start_pos, guint text_len)
        gboolean is_space;
        gboolean is_indent;
 
+       if (prefs_common.quote_chars == NULL) {
+               return 0 ;
+       }
+
        for (i = start_pos; i < text_len; i++) {
                GET_CHAR(i, cbuf, ch_len);
                if (ch_len > 1)
@@ -2696,7 +2732,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                        STEXT_FREEZE();
                        gtk_stext_set_point(text, line_pos);
                        gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
-                       /* gtk_stext_compact_buffer(text); */
+                       gtk_stext_compact_buffer(text);
                        tlen++;
                        line_pos++;
                        /* for loop will increase it */
@@ -2883,7 +2919,7 @@ static void compose_select_account(Compose *compose, PrefsAccount *account,
        activate_gnupg_mode(compose, account);          
 #endif /* USE_GPGME */
 
-       if (!init && account->auto_sig)
+       if (!init && compose->mode != COMPOSE_REDIRECT)
                compose_insert_sig(compose, TRUE);
 }
 
@@ -2979,6 +3015,8 @@ gint compose_send(Compose *compose)
        g_free(msgpath);
 
        folder_item_remove_msg(folder, msgnum);
+       
+       folder_item_scan(folder);
 
        return val;
 }
@@ -3098,8 +3136,9 @@ gint compose_send(Compose *compose)
 }
 #endif
 
-static gboolean compose_use_attach(Compose *compose) {
-    return(gtk_clist_get_row_data(GTK_CLIST(compose->attach_clist), 0) != NULL);
+static gboolean compose_use_attach(Compose *compose) 
+{
+       return gtk_clist_get_row_data(GTK_CLIST(compose->attach_clist), 0) != NULL;
 }
 
 static gint compose_redirect_write_headers_from_headerlist(Compose *compose, 
@@ -3483,6 +3522,10 @@ static gint compose_write_to_file(Compose *compose, const gchar *file,
                fprintf(fp, "\n--%s\n", compose->boundary);
                fprintf(fp, "Content-Type: text/plain; charset=%s\n",
                        out_codeset);
+#if USE_GPGME
+               if (compose->use_signing && !compose->gnupg_mode)
+                       fprintf(fp, "Content-Disposition: inline\n");
+#endif
                fprintf(fp, "Content-Transfer-Encoding: %s\n",
                        procmime_get_encoding_str(encoding));
                fputc('\n', fp);
@@ -3657,6 +3700,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        GSList *cur;
        gchar buf[BUFFSIZE];
        gint num;
+       MsgFlags flag = {0, 0};
         static gboolean lock = FALSE;
        PrefsAccount *mailac = NULL, *newsac = NULL;
        
@@ -3845,7 +3889,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                return -1;
        }
        folder_item_scan(queue);
-       if ((num = folder_item_add_msg(queue, tmp, TRUE)) < 0) {
+       if ((num = folder_item_add_msg(queue, tmp, NULL, TRUE)) < 0) {
                g_warning("can't queue the message\n");
                unlink(tmp);
                g_free(tmp);
@@ -3941,8 +3985,7 @@ static void compose_write_attach(Compose *compose, FILE *fp)
 
 #define QUOTE_IF_REQUIRED(out, str)                    \
 {                                                      \
-       if (*str != '"' && (strchr(str, ',')            \
-                       || strchr(str, '.'))) {         \
+       if (*str != '"' && strpbrk(str, ",.[]<>")) {    \
                gchar *__tmp;                           \
                gint len;                               \
                                                        \
@@ -3977,14 +4020,15 @@ static void compose_write_attach(Compose *compose, FILE *fp)
 
 static gint compose_write_headers_from_headerlist(Compose *compose, 
                                                  FILE *fp, 
-                                                 gchar *header)
+                                                 const gchar *header,
+                                                 const gchar *seperator)
 {
-       gchar buf[BUFFSIZE];
        gchar *str, *header_w_colon, *trans_hdr;
-       gboolean first_address;
+       gboolean write_header = FALSE;
        GSList *list;
        ComposeHeaderEntry *headerentry;
        gchar * headerentryname;
+       GString *headerstr;
 
        if (IS_IN_CUSTOM_HEADER(header)) {
                return 0;
@@ -3992,10 +4036,11 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
 
        debug_print("Writing %s-header\n", header);
 
+       headerstr = g_string_sized_new(64);
+
        header_w_colon = g_strconcat(header, ":", NULL);
        trans_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
 
-       first_address = TRUE;
        for (list = compose->header_list; list; list = list->next) {
                headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
@@ -4005,24 +4050,26 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
                        Xstrdup_a(str, str, return -1);
                        g_strstrip(str);
                        if (str[0] != '\0') {
-                               compose_convert_header
-                                       (buf, sizeof(buf), str,
-                                       strlen(header) + 2, TRUE);
-                               if (first_address) {
-                                       fprintf(fp, "%s: ", header);
-                                       first_address = FALSE;
-                               } else {
-                                       fprintf(fp, ",");
-                               }
-                               fprintf(fp, "%s", buf);
+                               g_string_append(headerstr, str);
+                               if (write_header)
+                                       g_string_append(headerstr, seperator);
+                               write_header = TRUE;
                        }
                }
        }
-       if (!first_address) {
-               fprintf(fp, "\n");
+       if (write_header) {
+               gchar *buf;
+
+               buf = g_new0(gchar, headerstr->len * 2);
+               compose_convert_header
+                       (buf, headerstr->len * 2, headerstr->str,
+                       strlen(header) + 2, TRUE);
+               fprintf(fp, "%s: %s\n", header, buf);
+               g_free(buf);
        }
 
        g_free(header_w_colon);
+       g_string_free(headerstr, TRUE);
 
        return(0);
 }
@@ -4078,7 +4125,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
        
        /* To */
-       compose_write_headers_from_headerlist(compose, fp, "To");
+       compose_write_headers_from_headerlist(compose, fp, "To", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_to) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->to_entry));
@@ -4087,7 +4134,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
 #endif
 
        /* Newsgroups */
-       compose_write_headers_from_headerlist(compose, fp, "Newsgroups");
+       compose_write_headers_from_headerlist(compose, fp, "Newsgroups", ",");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_newsgroups) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->newsgroups_entry));
@@ -4108,7 +4155,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 #endif
        /* Cc */
-       compose_write_headers_from_headerlist(compose, fp, "Cc");
+       compose_write_headers_from_headerlist(compose, fp, "Cc", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_cc) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->cc_entry));
@@ -4116,7 +4163,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 #endif
        /* Bcc */
-       compose_write_headers_from_headerlist(compose, fp, "Bcc");
+       compose_write_headers_from_headerlist(compose, fp, "Bcc", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_bcc) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->bcc_entry));
@@ -4143,16 +4190,18 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                compose->msgid = g_strdup(buf);
        }
 
-       /* 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 (compose->remove_references == FALSE) {
+               /* 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);
+       }
 
        /* Followup-To */
-       compose_write_headers_from_headerlist(compose, fp, "Followup-To");
+       compose_write_headers_from_headerlist(compose, fp, "Followup-To", ",");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_followupto && !IS_IN_CUSTOM_HEADER("Followup-To")) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->followup_entry));
@@ -4170,7 +4219,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 #endif
        /* Reply-To */
-       compose_write_headers_from_headerlist(compose, fp, "Reply-To");
+       compose_write_headers_from_headerlist(compose, fp, "Reply-To", ", ");
 #if 0 /* NEW COMPOSE GUI */
        if (compose->use_replyto && !IS_IN_CUSTOM_HEADER("Reply-To")) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->reply_entry));
@@ -4244,16 +4293,16 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        /* MIME */
        fprintf(fp, "Mime-Version: 1.0\n");
        if (compose_use_attach(compose)) {
-               get_rfc822_date(buf, sizeof(buf));
-               subst_char(buf, ' ', '_');
-               subst_char(buf, ',', '_');
-               compose->boundary = g_strdup_printf("Multipart_%s_%08x",
-                                                   buf, (guint)compose);
+               compose->boundary = generate_mime_boundary(NULL);
                fprintf(fp,
                        "Content-Type: multipart/mixed;\n"
                        " boundary=\"%s\"\n", compose->boundary);
        } else {
                fprintf(fp, "Content-Type: text/plain; charset=%s\n", charset);
+#if USE_GPGME
+               if (compose->use_signing && !compose->gnupg_mode)
+                       fprintf(fp, "Content-Disposition: inline\n");
+#endif
                fprintf(fp, "Content-Transfer-Encoding: %s\n",
                        procmime_get_encoding_str(encoding));
        }
@@ -4306,6 +4355,11 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                headerentry = ((ComposeHeaderEntry *)list->data);
                
                tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry)));
+               if (strchr(tmp, ' ') != NULL || strchr(tmp, '\r') != NULL || strchr(tmp, '\n') != NULL) {
+                       g_free(tmp);
+                       continue;
+               }
+
                if (!strstr(tmp, ":")) {
                        headername_wcolon = g_strconcat(tmp, ":", NULL);
                        headername = g_strdup(tmp);
@@ -4316,6 +4370,8 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                g_free(tmp);
                
                headervalue = gtk_entry_get_text(GTK_ENTRY(headerentry->entry));
+               subst_char(headervalue, '\r', ' ');
+               subst_char(headervalue, '\n', ' ');
                string = std_headers;
                while (*string != NULL) {
                        headername_trans = prefs_common.trans_hdr ? gettext(*string) : *string;
@@ -4327,8 +4383,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                        fprintf(fp, "%s %s\n", headername_wcolon, headervalue);
                                
                g_free(headername);
-               g_free(headername_wcolon);
-               
+               g_free(headername_wcolon);              
        }
 
        /* separator between header and body */
@@ -4347,6 +4402,8 @@ static void compose_convert_header(gchar *dest, gint len, gchar *src,
 
        if (len < 1) return;
 
+       subst_char(src, '\n', ' ');
+       subst_char(src, '\r', ' ');
        g_strchomp(src);
 
        conv_encode_header(dest, len, src, header_len, addr_field);
@@ -4978,6 +5035,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        ifactory = gtk_item_factory_from_widget(menubar);
        menu_set_sensitive(ifactory, "/Edit/Undo", FALSE);
        menu_set_sensitive(ifactory, "/Edit/Redo", FALSE);
+       menu_set_sensitive(ifactory, "/Message/Remove references", FALSE);
 
        tmpl_menu = gtk_item_factory_get_item(ifactory, "/Tools/Template");
 #if 0 /* NEW COMPOSE GUI */
@@ -5081,29 +5139,35 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        if (mode != COMPOSE_REDIRECT) {
                if (prefs_common.enable_aspell && prefs_common.dictionary &&
                    strcmp(prefs_common.dictionary, _("None"))) {
-                       gtkaspell = gtkaspell_new((const gchar*)prefs_common.dictionary,
+                       gtkaspell = gtkaspell_new(prefs_common.aspell_path,
+                                                 prefs_common.dictionary,
                                                  conv_get_current_charset_str(),
                                                  prefs_common.misspelled_col,
                                                  prefs_common.check_while_typing,
                                                  prefs_common.use_alternate,
                                                  GTK_STEXT(text));
                        if (!gtkaspell) {
-                               alertpanel_error(_("Spell checker could not be started.\n%s"), gtkaspellcheckers->error_message);
+                               alertpanel_error(_("Spell checker could not "
+                                               "be started.\n%s"),
+                                               gtkaspell_checkers_strerror());
                                gtkaspell_checkers_reset_error();
                        } else {
 
                                GtkWidget *menuitem;
 
-                               if (!gtkaspell_set_sug_mode(gtkaspell, prefs_common.aspell_sugmode)) {
-                                       debug_print("Aspell: could not set suggestion mode %s\n",
-                                       gtkaspellcheckers->error_message);
+                               if (!gtkaspell_set_sug_mode(gtkaspell,
+                                               prefs_common.aspell_sugmode)) {
+                                       debug_print("Aspell: could not set "
+                                                   "suggestion mode %s\n",
+                                                   gtkaspell_checkers_strerror());
                                        gtkaspell_checkers_reset_error();
                                }
 
-                               menuitem = gtk_item_factory_get_item(ifactory, "/Spelling/Spelling Configuration");
+                               menuitem = gtk_item_factory_get_item(ifactory,
+                                       "/Spelling/Spelling Configuration");
                                gtkaspell_populate_submenu(gtkaspell, menuitem);
                                menu_set_sensitive(ifactory, "/Spelling", TRUE);
-                               }
+                       }
                }
        }
 #endif
@@ -6178,7 +6242,9 @@ static void compose_allow_user_actions (Compose *compose, gboolean allow)
        toolbar_comp_set_sensitive(compose, allow);
        menu_set_sensitive(ifactory, "/File", allow);
        menu_set_sensitive(ifactory, "/Edit", allow);
+#if USE_ASPELL
        menu_set_sensitive(ifactory, "/Spelling", allow);
+#endif 
        menu_set_sensitive(ifactory, "/Message", allow);
        menu_set_sensitive(ifactory, "/Tools", allow);
        menu_set_sensitive(ifactory, "/Help", allow);
@@ -6225,6 +6291,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        FolderItem *draft;
        gchar *tmp;
        gint msgnum;
+       MsgFlags flag = {0, 0};
        static gboolean lock = FALSE;
        MsgInfo *newmsginfo;
        
@@ -6244,7 +6311,8 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                return;
        }
 
-       if ((msgnum = folder_item_add_msg(draft, tmp, TRUE)) < 0) {
+       folder_item_scan(draft);
+       if ((msgnum = folder_item_add_msg(draft, tmp, &flag, TRUE)) < 0) {
                unlink(tmp);
                g_free(tmp);
                lock = FALSE;
@@ -6264,6 +6332,8 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                procmsg_msginfo_free(newmsginfo);
        }
        
+       folder_item_scan(draft);
+       
        lock = FALSE;
 
        /* 0: quit editing  1: keep editing  2: keep editing (autosave) */
@@ -6866,6 +6936,17 @@ static void compose_toggle_return_receipt_cb(gpointer data, guint action,
                compose->return_receipt = FALSE;
 }
 
+static void compose_toggle_remove_refs_cb(gpointer data, guint action,
+                                            GtkWidget *widget)
+{
+       Compose *compose = (Compose *)data;
+
+       if (GTK_CHECK_MENU_ITEM(widget)->active)
+               compose->remove_references = TRUE;
+       else
+               compose->remove_references = FALSE;
+}
+
 void compose_headerentry_key_press_event_cb(GtkWidget *entry,
                                            GdkEventKey *event,
                                            ComposeHeaderEntry *headerentry)
@@ -6971,10 +7052,15 @@ static void text_inserted(GtkWidget *widget, const gchar *text,
                                           compose);
        gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert_text");
 
-       
        if (prefs_common.autosave && 
            gtk_stext_get_length(GTK_STEXT(widget)) % prefs_common.autosave_length == 0)
-               compose_draft_cb((gpointer)compose, 2, NULL);
+               gtk_timeout_add(500, (GtkFunction) compose_defer_auto_save_draft, compose);
+}
+
+static gint compose_defer_auto_save_draft(Compose *compose)
+{
+       compose_draft_cb((gpointer)compose, 2, NULL);
+       return FALSE;
 }
 
 static gboolean compose_send_control_enter(Compose *compose)