2006-06-24 [paul] 2.3.1cvs17
[claws.git] / src / compose.c
index f28a940646c07e8e6b645a2af1994bf49d106ff6..b91b9521c14f56523ae007366b229c008890d40a 100644 (file)
@@ -265,21 +265,19 @@ static gboolean compose_check_entries             (Compose        *compose,
                                                 gboolean       check_subject);
 static gint compose_write_to_file              (Compose        *compose,
                                                 FILE           *fp,
-                                                gint            action);
+                                                gint            action,
+                                                gboolean        attach_parts);
 static gint compose_write_body_to_file         (Compose        *compose,
                                                 const gchar    *file);
 static gint compose_remove_reedit_target       (Compose        *compose,
                                                 gboolean        force);
 void compose_remove_draft                      (Compose        *compose);
-static gint compose_queue                      (Compose        *compose,
-                                                gint           *msgnum,
-                                                FolderItem     **item,
-                                                gchar          **msgpath);
 static gint compose_queue_sub                  (Compose        *compose,
                                                 gint           *msgnum,
                                                 FolderItem     **item,
                                                 gchar          **msgpath,
-                                                gboolean       check_subject);
+                                                gboolean       check_subject,
+                                                gboolean       remove_reedit_target);
 static void compose_add_attachments            (Compose        *compose,
                                                 MimeInfo       *parent);
 static gchar *compose_get_header               (Compose        *compose);
@@ -506,8 +504,6 @@ static void compose_check_forwards_go          (Compose *compose);
 static gint compose_defer_auto_save_draft      (Compose        *compose);
 static PrefsAccount *compose_guess_forward_account_from_msginfo        (MsgInfo *msginfo);
 
-static gboolean compose_close  (Compose *compose);
-
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
        {N_("/_Add..."),        NULL, compose_attach_cb, 0, NULL},
@@ -1259,21 +1255,17 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                reply_account = account;
 
        compose = compose_create(account, COMPOSE_REPLY, FALSE);
+
+       compose->updating = TRUE;
+
        ifactory = gtk_item_factory_from_widget(compose->menubar);
 
        menu_set_active(ifactory, "/Options/Remove references", FALSE);
        menu_set_sensitive(ifactory, "/Options/Remove references", TRUE);
 
-       compose->updating = TRUE;
        compose->replyinfo = procmsg_msginfo_get_full_info(msginfo);
        if (!compose->replyinfo)
                compose->replyinfo = procmsg_msginfo_copy(msginfo);
-       compose->updating = FALSE;
-
-       if (compose->deferred_destroy) {
-               compose_destroy(compose);
-               return NULL;
-       }
 
        compose_extract_original_charset(compose);
        
@@ -1343,6 +1335,14 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                
        compose->modified = FALSE;
        compose_set_title(compose);
+
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
+
        return compose;
 }
 
@@ -1377,12 +1377,6 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
        compose->fwdinfo = procmsg_msginfo_get_full_info(msginfo);
        if (!compose->fwdinfo)
                compose->fwdinfo = procmsg_msginfo_copy(msginfo);
-       compose->updating = FALSE;
-
-       if (compose->deferred_destroy) {
-               compose_destroy(compose);
-               return NULL;
-       }
 
        compose_extract_original_charset(compose);
 
@@ -1420,16 +1414,9 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                gchar *qmark;
                MsgInfo *full_msginfo;
 
-               compose->updating = TRUE;
                full_msginfo = procmsg_msginfo_get_full_info(msginfo);
                if (!full_msginfo)
                        full_msginfo = procmsg_msginfo_copy(msginfo);
-               compose->updating = FALSE;
-
-               if (compose->deferred_destroy) {
-                       compose_destroy(compose);
-                       return NULL;
-               }
 
                if (prefs_common.fw_quotemark &&
                    *prefs_common.fw_quotemark)
@@ -1476,6 +1463,14 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
        
        compose->modified = FALSE;
        compose_set_title(compose);
+
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
+
         return compose;
 }
 
@@ -1515,20 +1510,16 @@ Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_list)
 
        compose = compose_create(account, COMPOSE_FORWARD, FALSE);
 
