2009-02-11 [colin] 3.7.0cvs58
[claws.git] / src / compose.c
index b940767f020ff0e69d118145bab3e5906caafde3..34b4f07be74854f408401b737cf5fbf4f36e1a76 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2008 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2009 Hiroyuki Yamamoto and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "privacy.h"
 #include "timing.h"
 #include "autofaces.h"
+#include "spell_entry.h"
 
 enum
 {
@@ -333,6 +334,7 @@ static void compose_remove_header_entries(Compose *compose);
 static void compose_update_priority_menu_item(Compose * compose);
 #if USE_ENCHANT
 static void compose_spell_menu_changed (void *data);
+static void compose_dict_changed       (void *data);
 #endif
 static void compose_add_field_list     ( Compose *compose,
                                          GList *listAddress );
@@ -677,21 +679,21 @@ static GtkRadioActionEntry compose_radio_prio_entries[] =
 
 static GtkRadioActionEntry compose_radio_enc_entries[] =
 {
-       ENC_ACTION(CS_AUTO, C_AUTO, "_Automatic"), /* RADIO compose_set_encoding_cb */
-       ENC_ACTION(CS_US_ASCII, C_US_ASCII, "7bit ASCII (US-ASC_II)"), /* RADIO compose_set_encoding_cb */
-       ENC_ACTION(CS_UTF_8, C_UTF_8, "Unicode (_UTF-8)"), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION(CS_AUTO, C_AUTO, N_("_Automatic")), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION(CS_US_ASCII, C_US_ASCII, N_("7bit ASCII (US-ASC_II)")), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION(CS_UTF_8, C_UTF_8, N_("Unicode (_UTF-8)")), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Western/"CS_ISO_8859_1, C_ISO_8859_1, "ISO-8859-_1"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Western/"CS_ISO_8859_15, C_ISO_8859_15, "ISO-8859-15"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Western/"CS_WINDOWS_1252, C_WINDOWS_1252, "Windows-1252"), /* RADIO compose_set_encoding_cb */
-       ENC_ACTION(CS_ISO_8859_2, C_ISO_8859_2, "Central European (ISO-8859-_2)"), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION(CS_ISO_8859_2, C_ISO_8859_2, N_("Central European (ISO-8859-_2)")), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Baltic/"CS_ISO_8859_13, C_ISO_8859_13, "ISO-8859-13"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Baltic/"CS_ISO_8859_4, C_ISO_8859_14, "ISO-8859-_4"), /* RADIO compose_set_encoding_cb */
-       ENC_ACTION(CS_ISO_8859_7, C_ISO_8859_7, "Greek (ISO-8859-_7)"), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION(CS_ISO_8859_7, C_ISO_8859_7, N_("Greek (ISO-8859-_7)")), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Hebrew/"CS_ISO_8859_8, C_ISO_8859_8, "ISO-8859-_8"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Hebrew/"CS_WINDOWS_1255, C_WINDOWS_1255, "Windows-1255"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Arabic/"CS_ISO_8859_6, C_ISO_8859_6, "ISO-8859-_6"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Arabic/"CS_WINDOWS_1256, C_WINDOWS_1256, "Windows-1256"), /* RADIO compose_set_encoding_cb */
-       ENC_ACTION(CS_ISO_8859_9, C_ISO_8859_9, "Turkish (ISO-8859-_9)"), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION(CS_ISO_8859_9, C_ISO_8859_9, N_("Turkish (ISO-8859-_9)")), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Cyrillic/"CS_ISO_8859_5, C_ISO_8859_5, "ISO-8859-_5"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Cyrillic/"CS_KOI8_R, C_KOI8_R, "KOI8-_R"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Cyrillic/"CS_KOI8_U, C_KOI8_U, "KOI8-_U"), /* RADIO compose_set_encoding_cb */
@@ -886,6 +888,41 @@ Compose *compose_new_with_list( PrefsAccount *account, GList *listAddress )
                cmark);                                         \
 }
 
