Fix g_timeout usage
[claws.git] / src / compose.c
index 1c8b05b7745e7726e016f6b4ef512bc9483753e3..5b7a58ebedcabea6433d0834c6fe732a1ccc511b 100644 (file)
@@ -182,6 +182,9 @@ typedef enum {
 
 #define MAX_REFERENCES_LEN     999
 
+#define COMPOSE_DRAFT_TIMEOUT_UNSET -1
+#define COMPOSE_DRAFT_TIMEOUT_FORBIDEN -2
+
 static GList *compose_list = NULL;
 static GSList *extra_headers = NULL;
 
@@ -393,6 +396,8 @@ static void compose_insert_file_cb  (GtkAction      *action,
                                         gpointer        data);
 static void compose_insert_sig_cb      (GtkAction      *action,
                                         gpointer        data);
+static void compose_replace_sig_cb     (GtkAction      *action,
+                                        gpointer        data);
 
 static void compose_close_cb           (GtkAction      *action,
                                         gpointer        data);
@@ -588,6 +593,7 @@ static GtkActionEntry compose_entries[] =
        {"Message/AttachFile",          NULL, N_("_Attach file"), "<control>M", NULL, G_CALLBACK(compose_attach_cb) },
        {"Message/InsertFile",          NULL, N_("_Insert file"), "<control>I", NULL, G_CALLBACK(compose_insert_file_cb) },
        {"Message/InsertSig",           NULL, N_("Insert si_gnature"), "<control>G", NULL, G_CALLBACK(compose_insert_sig_cb) },
+       {"Message/ReplaceSig",          NULL, N_("_Replace signature"), NULL, NULL, G_CALLBACK(compose_replace_sig_cb) },
        /* {"Message/---",              NULL, "---" }, */
        {"Message/Save",                NULL, N_("_Save"), "<control>S", NULL, G_CALLBACK(compose_save_cb) }, /*COMPOSE_KEEP_EDITING*/
        /* {"Message/---",              NULL, "---" }, */
@@ -1263,7 +1269,8 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        if (prefs_common.auto_exteditor)
                compose_exec_ext_editor(compose);
 
-       compose->draft_timeout_tag = -1;
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET;
+
        SCROLL_TO_CURSOR(compose);
 
        compose->modified = FALSE;
@@ -1704,7 +1711,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
        compose_set_title(compose);
 
        compose->updating = FALSE;
-       compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
        SCROLL_TO_CURSOR(compose);
        
        if (compose->deferred_destroy) {
@@ -1907,7 +1914,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
        compose_set_title(compose);
 
        compose->updating = FALSE;
-       compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
        SCROLL_TO_CURSOR(compose);
 
        if (compose->deferred_destroy) {
@@ -2055,7 +2062,7 @@ static Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_
        compose_set_title(compose);
 
        compose->updating = FALSE;
-       compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
        SCROLL_TO_CURSOR(compose);
 
        if (compose->deferred_destroy) {
@@ -2128,21 +2135,21 @@ static void compose_colorize_signature(Compose *compose)
                                G_CALLBACK(text_inserted),              \
                                compose);                               \
 }
-#define UNBLOCK_WRAP() {                                               \
-       compose->autowrap = prev_autowrap;                              \
-       if (compose->autowrap) {                                        \
-               gint old = compose->draft_timeout_tag;                  \
-               compose->draft_timeout_tag = -2;                        \
-               compose_wrap_all(compose);                              \
-               compose->draft_timeout_tag = old;                       \
-       }                                                               \
-                                                                       \
-       g_signal_handlers_unblock_by_func(G_OBJECT(buffer),             \
-                               G_CALLBACK(compose_changed_cb),         \
-                               compose);                               \
-       g_signal_handlers_unblock_by_func(G_OBJECT(buffer),             \
-                               G_CALLBACK(text_inserted),              \
-                               compose);                               \
+#define UNBLOCK_WRAP() {                                                       \
+       compose->autowrap = prev_autowrap;                                      \
+       if (compose->autowrap) {                                                \
+               gint old = compose->draft_timeout_tag;                          \
+               compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_FORBIDDEN;   \
+               compose_wrap_all(compose);                                      \
+               compose->draft_timeout_tag = old;                               \
+       }                                                                       \
+                                                                               \
+       g_signal_handlers_unblock_by_func(G_OBJECT(buffer),                     \
+                               G_CALLBACK(compose_changed_cb),                 \
+                               compose);                                       \
+       g_signal_handlers_unblock_by_func(G_OBJECT(buffer),                     \
+                               G_CALLBACK(text_inserted),                      \
+                               compose);                                       \
 }
 
 Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
@@ -2405,7 +2412,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
        compose_set_title(compose);
 
        compose->updating = FALSE;
-       compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
        SCROLL_TO_CURSOR(compose);
 
        if (compose->deferred_destroy) {
@@ -2491,6 +2498,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/InsertFile", FALSE);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/AttachFile", FALSE);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/InsertSig", FALSE);
+       cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/ReplaceSig", FALSE);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Edit", FALSE);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options", FALSE);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Tools/ShowRuler", FALSE);
@@ -2514,7 +2522,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
        compose->modified = FALSE;
        compose_set_title(compose);
        compose->updating = FALSE;