+       compose->updating = TRUE;
+
        textview = GTK_TEXT_VIEW(compose->text);
        textbuf = gtk_text_view_get_buffer(textview);
        compose_create_tags(textview, compose);
        
        undo_block(compose->undostruct);
        for (msginfo = msginfo_list; msginfo != NULL; msginfo = msginfo->next) {
-               compose->updating = TRUE;
                msgfile = procmsg_get_message_file_path((MsgInfo *)msginfo->data);
-               compose->updating = FALSE;
-               if (compose->deferred_destroy) {
-                       compose_destroy(compose);
-                       g_free(msgfile);
-                       return NULL;
-               }
+
                if (!is_file_exist(msgfile))
                        g_warning("%s: file not exist\n", msgfile);
                else
@@ -1573,6 +1564,14 @@ Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_list)
        undo_unblock(compose->undostruct);
        compose->modified = FALSE;
        compose_set_title(compose);
+
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
+
        return compose;
 }
 
@@ -1623,7 +1622,7 @@ static void compose_colorize_signature(Compose *compose)
                }
 }
 
-void compose_reedit(MsgInfo *msginfo)
+Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
 {
        Compose *compose = NULL;
        PrefsAccount *account = NULL;
@@ -1637,11 +1636,11 @@ void compose_reedit(MsgInfo *msginfo)
        gboolean use_encryption = FALSE;
        gchar *privacy_system = NULL;
 
-       g_return_if_fail(msginfo != NULL);
-       g_return_if_fail(msginfo->folder != NULL);
+       g_return_val_if_fail(msginfo != NULL, NULL);
+       g_return_val_if_fail(msginfo->folder != NULL, NULL);
 
        if (compose_put_existing_to_front(msginfo)) {
-               return;
+               return NULL;
        }
 
         if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
@@ -1703,9 +1702,12 @@ void compose_reedit(MsgInfo *msginfo)
         if (!account) {
                account = cur_account;
         }
-       g_return_if_fail(account != NULL);
+       g_return_val_if_fail(account != NULL, NULL);
 
-       compose = compose_create(account, COMPOSE_REEDIT, FALSE);
+       compose = compose_create(account, COMPOSE_REEDIT, batch);
+       
+       compose->updating = TRUE;
+       
        if (privacy_system != NULL) {
                compose->privacy_system = privacy_system;
                compose_use_signing(compose, use_signing);
@@ -1715,14 +1717,7 @@ void compose_reedit(MsgInfo *msginfo)
                activate_privacy_system(compose, account, FALSE);
        }
 
-       compose->updating = TRUE;
        compose->targetinfo = procmsg_msginfo_copy(msginfo);
-       compose->updating = FALSE;
-       
-       if (compose->deferred_destroy) {
-               compose_destroy(compose);
-               return;
-       }
 
        compose_extract_original_charset(compose);
 
@@ -1749,7 +1744,9 @@ void compose_reedit(MsgInfo *msginfo)
        }
        
        if (compose_parse_header(compose, msginfo) < 0) {
-               return;
+               compose->updating = FALSE;
+               compose_destroy(compose);
+               return NULL;
        }
        compose_reedit_set_entry(compose, msginfo);
 
@@ -1804,6 +1801,14 @@ void compose_reedit(MsgInfo *msginfo)
        }
        compose->modified = FALSE;
        compose_set_title(compose);
+
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
+       return compose;
 }
 
 Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
@@ -1822,6 +1827,9 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
        g_return_val_if_fail(account != NULL, NULL);
 
        compose = compose_create(account, COMPOSE_REDIRECT, batch);
+
+       compose->updating = TRUE;
+
        ifactory = gtk_item_factory_from_widget(compose->menubar);
        compose_create_tags(GTK_TEXT_VIEW(compose->text), compose);
        compose->replyinfo = NULL;
@@ -1831,18 +1839,14 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
 
        gtk_widget_grab_focus(compose->header_last->entry);
 
-       compose->updating = TRUE;
        filename = procmsg_get_message_file_path(msginfo);
-       compose->updating = FALSE;
 