+static void compose_set_save_to(Compose *compose, const gchar *folderidentifier)
+{
+       GtkEditable *entry;
+       if (folderidentifier) {
+               combobox_unset_popdown_strings(GTK_COMBO_BOX(compose->savemsg_combo));
+               prefs_common.compose_save_to_history = add_history(
+                               prefs_common.compose_save_to_history, folderidentifier);
+               combobox_set_popdown_strings(GTK_COMBO_BOX(compose->savemsg_combo),
+                               prefs_common.compose_save_to_history);
+       }
+
+       entry = GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(compose->savemsg_combo)));
+       if (folderidentifier)
+               gtk_entry_set_text(GTK_ENTRY(entry), folderidentifier);
+       else
+               gtk_entry_set_text(GTK_ENTRY(entry), "");
+}
+
+static gchar *compose_get_save_to(Compose *compose)
+{
+       GtkEditable *entry;
+       gchar *result = NULL;
+       entry = GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(compose->savemsg_combo)));
+       result = gtk_editable_get_chars(entry, 0, -1);
+       
+       if (result) {
+               combobox_unset_popdown_strings(GTK_COMBO_BOX(compose->savemsg_combo));
+               prefs_common.compose_save_to_history = add_history(
+                               prefs_common.compose_save_to_history, result);
+               combobox_set_popdown_strings(GTK_COMBO_BOX(compose->savemsg_combo),
+                               prefs_common.compose_save_to_history);
+       }
+       return result;
+}
+
 Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item,
                             GPtrArray *attach_files, GList *listAddress )
 {
@@ -1102,7 +1139,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), prefs_common.savemsg);
                folderidentifier = folder_item_get_identifier(item);
-               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               compose_set_save_to(compose, folderidentifier);
                g_free(folderidentifier);
        }
        
@@ -1122,9 +1159,9 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 }
 
 static void compose_force_encryption(Compose *compose, PrefsAccount *account,
-               gboolean override_pref)
+               gboolean override_pref, const gchar *system)
 {
-       gchar *privacy = NULL;
+       const gchar *privacy = NULL;
 
        g_return_if_fail(compose != NULL);
        g_return_if_fail(account != NULL);
@@ -1132,7 +1169,9 @@ static void compose_force_encryption(Compose *compose, PrefsAccount *account,
        if (override_pref == FALSE && account->default_encrypt_reply == FALSE)
                return;
 
-       if (account->default_privacy_system
+       if (system)
+               privacy = system;
+       else if (account->default_privacy_system
        &&  strlen(account->default_privacy_system)) {
                privacy = account->default_privacy_system;
        } else {
@@ -1142,6 +1181,10 @@ static void compose_force_encryption(Compose *compose, PrefsAccount *account,
                }
        }
        if (privacy != NULL) {
+               if (system) {
+                       g_free(compose->privacy_system);
+                       compose->privacy_system = NULL;
+               }
                if (compose->privacy_system == NULL)
                        compose->privacy_system = g_strdup(privacy);
                else if (*(compose->privacy_system) == '\0') {
@@ -1153,11 +1196,13 @@ static void compose_force_encryption(Compose *compose, PrefsAccount *account,
        }
 }      
 
-static void compose_force_signing(Compose *compose, PrefsAccount *account)
+static void compose_force_signing(Compose *compose, PrefsAccount *account, const gchar *system)
 {
        gchar *privacy = NULL;
 
-       if (account->default_privacy_system
+       if (system)
+               privacy = system;
+       else if (account->default_privacy_system
        &&  strlen(account->default_privacy_system)) {
                privacy = account->default_privacy_system;
        } else {
@@ -1166,7 +1211,12 @@ static void compose_force_signing(Compose *compose, PrefsAccount *account)
                        privacy = (gchar *)(privacy_avail->data);
                }
        }
+
        if (privacy != NULL) {
+               if (system) {
+                       g_free(compose->privacy_system);
+                       compose->privacy_system = NULL;
+               }
                if (compose->privacy_system == NULL)
                        compose->privacy_system = g_strdup(privacy);
                compose_update_privacy_system_menu_item(compose, FALSE);
@@ -1383,6 +1433,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
        gboolean quote = FALSE;
        const gchar *qmark = NULL;
        const gchar *body_fmt = NULL;
+       gchar *s_system = NULL;
        START_TIMING("");
        g_return_val_if_fail(msginfo != NULL, NULL);
        g_return_val_if_fail(msginfo->folder != NULL, NULL);
@@ -1413,7 +1464,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
 
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE);
                folderidentifier = folder_item_get_identifier(msginfo->folder);
-               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               compose_set_save_to(compose, folderidentifier);
                g_free(folderidentifier);
        }
 
@@ -1500,13 +1551,14 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
        }
 
        if (MSG_IS_ENCRYPTED(compose->replyinfo->flags)) {
-               compose_force_encryption(compose, account, FALSE);
+               compose_force_encryption(compose, account, FALSE, s_system);
        }
 
-       privacy_msginfo_get_signed_state(compose->replyinfo);
+       privacy_msginfo_get_signed_state(compose->replyinfo, &s_system);
        if (MSG_IS_SIGNED(compose->replyinfo->flags) && account->default_sign_reply) {
-               compose_force_signing(compose, account);
+               compose_force_signing(compose, account, s_system);
        }
+       g_free(s_system);
 
        SIGNAL_BLOCK(textbuf);
        
@@ -1713,7 +1765,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE);
                folderidentifier = folder_item_get_identifier(msginfo->folder);
-               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               compose_set_save_to(compose, folderidentifier);
                g_free(folderidentifier);
        }
 
@@ -2118,11 +2170,8 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
 
                /* Set message save folder */
                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "SCF:")) {
-                       gint startpos = 0;
-
                        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), TRUE);