-       compose->draft_timeout_tag = -1; /* desinhibit auto-drafting after loading */
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET; /* desinhibit auto-drafting after loading */
        SCROLL_TO_CURSOR(compose);
 
        if (compose->deferred_destroy) {
@@ -2668,6 +2676,9 @@ void compose_toolbar_cb(gint action, gpointer data)
        case A_SIG:
                compose_insert_sig(compose, FALSE);
                break;
+       case A_REP_SIG:
+               compose_insert_sig(compose, TRUE);
+               break;
        case A_EXTEDITOR:
                compose_ext_editor_cb(NULL, compose);
                break;
@@ -3275,16 +3286,18 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                        gchar *tmp1 = NULL;
                        if (!msginfo->from)
                                return;
-                       Xstrdup_a(tmp1, msginfo->from, return);
-                       extract_address(tmp1);
-                       if (to_all || to_sender ||
-                           !account_find_from_address(tmp1, FALSE))
+                       if (to_sender)
+                               compose_entry_append(compose, msginfo->from,
+                                                    COMPOSE_TO, PREF_NONE);
+                       else if (to_all) {
+                               Xstrdup_a(tmp1, msginfo->from, return);
+                               extract_address(tmp1);
                                compose_entry_append(compose,
-                                (compose->replyto && !to_sender)
-                                         ? compose->replyto :
-                                         msginfo->from ? msginfo->from : "",
+                                (!account_find_from_address(tmp1, FALSE))
+                                         ? msginfo->from :
+                                         msginfo->to,
                                          COMPOSE_TO, PREF_NONE);
-                       else if (!to_all && !to_sender) {
+                       } else {
                                if (!folder_has_parent_of_type(msginfo->folder, F_QUEUE) &&
                                    !folder_has_parent_of_type(msginfo->folder, F_OUTBOX) &&
                                    !folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
@@ -3664,9 +3677,18 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
                alertpanel_error("Can't get file size of %s\n", filename);
                return FALSE;
        }
-       if (size == 0) {
-               alertpanel_error(_("File %s is empty."), filename);
-               return FALSE;
+
+       /* In batch mode, we allow 0-length files to be attached no questions asked */
+       if (size == 0 && !compose->batch) {
+               gchar * msg = g_strdup_printf(_("File %s is empty."), filename);
+               AlertValue aval = alertpanel_full(_("Empty file"), msg, 
+                               GTK_STOCK_CANCEL, _("+_Attach anyway"), NULL, FALSE,
+                               NULL, ALERT_WARNING, G_ALERTDEFAULT);
+               g_free(msg);
+
+               if (aval != G_ALERTALTERNATE) {
+                       return FALSE;
+               }
        }
        if ((fp = g_fopen(file, "rb")) == NULL) {
                alertpanel_error(_("Can't read %s."), filename);
@@ -4294,7 +4316,7 @@ static gboolean compose_beautify_paragraph(Compose *compose, GtkTextIter *par_it
        if (force) {
                modified = TRUE;
        }
-       if (compose->draft_timeout_tag == -2) {
+       if (compose->draft_timeout_tag == COMPOSE_DRAFT_TIMEOUT_FORBIDDEN) {
                modified = TRUE;
        }
 
@@ -4311,7 +4333,7 @@ static gboolean compose_beautify_paragraph(Compose *compose, GtkTextIter *par_it
        }
 
 
-       if (compose->draft_timeout_tag == -2) {
+       if (compose->draft_timeout_tag == COMPOSE_DRAFT_TIMEOUT_FORBIDDEN) {
                if (gtk_text_iter_ends_line(&iter)) {
                        while (gtk_text_iter_ends_line(&iter) &&
                               gtk_text_iter_forward_line(&iter))
@@ -4733,7 +4755,7 @@ compose_current_mail_account(void)
 
 #define QUOTE_IF_REQUIRED(out, str)                                    \
 {                                                                      \
-       if (*str != '"' && strpbrk(str, ",.[]<>")) {                    \
+       if (*str != '"' && strpbrk(str, ",.:;[]<>()@\\\"")) {           \
                gchar *__tmp;                                           \
                gint len;                                               \
                                                                        \
@@ -4761,7 +4783,7 @@ compose_current_mail_account(void)
 
 #define QUOTE_IF_REQUIRED_NORMAL(out, str, errret)                     \
 {                                                                      \
-       if (*str != '"' && strpbrk(str, ",.[]<>")) {                    \
+       if (*str != '"' && strpbrk(str, ",.:;[]<>()@\\\"")) {           \
                gchar *__tmp;                                           \
                gint len;                                               \
                                                                        \
@@ -4798,10 +4820,13 @@ static void compose_select_account(Compose *compose, PrefsAccount *account,
 
        compose->account = account;
        if (account->name && *account->name) {
-               gchar *buf;
+               gchar *buf, *qbuf;
                QUOTE_IF_REQUIRED_NORMAL(buf, account->name, return);
+               qbuf = escape_internal_quotes(buf, '"');
                from = g_strdup_printf("%s <%s>",
-                                      buf, account->address);
+                                      qbuf, account->address);
+               if (qbuf != buf)
+                       g_free(qbuf);
                gtk_entry_set_text(GTK_ENTRY(compose->from_name), from);
        } else {
                from = g_strdup_printf("<%s>",
@@ -5327,6 +5352,8 @@ static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
                }
                generate_msgid(buf, sizeof(buf), addr);
                err |= (fprintf(fp, "Resent-Message-ID: <%s>\n", buf) < 0);
+               if (compose->msgid)
+                       g_free(compose->msgid);
                compose->msgid = g_strdup(buf);
        } else {
                compose->msgid = NULL;
@@ -6138,16 +6165,20 @@ static gchar *compose_quote_list_of_addresses(gchar *str)
        for (item = list; item != NULL; item = item->next) {
                gchar *spec = item->data;
                gchar *endofname = strstr(spec, " <");
-               *endofname = '\0';
-               QUOTE_IF_REQUIRED_NORMAL(qname, spec, return NULL);
-               *endofname = ' ';
-               if (*qname != *spec) { /* has been quoted, compute new */
-                       gchar *addr = g_strdup(endofname);
-                       gchar *name = g_strdup(qname);
-                       faddr = g_strconcat(name, addr, NULL);
-                       g_free(name);
-                       g_free(addr);
-                       debug_print("new auto-quoted address: '%s'", faddr);
+               if (endofname != NULL) {
+                       gchar * qqname;
+                       *endofname = '\0';
+                       QUOTE_IF_REQUIRED_NORMAL(qname, spec, return NULL);
+                       qqname = escape_internal_quotes(qname, '"');
+                       *endofname = ' ';
+                       if (*qname != *spec || qqname != qname) { /* has been quoted, compute new */
+                               gchar *addr = g_strdup(endofname);
+                               gchar *name = (qqname != qname)? qqname: g_strdup(qname);
+                               faddr = g_strconcat(name, addr, NULL);
+                               g_free(name);
+                               g_free(addr);
+                               debug_print("new auto-quoted address: '%s'", faddr);
+                       }
                }
                if (result == NULL)
                        result = g_strdup((faddr != NULL)? faddr: spec);
@@ -6333,13 +6364,17 @@ static gchar *compose_get_header(Compose *compose)
        
        
        if (from_name && *from_name) {
+               gchar *qname;
                compose_convert_header
                        (compose, buf, sizeof(buf), from_name,
                         strlen("From: "), TRUE);
                QUOTE_IF_REQUIRED(name, buf);
+               qname = escape_internal_quotes(name, '"');
                
                g_string_append_printf(header, "From: %s <%s>\n",
-                       name, from_address);
+                       qname, from_address);
+               if (qname != name)
+                       g_free(qname);
        } else
                g_string_append_printf(header, "From: %s\n", from_address);
        
@@ -6395,6 +6430,8 @@ static gchar *compose_get_header(Compose *compose)
                }
                generate_msgid(buf, sizeof(buf), addr);
                g_string_append_printf(header, "Message-ID: <%s>\n", buf);
+               if (compose->msgid)
+                       g_free(compose->msgid);
                compose->msgid = g_strdup(buf);
        } else {
                compose->msgid = NULL;
@@ -6435,7 +6472,8 @@ static gchar *compose_get_header(Compose *compose)
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
                        TARGET_ALIAS);
        }
-       if (g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
+       if (compose->account->gen_xmailer &&
+           g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
                g_string_append_printf(header, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
@@ -6785,7 +6823,7 @@ static void compose_create_header_entry(Compose *compose)
        gtk_table_attach(GTK_TABLE(compose->header_table), combo, 0, 1,
                        compose->header_nextrow, compose->header_nextrow+1,
                        GTK_SHRINK, GTK_FILL, 0, 0);
-       if (compose->header_last && (compose->draft_timeout_tag != -2)) {
+       if (compose->header_last && (compose->draft_timeout_tag != COMPOSE_DRAFT_TIMEOUT_FORBIDDEN)) {
                const gchar *last_header_entry = gtk_entry_get_text(
                                GTK_ENTRY(gtk_bin_get_child(GTK_BIN((compose->header_last->combo)))));
                string = headers;
@@ -7436,6 +7474,7 @@ static Compose *compose_create(PrefsAccount *account,
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "AttachFile", "Message/AttachFile", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "InsertFile", "Message/InsertFile", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "InsertSig", "Message/InsertSig", GTK_UI_MANAGER_MENUITEM)
+       MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "ReplaceSig", "Message/ReplaceSig", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "Separator2", "Message/---", GTK_UI_MANAGER_SEPARATOR)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "Save", "Message/Save", GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Message", "Separator3", "Message/---", GTK_UI_MANAGER_SEPARATOR)
@@ -7851,7 +7890,7 @@ static Compose *compose_create(PrefsAccount *account,
        compose->exteditor_file    = NULL;
        compose->exteditor_pid     = -1;
        compose->exteditor_tag     = -1;
-       compose->draft_timeout_tag = -2; /* inhibit auto-drafting while loading */
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_FORBIDDEN; /* inhibit auto-drafting while loading */
 
 #if USE_ENCHANT
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Spelling", FALSE);
@@ -9285,6 +9324,7 @@ static void compose_set_ext_editor_sensitive(Compose *compose,
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/SendLater", sensitive);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/InsertFile", sensitive);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/InsertSig", sensitive);
+       cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Message/ReplaceSig", sensitive);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Edit/WrapPara", sensitive);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Edit/WrapAllLines", sensitive);
        cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Edit/ExtEditor", sensitive);
@@ -9595,7 +9635,7 @@ static void compose_send_cb(GtkAction *action, gpointer data)
        
        if (compose->draft_timeout_tag >= 0) { /* CLAWS: disable draft timeout */
                g_source_remove(compose->draft_timeout_tag);
-               compose->draft_timeout_tag = -1;
+               compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET;
        }
 
        compose_send(compose);
@@ -9756,9 +9796,11 @@ gboolean compose_draft (gpointer data, guint action)
                goto warn_err;
        }
        
+       flag.perm_flags = MSG_NEW|MSG_UNREAD;
        if (compose->targetinfo) {
                target_locked = MSG_IS_LOCKED(compose->targetinfo->flags);
-               flag.perm_flags = target_locked?MSG_LOCKED:0;
+               if (target_locked) 
+                       flag.perm_flags |= MSG_LOCKED;
        }
        flag.tmp_flags = MSG_DRAFT;
 
@@ -9819,9 +9861,9 @@ warn_err:
        if (newmsginfo) {
                procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
                if (target_locked)
-                       procmsg_msginfo_set_flags(newmsginfo, MSG_LOCKED, MSG_DRAFT);
+                       procmsg_msginfo_set_flags(newmsginfo, MSG_NEW|MSG_UNREAD|MSG_LOCKED, MSG_DRAFT);
                else
-                       procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
+                       procmsg_msginfo_set_flags(newmsginfo, MSG_NEW|MSG_UNREAD, MSG_DRAFT);
                if (compose_use_attach(compose) && action != COMPOSE_AUTO_SAVE)
                        procmsg_msginfo_set_flags(newmsginfo, 0,
                                                  MSG_HAS_ATTACHMENT);
@@ -10009,6 +10051,13 @@ static void compose_insert_sig_cb(GtkAction *action, gpointer data)
        compose_insert_sig(compose, FALSE);
 }
 
+static void compose_replace_sig_cb(GtkAction *action, gpointer data)
+{
+       Compose *compose = (Compose *)data;
+
+       compose_insert_sig(compose, TRUE);
+}
+
 static gint compose_delete_cb(GtkWidget *widget, GdkEventAny *event,
                              gpointer data)
 {
@@ -10031,6 +10080,14 @@ void compose_close_toolbar(Compose *compose)
        compose_close_cb(NULL, compose);
 }
 
+static gboolean compose_can_autosave(Compose *compose)
+{
+       if (compose->privacy_system && compose->use_encryption)
+               return prefs_common.autosave && prefs_common.autosave_encrypted;
+       else
+               return prefs_common.autosave;
+}
+
 static void compose_close_cb(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
@@ -10065,8 +10122,8 @@ static void compose_close_cb(GtkAction *action, gpointer data)
                g_mutex_unlock(compose->mutex);
                switch (val) {
                case G_ALERTDEFAULT:
-                       if (prefs_common.autosave && !reedit)
-                               compose_remove_draft(compose);                  
+                       if (compose_can_autosave(compose) && !reedit)
+                               compose_remove_draft(compose);
                        break;
                case G_ALERTALTERNATE:
                        compose_draft(data, COMPOSE_QUIT_EDITING);
@@ -11140,7 +11197,8 @@ static gboolean scroll_postpone(gpointer data)
 {
        Compose *compose = (Compose *)data;
 
-       cm_return_val_if_fail(!compose->batch, FALSE);
+       if (compose->batch)
+               return FALSE;
 
        GTK_EVENTS_FLUSH();
        compose_show_first_last_header(compose, FALSE);
@@ -11163,7 +11221,7 @@ static void compose_headerentry_changed_cb(GtkWidget *entry,
 
 static gboolean compose_defer_auto_save_draft(Compose *compose)
 {
-       compose->draft_timeout_tag = -1;
+       compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_UNSET;
        compose_draft((gpointer)compose, COMPOSE_AUTO_SAVE);
        return FALSE;
 }
@@ -11173,7 +11231,10 @@ static void compose_show_first_last_header(Compose *compose, gboolean show_first
        GtkAdjustment *vadj;
 
        cm_return_if_fail(compose);
-       cm_return_if_fail(!compose->batch);
+
+       if(compose->batch)
+               return;
+
        cm_return_if_fail(GTK_IS_WIDGET(compose->header_table));
        cm_return_if_fail(GTK_IS_VIEWPORT(gtk_widget_get_parent(compose->header_table)));
        vadj = gtk_viewport_get_vadjustment(GTK_VIEWPORT(
@@ -11282,9 +11343,9 @@ static void text_inserted(GtkTextBuffer *buffer, GtkTextIter *iter,
                                          compose);
        g_signal_stop_emission_by_name(G_OBJECT(buffer), "insert-text");
 
-       if (prefs_common.autosave && 
+       if (compose_can_autosave(compose) && 
            gtk_text_buffer_get_char_count(buffer) % prefs_common.autosave_length == 0 &&
-           compose->draft_timeout_tag != -2 /* disabled while loading */)
+           compose->draft_timeout_tag != COMPOSE_DRAFT_TIMEOUT_FORBIDDEN /* disabled while loading */)
                compose->draft_timeout_tag = g_timeout_add
                        (500, (GSourceFunc) compose_defer_auto_save_draft, compose);
 }
@@ -11396,16 +11457,28 @@ gboolean compose_close(Compose *compose)
 {
        gint x, y;
 
+       cm_return_val_if_fail(compose, FALSE);
+
        if (!g_mutex_trylock(compose->mutex)) {
                /* we have to wait for the (possibly deferred by auto-save)
                 * drafting to be done, before destroying the compose under
                 * it. */
                debug_print("waiting for drafting to finish...\n");
                compose_allow_user_actions(compose, FALSE);
-               g_timeout_add (500, (GSourceFunc) compose_close, compose);
+               if (compose->close_timeout_tag == 0) {
+                       compose->close_timeout_tag = 
+                               g_timeout_add (500, (GSourceFunc) compose_close,
+                               compose);
+               }
                return FALSE;
        }
-       cm_return_val_if_fail(compose, FALSE);
+       
+       if (compose->close_timeout_tag) {
+               /* let the close be done by the deferred callback */
+               g_mutex_unlock(compose->mutex);
+               return FALSE;
+       }
+
        gtkut_widget_get_uposition(compose->window, &x, &y);
        if (!compose->batch) {
                prefs_common.compose_x = x;