-       if (compose->deferred_destroy) {
+       if (filename == NULL) {
+               compose->updating = FALSE;
                compose_destroy(compose);
-               g_free(filename);
-               return NULL;
-       }
 
-       if (filename == NULL)
                return NULL;
+       }
 
        compose->redirect_filename = filename;
        
@@ -1901,7 +1905,14 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
 
        compose->modified = FALSE;
        compose_set_title(compose);
-        return compose;
+       compose->updating = FALSE;
+
+       if (compose->deferred_destroy) {
+               compose_destroy(compose);
+               return NULL;
+       }
+       
+       return compose;
 }
 
 GList *compose_get_compose_list(void)
@@ -1953,7 +1964,7 @@ void compose_entry_append(Compose *compose, const gchar *address,
                        tmp[cur-begin]='\0';
                        cur++;
                        begin = cur;
-                       while (*tmp == ' ')
+                       while (*tmp == ' ' || *tmp == '\t')
                                tmp++;
                        compose_add_header_entry(compose, header, tmp);
                        g_free(o_tmp);
@@ -1967,7 +1978,7 @@ void compose_entry_append(Compose *compose, const gchar *address,
                tmp[cur-begin]='\0';
                cur++;
                begin = cur;
-               while (*tmp == ' ')
+               while (*tmp == ' ' || *tmp == '\t')
                        tmp++;
                compose_add_header_entry(compose, header, tmp);
                g_free(o_tmp);          
@@ -3936,6 +3947,9 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
                }
                if (!found_other) {
                        AlertValue aval;
+                       if (compose->batch) {
+                               gtk_widget_show_all(compose->window);
+                       }
                        aval = alertpanel(_("Send"),
                                          _("The only recipient is the default CC address. Send anyway?"),
                                          GTK_STOCK_CANCEL, _("+_Send"), NULL);
@@ -3964,6 +3978,9 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
                }
                if (!found_other) {
                        AlertValue aval;
+                       if (compose->batch) {
+                               gtk_widget_show_all(compose->window);
+                       }
                        aval = alertpanel(_("Send"),
                                          _("The only recipient is the default BCC address. Send anyway?"),
                                          GTK_STOCK_CANCEL, _("+_Send"), NULL);
@@ -3979,6 +3996,9 @@ static gboolean compose_check_entries(Compose *compose, gboolean check_subject)
        const gchar *str;
 
        if (compose_check_for_valid_recipient(compose) == FALSE) {
+               if (compose->batch) {
+                       gtk_widget_show_all(compose->window);
+               }
                alertpanel_error(_("Recipient is not specified."));
                return FALSE;
        }
@@ -4006,11 +4026,11 @@ static gboolean compose_check_entries(Compose *compose, gboolean check_subject)
 gint compose_send(Compose *compose)
 {
        gint msgnum;
-       FolderItem *folder;
+       FolderItem *folder = NULL;
        gint val = -1;
        gchar *msgpath = NULL;
        gboolean discard_window = FALSE;
-
+       gchar *errstr = NULL;
        if (prefs_common.send_dialog_mode != SEND_DIALOG_ALWAYS
                        || compose->batch == TRUE)
                discard_window = TRUE;
@@ -4025,7 +4045,7 @@ gint compose_send(Compose *compose)
                goto bail;
        }
 
-       val = compose_queue(compose, &msgnum, &folder, &msgpath);
+       val = compose_queue(compose, &msgnum, &folder, &msgpath, TRUE);
 
        if (val) {
                if (compose->batch) {
@@ -4036,7 +4056,7 @@ gint compose_send(Compose *compose)
                                           "Charset conversion failed."));
                } else if (val == -3) {
                        alertpanel_error(_("Could not queue message for sending:\n\n"
-                                          "Signature failed."));
+                                          "Signature failed: %s"), privacy_get_error());
                } else if (val == -2 && errno != 0) {
                        alertpanel_error(_("Could not queue message for sending:\n\n%s."), strerror(errno));
                } else {
@@ -4065,10 +4085,10 @@ gint compose_send(Compose *compose)
        
        if (msgpath == NULL) {
                msgpath = folder_item_fetch_msg(folder, msgnum);
-               val = procmsg_send_message_queue(msgpath);
+               val = procmsg_send_message_queue(msgpath, &errstr);
                g_free(msgpath);
        } else {
-               val = procmsg_send_message_queue(msgpath);
+               val = procmsg_send_message_queue(msgpath, &errstr);
                g_unlink(msgpath);
                g_free(msgpath);
        }
@@ -4087,9 +4107,17 @@ gint compose_send(Compose *compose)
                if (!discard_window)
                        compose_close(compose);
        } else {
-               alertpanel_error(_("The message was queued but could not be "
+               if (errstr) {
+                       gchar *tmp = g_strdup_printf(_("%s\nUse \"Send queued messages\" from "
+                                  "the main window to retry."), errstr);
+                       g_free(errstr);
+                       alertpanel_error_log(tmp);
+                       g_free(tmp);
+               } else {
+                       alertpanel_error_log(_("The message was queued but could not be "
                                   "sent.\nUse \"Send queued messages\" from "
                                   "the main window to retry."));
+               }
                if (!discard_window) {
                        goto bail;              
                }
@@ -4311,7 +4339,7 @@ error:
        return -1;
 }
 
-static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
+static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gboolean attach_parts)
 {
        GtkTextBuffer *buffer;
        GtkTextIter start, end;
@@ -4322,6 +4350,9 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
        MimeInfo *mimemsg, *mimetext;
        gint line;
 
+       if (action == COMPOSE_WRITE_FOR_SEND)
+               attach_parts = TRUE;
+
        /* create message MimeInfo */
        mimemsg = procmime_mimeinfo_new();
         mimemsg->type = MIMETYPE_MESSAGE;
@@ -4468,7 +4499,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
                procmime_encode_content(mimetext, encoding);
 
        /* append attachment parts */
-       if (compose_use_attach(compose)) {
+       if (compose_use_attach(compose) && attach_parts) {
                MimeInfo *mimempart;
                gchar *boundary = NULL;
                mimempart = procmime_mimeinfo_new();
@@ -4595,11 +4626,14 @@ void compose_remove_draft(Compose *compose)
 
 }
 
-static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item, gchar **msgpath)
+gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item, gchar **msgpath,
+                  gboolean remove_reedit_target)
 {
-       return compose_queue_sub (compose, msgnum, item, msgpath, FALSE);
+       return compose_queue_sub (compose, msgnum, item, msgpath, FALSE, remove_reedit_target);
 }
-static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item, gchar **msgpath, gboolean check_subject)
+static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item, 
+                             gchar **msgpath, gboolean check_subject,
+                             gboolean remove_reedit_target)
 {
        FolderItem *queue;
        gchar *tmp;
@@ -4616,6 +4650,9 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        
        if (compose_check_entries(compose, check_subject) == FALSE) {
                 lock = FALSE;
+               if (compose->batch) {
+                       gtk_widget_show_all(compose->window);
+               }
                 return -1;
        }
 
@@ -4653,6 +4690,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        if ((fp = g_fopen(tmp, "wb")) == NULL) {
                FILE_OP_ERROR(tmp, "fopen");
                g_free(tmp);
+               lock = FALSE;
                return -2;
        }
 
@@ -4764,7 +4802,9 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                fprintf(fp, "FMID:%s\t%d\t%s\n", folderid, compose->fwdinfo->msgnum, compose->fwdinfo->msgid);
                g_free(folderid);
        }