-                       gtk_editable_delete_text(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
-                       gtk_editable_insert_text(GTK_EDITABLE(compose->savemsg_entry), &queueheader_buf[4], strlen(&queueheader_buf[4]), &startpos);
+                       compose_set_save_to(compose, &queueheader_buf[4]);
                }
                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, sizeof(queueheader_buf), "RRCPT:")) {
                        gint active = atoi(&queueheader_buf[strlen("RRCPT:")]);
@@ -2153,7 +2202,7 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
        if (MSG_IS_ENCRYPTED(msginfo->flags)) {
                fp = procmime_get_first_encrypted_text_content(msginfo);
                if (fp) {
-                       compose_force_encryption(compose, account, TRUE);
+                       compose_force_encryption(compose, account, TRUE, NULL);
                }
        } else {
                fp = procmime_get_first_text_content(msginfo);
@@ -2248,7 +2297,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
 
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), prefs_common.savemsg);
                folderidentifier = folder_item_get_identifier(item);
-               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               compose_set_save_to(compose, folderidentifier);
                g_free(folderidentifier);
        }
 
@@ -3230,7 +3279,8 @@ static void compose_insert_sig(Compose *compose, gboolean replace)
        else
                gtk_text_buffer_get_iter_at_offset(buffer, &iter, 
                        compose->set_cursor_pos);
-               
+       
+       compose->set_cursor_pos = -1;
        gtk_text_buffer_place_cursor(buffer, &iter);
        g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
                                        G_CALLBACK(compose_changed_cb),
@@ -3530,7 +3580,7 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
                                compose_attach_append(compose, outfile, 
                                                      partname, content_type);
                        } else {
-                               compose_force_signing(compose, compose->account);
+                               compose_force_signing(compose, compose->account, NULL);
                        }
                        g_free(content_type);
                }
@@ -3818,7 +3868,7 @@ static gboolean compose_get_line_break_pos(GtkTextBuffer *buffer,
                can_break = TRUE;
        }
 
-       debug_print("compose_get_line_break_pos(): do_break = %d, pos = %d, col = %d\n", do_break, pos, col);
+//     debug_print("compose_get_line_break_pos(): do_break = %d, pos = %d, col = %d\n", do_break, pos, col);
 
        g_free(attrs);
        g_free(str);