-       fprintf(fp, "\n");
+
+       /* end of headers */
+       fprintf(fp, "X-Sylpheed-End-Special-Headers: 1\n");
 
        if (compose->redirect_filename != NULL) {
                if (compose_redirect_write_to_file(compose, fp) < 0) {
@@ -4776,7 +4816,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                }
        } else {
                gint result = 0;
-               if ((result = compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_SEND)) < 0) {
+               if ((result = compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_SEND, TRUE)) < 0) {
                        lock = FALSE;
                        fclose(fp);
                        g_unlink(tmp);
@@ -4789,14 +4829,20 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                FILE_OP_ERROR(tmp, "fclose");
                g_unlink(tmp);
                g_free(tmp);
+               lock = FALSE;
                return -2;
        }
 
-       queue = account_get_special_folder(compose->account, F_QUEUE);
+       if (item && *item) {
+               queue = *item;
+       } else {
+               queue = account_get_special_folder(compose->account, F_QUEUE);
+       }
        if (!queue) {
                g_warning("can't find queue folder\n");
                g_unlink(tmp);
                g_free(tmp);
+               lock = FALSE;
                return -1;
        }
        folder_item_scan(queue);
@@ -4804,6 +4850,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                g_warning("can't queue the message\n");
                g_unlink(tmp);
                g_free(tmp);