@@ -4063,7 +4113,7 @@ static gboolean compose_beautify_paragraph(Compose *compose, GtkTextIter *par_it
                quote_str = compose_get_quote_str(buffer, &iter, &quote_len);
 
                if (quote_str) {
-                       debug_print("compose_beautify_paragraph(): quote_str = '%s'\n", quote_str);
+//                     debug_print("compose_beautify_paragraph(): quote_str = '%s'\n", quote_str);
                        if (startq_offset == -1) 
                                startq_offset = gtk_text_iter_get_offset(&iter);
                        quotelevel = get_quote_level(quote_str, prefs_common.quote_chars);
@@ -4309,11 +4359,11 @@ colorize:
                        }
                }
                if (!modified) {
-                       debug_print("not modified, out after %d lines\n", lines);
+//                     debug_print("not modified, out after %d lines\n", lines);
                        goto end;
                }
        }
-       debug_print("modified, out after %d lines\n", lines);
+//     debug_print("modified, out after %d lines\n", lines);
 end:
        g_free(itemized_chars);
        if (par_iter)
@@ -5078,6 +5128,8 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
        MimeInfo *mimemsg, *mimetext;
        gint line;
        const gchar *src_codeset = CS_INTERNAL;
+       gchar *from_addr = NULL;
+       gchar *from_name = NULL;
 
        if (action == COMPOSE_WRITE_FOR_SEND)
                attach_parts = TRUE;
@@ -5261,12 +5313,31 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
 
        g_free(buf);
 
+       if (strlen(gtk_entry_get_text(GTK_ENTRY(compose->from_name))) != 0) {
+               gchar *spec = gtk_editable_get_chars(GTK_EDITABLE(compose->from_name), 0, -1);
+               /* extract name and address */
+               if (strstr(spec, " <") && strstr(spec, ">")) {
+                       from_addr = g_strdup(strrchr(spec, '<')+1);
+                       *(strrchr(from_addr, '>')) = '\0';
+                       from_name = g_strdup(spec);
+                       *(strrchr(from_name, '<')) = '\0';
+               } else {
+                       from_name = NULL;
+                       from_addr = NULL;
+               }
+               g_free(spec);
+       }
        /* sign message if sending */
        if (action == COMPOSE_WRITE_FOR_SEND && compose->use_signing && 
            privacy_system_can_sign(compose->privacy_system))
-               if (!privacy_sign(compose->privacy_system, mimemsg, compose->account))
+               if (!privacy_sign(compose->privacy_system, mimemsg, 
+                       compose->account, from_addr)) {
+                       g_free(from_name);
+                       g_free(from_addr);
                        return -2;
-
+       }
+       g_free(from_name);
+       g_free(from_addr);
        procmime_write_mimeinfo(mimemsg, fp);
        
        procmime_mimeinfo_free_all(mimemsg);