+               lock = FALSE;
                return -1;
        }
        
@@ -4813,7 +4860,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        } else
                *msgpath = tmp;
 
-       if (compose->mode == COMPOSE_REEDIT) {
+       if (compose->mode == COMPOSE_REEDIT && remove_reedit_target) {
                compose_remove_reedit_target(compose, FALSE);
        }
 
@@ -4967,10 +5014,8 @@ static gchar *compose_get_header(Compose *compose)
        header = g_string_sized_new(64);
 
        /* Date */
-       if (compose->account->add_date) {
-               get_rfc822_date(buf, sizeof(buf));
-               g_string_append_printf(header, "Date: %s\n", buf);
-       }
+       get_rfc822_date(buf, sizeof(buf));
+       g_string_append_printf(header, "Date: %s\n", buf);
 
        /* From */
        
@@ -5366,8 +5411,6 @@ static void compose_add_header_entry(Compose *compose, gchar *header, gchar *tex
 
 static GtkWidget *compose_create_header(Compose *compose) 
 {
-       GtkWidget *label;
-       GtkWidget *hbox;
        GtkWidget *from_optmenu_hbox;
        GtkWidget *header_scrolledwin;
        GtkWidget *header_table;
@@ -5387,11 +5430,6 @@ static GtkWidget *compose_create_header(Compose *compose)
        count = 0;
 
        /* option menu for selecting accounts */
-       hbox = gtk_hbox_new(FALSE, 0);
-       label = gtk_label_new(prefs_common.trans_hdr ? _("From:") : "From:");
-       gtk_box_pack_end(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-       //gtk_table_attach(GTK_TABLE(header_table), hbox, 0, 1, count, count + 1,
-       //               GTK_FILL, 0, 2, 0);
        from_optmenu_hbox = compose_account_option_menu_create(compose);
        gtk_table_attach(GTK_TABLE(header_table), from_optmenu_hbox,
                                  0, 2, count, count + 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
@@ -5689,6 +5727,7 @@ static void compose_spell_menu_changed(void *data)
 }
 #endif
 
+static gboolean compose_force_window_origin = TRUE;
 static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
                                                 gboolean batch)
 {
@@ -5768,7 +5807,9 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        }
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL,
                                      &geometry, GDK_HINT_MIN_SIZE);
-       gtk_widget_set_uposition(window, prefs_common.compose_x, 
+       
+       if (compose_force_window_origin)
+               gtk_widget_set_uposition(window, prefs_common.compose_x, 
                                 prefs_common.compose_y);
 
        g_signal_connect(G_OBJECT(window), "delete_event",
@@ -6118,6 +6159,9 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
 
        hbox = gtk_hbox_new(FALSE, 6);
        from_name = gtk_entry_new();
+       
+       g_signal_connect_after(G_OBJECT(from_name), "grab_focus",
+                        G_CALLBACK(compose_grab_focus_cb), compose);
 
        for (; accounts != NULL; accounts = accounts->next, num++) {
                PrefsAccount *ac = (PrefsAccount *)accounts->data;
@@ -6126,13 +6170,8 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
 
                if (ac == compose->account) def_menu = num;
 
-               if (ac->name) {
-                       name = g_markup_printf_escaped("From: <i>%s</i>",
-                                              ac->account_name);
-               } else {
-                       name = g_markup_printf_escaped("From: <i>%s</i>",
-                                              ac->account_name);
-               }
+               name = g_markup_printf_escaped(_("From: <i>%s</i>"),
+                                      ac->account_name);
                
                if (ac == compose->account) {
                        if (ac->name && *ac->name) {
@@ -7474,14 +7513,16 @@ static void compose_send_later_cb(gpointer data, guint action,
        Compose *compose = (Compose *)data;
        gint val;
 
-       val = compose_queue_sub(compose, NULL, NULL, NULL, TRUE);
+       val = compose_queue_sub(compose, NULL, NULL, NULL, TRUE, TRUE);
        if (!val) 
                compose_close(compose);
-       else if (val == -2) {
+       else if (val == -1) {
+               alertpanel_error(_("Could not queue message."));
+       } else if (val == -2) {
                alertpanel_error(_("Could not queue message:\n\n%s."), strerror(errno));
        } else if (val == -3) {
                alertpanel_error(_("Could not queue message for sending:\n\n"
-                                  "Signature failed."));
+                                  "Signature failed: %s"), privacy_get_error());
        } else if (val == -4) {
                alertpanel_error(_("Could not queue message for sending:\n\n"
                                   "Charset conversion failed."));
@@ -7553,9 +7594,11 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                fprintf(fp, "X-Sylpheed-Encrypt:%d\n", compose->use_encryption);
                fprintf(fp, "X-Sylpheed-Privacy-System:%s\n", compose->privacy_system);
        }
-       fprintf(fp, "\n");
 
-       if (compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_STORE) < 0) {
+       /* end of headers */
+       fprintf(fp, "X-Sylpheed-End-Special-Headers: 1\n");
+
+       if (compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_STORE, action != COMPOSE_AUTO_SAVE) < 0) {
                fclose(fp);
                g_unlink(tmp);
                g_free(tmp);
@@ -7578,7 +7621,6 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                goto unlock;
        }
        g_free(tmp);
-       draft->mtime = 0;       /* force updating */
 
        if (compose->mode == COMPOSE_REEDIT) {
                compose_remove_reedit_target(compose, TRUE);
@@ -7591,7 +7633,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                        procmsg_msginfo_set_flags(newmsginfo, MSG_LOCKED, MSG_DRAFT);
                else
                        procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
-               if (compose_use_attach(compose))
+               if (compose_use_attach(compose) && action != COMPOSE_AUTO_SAVE)
                        procmsg_msginfo_set_flags(newmsginfo, 0,
                                                  MSG_HAS_ATTACHMENT);
 
@@ -7717,7 +7759,7 @@ static gint compose_delete_cb(GtkWidget *widget, GdkEventAny *event,
        prefs_common.compose_x = x;
        prefs_common.compose_y = y;
 
-       if (compose->sending)
+       if (compose->sending || compose->updating)
                return TRUE;
        compose_close_cb(compose, 0, NULL);
        return TRUE;
@@ -8464,6 +8506,44 @@ static void compose_insert_drag_received_cb (GtkWidget           *widget,
 {
        Compose *compose = (Compose *)user_data;
        GList *list, *tmp;
+       AlertValue val = G_ALERTDEFAULT;
+
+       switch (prefs_common.compose_dnd_mode) {
+               case COMPOSE_DND_ASK:
+                       val = alertpanel_full(_("Insert or attach?"),
+                                _("Do you want to insert the contents of the file(s) "
+                                  "into the message body, or attach it to the email?"),
+                                 GTK_STOCK_CANCEL, _("+_Insert"), _("_Attach"),
+                                 TRUE, NULL, ALERT_QUESTION, G_ALERTALTERNATE);
+                       break;
+               case COMPOSE_DND_INSERT:
+                       val = G_ALERTALTERNATE;
+                       break;
+               case COMPOSE_DND_ATTACH:
+                       val = G_ALERTOTHER;
+                       break;
+               default:
+                       /* unexpected case */
+                       g_warning("error: unexpected compose_dnd_mode option value in compose_insert_drag_received_cb()");
+       }
+
+       if (val & G_ALERTDISABLE) {
+               val &= ~G_ALERTDISABLE;
+               /* remember what action to perform by default, only if we don't click Cancel */
+               if (val == G_ALERTALTERNATE)
+                       prefs_common.compose_dnd_mode = COMPOSE_DND_INSERT;
+               else
+                       if (val == G_ALERTOTHER)
+                               prefs_common.compose_dnd_mode = COMPOSE_DND_ATTACH;
+       }
+       
+       if (val == G_ALERTDEFAULT) {
+               gtk_drag_finish(drag_context, FALSE, FALSE, time);
+               return;
+       } else if (val == G_ALERTOTHER) {
+               compose_attach_drag_received_cb(widget, drag_context, x, y, data, info, time, user_data);
+               return;
+       } 
 
        /* strangely, testing data->type == gdk_atom_intern("text/uri-list", TRUE)
         * does not work */
@@ -8753,7 +8833,7 @@ static PrefsAccount *compose_guess_forward_account_from_msginfo(MsgInfo *msginfo
        return account;
 }
 
-static gboolean compose_close(Compose *compose)
+gboolean compose_close(Compose *compose)
 {
        gint x, y;
 
@@ -8790,10 +8870,10 @@ static void compose_add_field_list( Compose *compose, GList *listAddress ) {
        }
 }
 
-void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list, 
-                                   guint action)
+static void compose_reply_from_messageview_real(MessageView *msgview, GSList *msginfo_list, 
+                                   guint action, gboolean opening_multiple)
 {
-       gchar *body;
+       gchar *body = NULL;
        GSList *new_msglist = NULL;
        MsgInfo *tmp_msginfo = NULL;
        gboolean originally_enc = FALSE;
@@ -8803,7 +8883,7 @@ void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list,
 
        g_return_if_fail(msginfo_list != NULL);
 
-       if (g_slist_length(msginfo_list) == 1) {
+       if (g_slist_length(msginfo_list) == 1 && !opening_multiple) {
                MimeInfo *mimeinfo = messageview_get_selected_mime_part(msgview);
                MsgInfo *orig_msginfo = (MsgInfo *)msginfo_list->data;
                
@@ -8820,7 +8900,8 @@ void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list,
                }
        }
 
-       body = messageview_get_selection(msgview);
+       if (!opening_multiple)
+               body = messageview_get_selection(msgview);
 
        if (new_msglist) {
                compose = compose_reply_mode((ComposeMode)action, new_msglist, body);
@@ -8836,6 +8917,41 @@ void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list,
        g_free(body);
 }
 
+void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list, 
+                                   guint action)
+{
+       if ((!prefs_common.forward_as_attachment || action != COMPOSE_FORWARD) 
+       &&  action != COMPOSE_FORWARD_AS_ATTACH && g_slist_length(msginfo_list) > 1) {
+               GSList *cur = msginfo_list;
+               gchar *msg = g_strdup_printf(_("You are about to reply to %d "
+                                              "messages. Opening the windows "
+                                              "could take some time. Do you "
+                                              "want to continue?"), 
+                                              g_slist_length(msginfo_list));
+               if (g_slist_length(msginfo_list) > 9
+               &&  alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, "+" GTK_STOCK_YES, NULL)
+                   != G_ALERTALTERNATE) {
+                       g_free(msg);
+                       return;
+               }
+               g_free(msg);
+               /* We'll open multiple compose windows */
+               /* let the WM place the next windows */
+               compose_force_window_origin = FALSE;
+               for (; cur; cur = cur->next) {
+                       GSList tmplist;
+                       tmplist.data = cur->data;
+                       tmplist.next = NULL;
+                       compose_reply_from_messageview_real(msgview, &tmplist, action, TRUE);
+               }
+               compose_force_window_origin = TRUE;
+       } else {
+               /* forwarding multiple mails as attachments is done via a
+                * single compose window */
+               compose_reply_from_messageview_real(msgview, msginfo_list, action, FALSE);
+       }
+}
+
 void compose_set_position(Compose *compose, gint pos)
 {
        GtkTextView *text = GTK_TEXT_VIEW(compose->text);