@@ -5557,7 +5628,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn))) {
                gchar *savefolderid;
                
-               savefolderid = gtk_editable_get_chars(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
+               savefolderid = compose_get_save_to(compose);
                err |= (fprintf(fp, "SCF:%s\n", savefolderid) < 0);
                g_free(savefolderid);
        }
@@ -5686,7 +5757,7 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
                mimepart->tmp = FALSE; /* or we destroy our attachment */
                mimepart->offset = 0;
 
-               stat(ainfo->file, &statbuf);
+               g_stat(ainfo->file, &statbuf);
                mimepart->length = statbuf.st_size;
 
                type = g_strdup(ainfo->content_type);
@@ -5707,8 +5778,10 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
                        mimepart->disposition = DISPOSITIONTYPE_INLINE;
                } else {
                        if (ainfo->name) {
-                               g_hash_table_insert(mimepart->typeparameters,
-                                           g_strdup("name"), g_strdup(ainfo->name));
+                               if (mimepart->type == MIMETYPE_APPLICATION && 
+                                  !strcmp2(mimepart->subtype, "octet-stream"))
+                                       g_hash_table_insert(mimepart->typeparameters,
+                                                   g_strdup("name"), g_strdup(ainfo->name));
                                g_hash_table_insert(mimepart->dispositionparameters,
                                            g_strdup("filename"), g_strdup(ainfo->name));
                                mimepart->disposition = DISPOSITIONTYPE_ATTACHMENT;
@@ -6441,7 +6514,7 @@ static GtkWidget *compose_create_others(Compose *compose)
 {
        GtkWidget *table;
        GtkWidget *savemsg_checkbtn;
-       GtkWidget *savemsg_entry;
+       GtkWidget *savemsg_combo;
        GtkWidget *savemsg_select;
        
        guint rowcount = 0;
@@ -6464,16 +6537,23 @@ static GtkWidget *compose_create_others(Compose *compose)
        g_signal_connect(G_OBJECT(savemsg_checkbtn), "toggled",
                         G_CALLBACK(compose_savemsg_checkbtn_cb), compose);
 
-       savemsg_entry = gtk_entry_new();
-       gtk_widget_show(savemsg_entry);
-       gtk_table_attach_defaults(GTK_TABLE(table), savemsg_entry, 1, 2, rowcount, rowcount + 1);
-       gtk_editable_set_editable(GTK_EDITABLE(savemsg_entry), prefs_common.savemsg);
-       g_signal_connect_after(G_OBJECT(savemsg_entry), "grab_focus",
+       savemsg_combo = gtk_combo_box_entry_new_text();
+       compose->savemsg_checkbtn = savemsg_checkbtn;
+       compose->savemsg_combo = savemsg_combo;
+       gtk_widget_show(savemsg_combo);
+
+       if (prefs_common.compose_save_to_history)
+               combobox_set_popdown_strings(GTK_COMBO_BOX(savemsg_combo),
+                               prefs_common.compose_save_to_history);
+
+       gtk_table_attach(GTK_TABLE(table), savemsg_combo, 1, 2, rowcount, rowcount + 1, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0);
+       gtk_widget_set_sensitive(GTK_WIDGET(savemsg_combo), prefs_common.savemsg);
+       g_signal_connect_after(G_OBJECT(savemsg_combo), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        if (account_get_special_folder(compose->account, F_OUTBOX)) {
                folderidentifier = folder_item_get_identifier(account_get_special_folder
                                  (compose->account, F_OUTBOX));
-               gtk_entry_set_text(GTK_ENTRY(savemsg_entry), folderidentifier);
+               compose_set_save_to(compose, folderidentifier);
                g_free(folderidentifier);
        }
 
@@ -6486,15 +6566,12 @@ static GtkWidget *compose_create_others(Compose *compose)
 
        rowcount++;
 
-       compose->savemsg_checkbtn = savemsg_checkbtn;
-       compose->savemsg_entry = savemsg_entry;
-
        return table;   
 }
 
 static void compose_savemsg_checkbtn_cb(GtkWidget *widget, Compose *compose) 
 {
-       gtk_editable_set_editable(GTK_EDITABLE(compose->savemsg_entry),
+       gtk_widget_set_sensitive(GTK_WIDGET(compose->savemsg_combo),
                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn)));
 }
 
@@ -6508,7 +6585,7 @@ static void compose_savemsg_select_cb(GtkWidget *widget, Compose *compose)
 
        path = folder_item_get_identifier(dest);
 
-       gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), path);
+       compose_set_save_to(compose, path);
        g_free(path);
 }
 
@@ -6612,7 +6689,18 @@ static void compose_spell_menu_changed(void *data)
        g_slist_free(spell_menu);
 
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent_item), GTK_WIDGET(menu));
-       
+       gtk_widget_show(parent_item);
+}
+
+static void compose_dict_changed(void *data)
+{
+       Compose *compose = (Compose *) data;
+
+       if(compose->gtkaspell->recheck_when_changing_dict == FALSE)
+               return;
+
+       gtkaspell_highlight_all(compose->gtkaspell);
+       claws_spell_entry_recheck_all(CLAWS_SPELL_ENTRY(compose->subject_entry));
 }
 #endif
 
@@ -6712,7 +6800,7 @@ static Compose *compose_create(PrefsAccount *account,
                                      &geometry, GDK_HINT_MAX_SIZE);
        if (!geometry.min_width) {
                geometry.min_width = 600;
-               geometry.min_height = 480;
+               geometry.min_height = 440;
        }
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL,
                                      &geometry, GDK_HINT_MIN_SIZE);
@@ -6747,7 +6835,7 @@ static Compose *compose_create(PrefsAccount *account,
 #ifndef MAEMO
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_MENUBAR)
 #else
-       MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_MENU)
+       MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/", "Menu", NULL, GTK_UI_MANAGER_POPUP)
 #endif
 
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu", "Message", "Message", GTK_UI_MANAGER_MENU)
@@ -6998,7 +7086,11 @@ static Compose *compose_create(PrefsAccount *account,
        gtk_box_pack_start(GTK_BOX(subject), label, FALSE, FALSE, 0);
        gtk_widget_show(label);
 
+#ifdef USE_ENCHANT
+       subject_entry = claws_spell_entry_new();
+#else
        subject_entry = gtk_entry_new();
+#endif
        gtk_box_pack_start(GTK_BOX(subject), subject_entry, TRUE, TRUE, 0);
        g_signal_connect_after(G_OBJECT(subject_entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
@@ -7201,6 +7293,7 @@ static Compose *compose_create(PrefsAccount *account,
                                                  prefs_common.use_both_dicts,
                                                  GTK_TEXT_VIEW(text),
                                                  GTK_WINDOW(compose->window),
+                                                 compose_dict_changed,
                                                  compose_spell_menu_changed,
                                                  compose);
                        if (!gtkaspell) {
@@ -7215,6 +7308,7 @@ static Compose *compose_create(PrefsAccount *account,
        }
         compose->gtkaspell = gtkaspell;
        compose_spell_menu_changed(compose);
+       claws_spell_entry_set_gtkaspell(CLAWS_SPELL_ENTRY(subject_entry), gtkaspell);
 #endif
 
        compose_select_account(compose, account, TRUE);
@@ -8368,6 +8462,10 @@ static gboolean attach_property_key_pressed(GtkWidget *widget,
                *cancelled = TRUE;
                gtk_main_quit();
        }
+       if (event && event->keyval == GDK_Return) {
+               *cancelled = FALSE;
+               gtk_main_quit();
+       }
        return FALSE;
 }
 
@@ -8402,7 +8500,11 @@ static void compose_exec_ext_editor(Compose *compose)
 
                compose_set_ext_editor_sensitive(compose, FALSE);
 
+#ifndef G_OS_WIN32
                compose->exteditor_ch = g_io_channel_unix_new(pipe_fds[0]);
+#else
+               compose->exteditor_ch = g_io_channel_win32_new_fd(pipe_fds[0]);
+#endif
                compose->exteditor_tag = g_io_add_watch(compose->exteditor_ch,
                                                        G_IO_IN,
                                                        compose_input_cb,
@@ -8468,7 +8570,7 @@ static gint compose_exec_ext_editor_real(const gchar *file)
                g_snprintf(buf, sizeof(buf), prefs_common_get_ext_editor_cmd(), file);
        } else {
                if (prefs_common_get_ext_editor_cmd())
-                       g_warning("External editor command line is invalid: '%s'\n",
+                       g_warning("External editor command-line is invalid: '%s'\n",
                                  prefs_common_get_ext_editor_cmd());
                g_snprintf(buf, sizeof(buf), DEFAULT_EDITOR_CMD, file);
        }
@@ -8552,6 +8654,7 @@ static gboolean compose_input_cb(GIOChannel *source, GIOCondition condition,
                gtk_text_buffer_set_text(buffer, "", -1);
                compose_insert_file(compose, compose->exteditor_file);
                compose_changed_cb(NULL, compose);
+               compose_draft((gpointer)compose, COMPOSE_AUTO_SAVE);
 
                if (claws_unlink(compose->exteditor_file) < 0)
                        FILE_OP_ERROR(compose->exteditor_file, "unlink");
@@ -8720,11 +8823,11 @@ static void account_activated(GtkComboBox *optmenu, gpointer data)
        g_signal_connect(G_OBJECT(compose->savemsg_checkbtn), "toggled",
                         G_CALLBACK(compose_savemsg_checkbtn_cb), compose);
                           
-       gtk_editable_delete_text(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
+       compose_set_save_to(compose, NULL);
        if (account_get_special_folder(compose->account, F_OUTBOX)) {
                folderidentifier = folder_item_get_identifier(account_get_special_folder
                                  (compose->account, F_OUTBOX));
-               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               compose_set_save_to(compose, folderidentifier);
                g_free(folderidentifier);
        }
 }
@@ -8850,7 +8953,7 @@ static void compose_register_draft(MsgInfo *info)
 {
        gchar *filepath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                      DRAFTED_AT_EXIT, NULL);
-       FILE *fp = fopen(filepath, "ab");
+       FILE *fp = g_fopen(filepath, "ab");
        
        if (fp) {
                fprintf(fp, "%s\t%d\n", folder_item_get_identifier(info->folder), 
@@ -8913,7 +9016,7 @@ gboolean compose_draft (gpointer data, guint action)
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn))) {
                gchar *savefolderid;
 
-               savefolderid = gtk_editable_get_chars(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
+               savefolderid = compose_get_save_to(compose);
                err |= (fprintf(fp, "SCF:%s\n", savefolderid) < 0);
                g_free(savefolderid);
        }
@@ -9097,7 +9200,7 @@ void compose_reopen_exit_drafts(void)
 {
        gchar *filepath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                      DRAFTED_AT_EXIT, NULL);
-       FILE *fp = fopen(filepath, "rb");
+       FILE *fp = g_fopen(filepath, "rb");
        gchar buf[1024];
        
        if (fp) {
@@ -9122,7 +9225,9 @@ void compose_reopen_exit_drafts(void)
 
 static void compose_save_cb(GtkAction *action, gpointer data)
 {
-       compose_draft(data, COMPOSE_KEEP_EDITING);
+       Compose *compose = (Compose *)data;
+       compose_draft(compose, COMPOSE_KEEP_EDITING);
+       compose->rmode = COMPOSE_REEDIT;
 }
 
 static void compose_attach_from_list(Compose *compose, GList *file_list, gboolean free_data)
@@ -9391,6 +9496,8 @@ static void entry_paste_clipboard(Compose *compose, GtkWidget *entry,
                         * used for mid-click-pasting */
                        start = gtk_text_iter_get_offset(insert_place);
                        gtk_text_buffer_insert(buffer, insert_place, contents, strlen(contents));
+                       if (prefs_common.primary_paste_unselects)
+                               gtk_text_buffer_select_range(buffer, insert_place, insert_place);
                }
                
                if (!wrap) {
@@ -9924,6 +10031,7 @@ static void compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
 static void compose_changed_cb(GtkTextBuffer *textbuf, Compose *compose)
 {
        compose->modified = TRUE;
+//     compose_beautify_paragraph(compose, NULL, TRUE);
 #ifndef GENERIC_UMPC
        compose_set_title(compose);
 #endif
@@ -10013,9 +10121,11 @@ static void compose_attach_drag_received_cb (GtkWidget         *widget,
        Compose *compose = (Compose *)user_data;
        GList *list, *tmp;
 
-       if (gdk_atom_name(data->type) && 
-           !strcmp(gdk_atom_name(data->type), "text/uri-list")
-           && gtk_drag_get_source_widget(context) != 
+       if (((gdk_atom_name(data->type) && !strcmp(gdk_atom_name(data->type), "text/uri-list"))
+#ifdef G_OS_WIN32
+        || (gdk_atom_name(data->type) && !strcmp(gdk_atom_name(data->type), "DROPFILES_DND"))
+#endif
+          ) && gtk_drag_get_source_widget(context) != 
                summary_get_main_widget(mainwindow_get_mainwindow()->summaryview)) {
                list = uri_list_extract_filenames((const gchar *)data->data);
                for (tmp = list; tmp != NULL; tmp = tmp->next) {
@@ -10080,11 +10190,18 @@ static void compose_insert_drag_received_cb (GtkWidget                *widget,
 
        /* strangely, testing data->type == gdk_atom_intern("text/uri-list", TRUE)
         * does not work */
+       debug_print("drop: %s (%s)\n", gdk_atom_name(data->type)?gdk_atom_name(data->type):"nul",
+               (gchar *)(data->data?data->data:"nul"));
+#ifndef G_OS_WIN32
        if (gdk_atom_name(data->type) && !strcmp(gdk_atom_name(data->type), "text/uri-list")) {
+#else
+       if (gdk_atom_name(data->type) && !strcmp(gdk_atom_name(data->type), "DROPFILES_DND")) {
+#endif
                AlertValue val = G_ALERTDEFAULT;
 
                list = uri_list_extract_filenames((const gchar *)data->data);
-
+               debug_print("list: %p (%s)\n", list, 
+                       (gchar *)(data->data?data->data:"nul"));
                if (list == NULL && strstr((gchar *)(data->data), "://")) {
                        /* Assume a list of no files, and data has ://, is a remote link */
                        gchar *tmpdata = g_strstrip(g_strdup((const gchar *)data->data));
@@ -10386,35 +10503,54 @@ static gint compose_defer_auto_save_draft(Compose *compose)
 static void compose_check_all(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
-       if (compose->gtkaspell)
+       if (!compose->gtkaspell)
+               return;
+               
+       if (GTK_WIDGET_HAS_FOCUS(compose->subject_entry))
+               claws_spell_entry_check_all(
+                       CLAWS_SPELL_ENTRY(compose->subject_entry));             
+       else
                gtkaspell_check_all(compose->gtkaspell);
 }
 
 static void compose_highlight_all(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
-       if (compose->gtkaspell)
+       if (compose->gtkaspell) {
+               claws_spell_entry_recheck_all(
+                       CLAWS_SPELL_ENTRY(compose->subject_entry));
                gtkaspell_highlight_all(compose->gtkaspell);
+       }
 }
 
 static void compose_check_backwards(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
-       if (compose->gtkaspell) 
-               gtkaspell_check_backwards(compose->gtkaspell);
-       else {
+       if (!compose->gtkaspell) {
                cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Spelling", FALSE);
+               return;
        }
+
+       if (GTK_WIDGET_HAS_FOCUS(compose->subject_entry))
+               claws_spell_entry_check_backwards(
+                       CLAWS_SPELL_ENTRY(compose->subject_entry));
+       else
+               gtkaspell_check_backwards(compose->gtkaspell);
 }
 
 static void compose_check_forwards_go(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
-       if (compose->gtkaspell) 
-               gtkaspell_check_forwards_go(compose->gtkaspell);
-       else {
+       if (!compose->gtkaspell) {
                cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Spelling", FALSE);
+               return;
        }
+
+       if (GTK_WIDGET_HAS_FOCUS(compose->subject_entry))
+               claws_spell_entry_check_forwards_go(
+                       CLAWS_SPELL_ENTRY(compose->subject_entry));
+       else
+               gtkaspell_check_forwards_go(compose->gtkaspell);
 }
 #endif
 
@@ -10515,6 +10651,7 @@ static void compose_reply_from_messageview_real(MessageView *msgview, GSList *ms
        gboolean originally_enc = FALSE;
        gboolean originally_sig = FALSE;
        Compose *compose = NULL;
+       gchar *s_system = NULL;
 
        g_return_if_fail(msgview != NULL);
 
@@ -10532,7 +10669,7 @@ static void compose_reply_from_messageview_real(MessageView *msgview, GSList *ms
                                new_msglist = g_slist_append(NULL, tmp_msginfo);
 
                                originally_enc = MSG_IS_ENCRYPTED(orig_msginfo->flags);
-                               privacy_msginfo_get_signed_state(orig_msginfo);
+                               privacy_msginfo_get_signed_state(orig_msginfo, &s_system);
                                originally_sig = MSG_IS_SIGNED(orig_msginfo->flags);
 
                                tmp_msginfo->folder = orig_msginfo->folder;
@@ -10554,13 +10691,13 @@ static void compose_reply_from_messageview_real(MessageView *msgview, GSList *ms
                compose = compose_reply_mode((ComposeMode)action, msginfo_list, body);
 
        if (compose && originally_enc) {
-               compose_force_encryption(compose, compose->account, FALSE);
+               compose_force_encryption(compose, compose->account, FALSE, s_system);
        }
 
        if (compose && originally_sig && compose->account->default_sign_reply) {
-               compose_force_signing(compose, compose->account);
+               compose_force_signing(compose, compose->account, s_system);
        }
-
+       g_free(s_system);
        g_free(body);
 }