2007-04-25 [colin] 2.9.1cvs24
[claws.git] / src / compose.c
index 2df9191b1d23dc762e7e1e9303395c81de097262..7ebe66e7f7cd04240733ec078659ab28cc538846 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team
+ * Copyright (C) 1999-2007 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
@@ -81,7 +81,7 @@
 #  include <wctype.h>
 #endif
 
-#include "sylpheed.h"
+#include "claws.h"
 #include "main.h"
 #include "mainwindow.h"
 #include "compose.h"
 #include "inc.h"
 #include "message_search.h"
 #include "combobox.h"
+#include "hooks.h"
 
 enum
 {
@@ -170,13 +171,6 @@ typedef enum
        COMPOSE_INSERT_NO_FILE
 } ComposeInsertResult;
 
-typedef enum
-{
-       COMPOSE_QUIT_EDITING,
-       COMPOSE_KEEP_EDITING,
-       COMPOSE_AUTO_SAVE
-} ComposeDraftAction;
-
 typedef enum
 {
        COMPOSE_WRITE_FOR_SEND,
@@ -190,7 +184,7 @@ typedef enum
 
 static GList *compose_list = NULL;
 
-Compose *compose_generic_new                   (PrefsAccount   *account,
+static Compose *compose_generic_new                    (PrefsAccount   *account,
                                                 const gchar    *to,
                                                 FolderItem     *item,
                                                 GPtrArray      *attach_files,
@@ -200,6 +194,27 @@ static Compose *compose_create                     (PrefsAccount   *account,
                                                 ComposeMode     mode,
                                                 gboolean batch);
 
+static void compose_entry_mark_default_to      (Compose          *compose,
+                                        const gchar      *address);
+static Compose *compose_followup_and_reply_to  (MsgInfo        *msginfo,
+                                        gboolean        quote,
+                                        gboolean        to_all,
+                                        gboolean        to_sender,
+                                        const gchar    *body);
+static Compose *compose_forward_multiple       (PrefsAccount   *account, 
+                                        GSList         *msginfo_list);
+static Compose *compose_reply                  (MsgInfo        *msginfo,
+                                        gboolean        quote,
+                                        gboolean        to_all,
+                                        gboolean        to_ml,
+                                        gboolean        to_sender,
+                                        const gchar    *body);
+static Compose *compose_reply_mode             (ComposeMode     mode, 
+                                        GSList         *msginfo_list, 
+                                        gchar          *body);
+static void compose_template_apply_fields(Compose *compose, Template *tmpl);
+static void compose_update_privacy_systems_menu(Compose        *compose);
+
 static GtkWidget *compose_account_option_menu_create
                                                (Compose        *compose);
 static void compose_set_out_encoding           (Compose        *compose);
@@ -221,7 +236,9 @@ static gchar *compose_quote_fmt                     (Compose        *compose,
                                                 const gchar    *fmt,
                                                 const gchar    *qmark,
                                                 const gchar    *body,
-                                                gboolean        rewrap);
+                                                gboolean        rewrap,
+                                                gboolean        need_unescape,
+                                                const gchar *err_msg);
 
 static void compose_reply_set_entry            (Compose        *compose,
                                                 MsgInfo        *msginfo,
@@ -239,7 +256,7 @@ static gchar *compose_get_signature_str             (Compose        *compose);
 static ComposeInsertResult compose_insert_file (Compose        *compose,
                                                 const gchar    *file);
 
-static void compose_attach_append              (Compose        *compose,
+static gboolean compose_attach_append          (Compose        *compose,
                                                 const gchar    *file,
                                                 const gchar    *type,
                                                 const gchar    *content_type);
@@ -263,7 +280,7 @@ static PrefsAccount *compose_current_mail_account(void);
 static gboolean compose_check_for_valid_recipient
                                                (Compose        *compose);
 static gboolean compose_check_entries          (Compose        *compose,
-                                                gboolean       check_subject);
+                                                gboolean       check_everything);
 static gint compose_write_to_file              (Compose        *compose,
                                                 FILE           *fp,
                                                 gint            action,
@@ -272,7 +289,7 @@ 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 void compose_remove_draft                       (Compose        *compose);
 static gint compose_queue_sub                  (Compose        *compose,
                                                 gint           *msgnum,
                                                 FolderItem     **item,
@@ -323,7 +340,9 @@ static void compose_undo_state_changed              (UndoMain       *undostruct,
                                                 gpointer        data);
 
 static void compose_create_header_entry        (Compose *compose);
-static void compose_add_header_entry   (Compose *compose, gchar *header, gchar *text);
+static void compose_add_header_entry   (Compose *compose, const gchar *header, gchar *text);
+static void compose_remove_header_entries(Compose *compose);
+
 static void compose_update_priority_menu_item(Compose * compose);
 #if USE_ASPELL
 static void compose_spell_menu_changed (void *data);
@@ -348,7 +367,6 @@ static gboolean attach_button_pressed       (GtkWidget      *widget,
 static gboolean attach_key_pressed     (GtkWidget      *widget,
                                         GdkEventKey    *event,
                                         gpointer        data);
-
 static void compose_send_cb            (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
@@ -445,6 +463,9 @@ static void compose_toggle_remove_refs_cb(gpointer data, guint action,
 static void compose_set_priority_cb    (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
+static void compose_reply_change_mode  (gpointer        data,
+                                        ComposeMode    action,
+                                        GtkWidget      *widget);
 
 static void compose_attach_drag_received_cb (GtkWidget         *widget,
                                             GdkDragContext     *drag_context,
@@ -487,9 +508,9 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                                  gboolean followup_and_reply_to,
                                  const gchar *body);
 
-gboolean compose_headerentry_changed_cb           (GtkWidget          *entry,
+static gboolean compose_headerentry_changed_cb    (GtkWidget          *entry,
                                            ComposeHeaderEntry *headerentry);
-gboolean compose_headerentry_key_press_event_cb(GtkWidget             *entry,
+static gboolean compose_headerentry_key_press_event_cb(GtkWidget              *entry,
                                            GdkEventKey        *event,
                                            ComposeHeaderEntry *headerentry);
 
@@ -507,18 +528,25 @@ 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 MsgInfo *compose_msginfo_new_from_compose(Compose *compose);
+
+#ifdef USE_ASPELL
+static void compose_set_dictionaries_from_folder_prefs(Compose *compose,
+                                               FolderItem *folder_item);
+#endif
+
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
        {N_("/_Add..."),        NULL, compose_attach_cb, 0, NULL},
        {N_("/_Remove"),        NULL, compose_attach_remove_selected, 0, NULL},
-       {N_("/---"),            NULL, NULL, 0, "<Separator>"},
+       {"/---",                NULL, NULL, 0, "<Separator>"},
        {N_("/_Properties..."), NULL, compose_attach_property, 0, NULL}
 };
 
 static GtkItemFactoryEntry compose_entries[] =
 {
        {N_("/_Message"),                               NULL, NULL, 0, "<Branch>"},
-       {N_("/_Message/_Send"),         "<control>Return",
+       {N_("/_Message/S_end"),         "<control>Return",
                                        compose_send_cb, 0, NULL},
        {N_("/_Message/Send _later"),   "<shift><control>S",
                                        compose_send_later_cb,  0, NULL},
@@ -650,8 +678,14 @@ static GtkItemFactoryEntry compose_entries[] =
                                        NULL, NULL, 0, "<Branch>"},
 #endif
        {N_("/_Options"),               NULL, NULL, 0, "<Branch>"},
-       {N_("/_Options/Privacy System"),                NULL, NULL,   0, "<Branch>"},
-       {N_("/_Options/Privacy System/None"),   NULL, NULL,   0, "<RadioItem>"},
+       {N_("/_Options/Reply _mode"),           NULL, NULL,   0, "<Branch>"},
+       {N_("/_Options/Reply _mode/_Normal"),   NULL, compose_reply_change_mode,   COMPOSE_REPLY, "<RadioItem>"},
+       {N_("/_Options/Reply _mode/_All"),              NULL, compose_reply_change_mode,   COMPOSE_REPLY_TO_ALL, "/Options/Reply mode/Normal"},
+       {N_("/_Options/Reply _mode/_Sender"),           NULL, compose_reply_change_mode,   COMPOSE_REPLY_TO_SENDER, "/Options/Reply mode/Normal"},
+       {N_("/_Options/Reply _mode/_Mailing-list"),     NULL, compose_reply_change_mode,   COMPOSE_REPLY_TO_LIST, "/Options/Reply mode/Normal"},
+       {N_("/_Options/---"),           NULL,           NULL,   0, "<Separator>"},
+       {N_("/_Options/Privacy _System"),               NULL, NULL,   0, "<Branch>"},
+       {N_("/_Options/Privacy _System/None"),  NULL, NULL,   0, "<RadioItem>"},
        {N_("/_Options/Si_gn"),         NULL, compose_toggle_sign_cb   , 0, "<ToggleItem>"},
        {N_("/_Options/_Encrypt"),      NULL, compose_toggle_encrypt_cb, 0, "<ToggleItem>"},
        {N_("/_Options/---"),           NULL,           NULL,   0, "<Separator>"},
@@ -765,8 +799,8 @@ static GtkItemFactoryEntry compose_entries[] =
 static GtkTargetEntry compose_mime_types[] =
 {
        {"text/uri-list", 0, 0},
-       {"text/plain", 0, 0},
-       {"STRING", 0, 0}
+       {"UTF8_STRING", 0, 0},
+       {"text/plain", 0, 0}
 };
 
 static gboolean compose_put_existing_to_front(MsgInfo *info)
@@ -918,9 +952,9 @@ Compose *compose_new(PrefsAccount *account, const gchar *mailto,
        return compose_generic_new(account, mailto, NULL, attach_files, NULL);
 }
 
-Compose *compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
+Compose *compose_new_with_folderitem(PrefsAccount *account, FolderItem *item, const gchar *mailto)
 {
-       return compose_generic_new(account, NULL, item, NULL, NULL);
+       return compose_generic_new(account, mailto, item, NULL, NULL);
 }
 
 Compose *compose_new_with_list( PrefsAccount *account, GList *listAddress )
@@ -956,11 +990,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
        undo_block(compose->undostruct);
 #ifdef USE_ASPELL
-       if (item && item->prefs && item->prefs->enable_default_dictionary &&
-           compose->gtkaspell) 
-               gtkaspell_change_dict(compose->gtkaspell, 
-                   item->prefs->default_dictionary);
-       compose_spell_menu_changed(compose);
+       compose_set_dictionaries_from_folder_prefs(compose, item);
 #endif
 
        if (account->auto_sig)
@@ -982,7 +1012,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        } else {
                if (mailto) {
                        compose_entry_append(compose, mailto, COMPOSE_NEWSGROUPS);
-               } else if (item) {
+               } else if (item && FOLDER_CLASS(item->folder) == news_get_class()) {
                        compose_entry_append(compose, item->path, COMPOSE_NEWSGROUPS);
                }
                /*
@@ -993,6 +1023,67 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        }
        compose_add_field_list( compose, listAddress );
 
+       if (prefs_common.compose_with_format) {
+               MsgInfo* dummyinfo = NULL;
+
+               if ( prefs_common.compose_subject_format
+                        && *prefs_common.compose_subject_format != '\0' )
+               {
+                       gchar *subject = NULL;
+                       gchar *tmp = NULL;
+                       gchar *buf = NULL;
+
+                       dummyinfo = compose_msginfo_new_from_compose(compose);
+
+                       /* decode \-escape sequences in the internal representation of the quote format */
+                       tmp = malloc(strlen(prefs_common.compose_subject_format)+1);
+                       pref_get_unescaped_pref(tmp, prefs_common.compose_subject_format);
+
+                       subject = gtk_editable_get_chars(GTK_EDITABLE(compose->subject_entry), 0, -1);
+                       quote_fmt_init(dummyinfo, NULL, subject, FALSE, compose->account);
+                       quote_fmt_scan_string(tmp);
+                       quote_fmt_parse();
+
+                       buf = quote_fmt_get_buffer();
+                       if (buf == NULL)
+                               alertpanel_error(_("New message subject format error."));
+                       else
+                               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf);
+                       quote_fmt_reset_vartable();
+
+                       g_free(subject);
+                       g_free(tmp);
+               }
+
+               if ( prefs_common.compose_body_format
+                        && *prefs_common.compose_body_format != '\0' )
+               {
+                       GtkTextView *text;
+                       GtkTextBuffer *buffer;
+                       GtkTextIter start, end;
+                       gchar *tmp = NULL;
+
+                       if ( dummyinfo == NULL )
+                               dummyinfo = compose_msginfo_new_from_compose(compose);
+
+                       text = GTK_TEXT_VIEW(compose->text);
+                       buffer = gtk_text_view_get_buffer(text);
+                       gtk_text_buffer_get_start_iter(buffer, &start);
+                       gtk_text_buffer_get_iter_at_offset(buffer, &end, -1);
+                       tmp = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+                       compose_quote_fmt(compose, dummyinfo,
+                                         prefs_common.compose_body_format,
+                                         NULL, tmp, FALSE, TRUE,
+                                                 _("New message body format error."));
+                       quote_fmt_reset_vartable();
+
+                       g_free(tmp);
+               }
+
+               procmsg_msginfo_free( dummyinfo );
+       }
+
        if (attach_files) {
                gint i;
                gchar *file;
@@ -1048,7 +1139,8 @@ static void compose_force_encryption(Compose *compose, PrefsAccount *account,
                }
        }
        if (privacy != NULL) {
-               compose->privacy_system = g_strdup(privacy);
+               if (compose->privacy_system == NULL)
+                       compose->privacy_system = g_strdup(privacy);
                compose_update_privacy_system_menu_item(compose, FALSE);
                compose_use_encryption(compose, TRUE);
        }
@@ -1068,17 +1160,20 @@ static void compose_force_signing(Compose *compose, PrefsAccount *account)
                }
        }
        if (privacy != NULL) {
-               compose->privacy_system = g_strdup(privacy);
+               if (compose->privacy_system == NULL)
+                       compose->privacy_system = g_strdup(privacy);
                compose_update_privacy_system_menu_item(compose, FALSE);
                compose_use_signing(compose, TRUE);
        }
 }      
 
-Compose *compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar *body)
+static Compose *compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar *body)
 {
        MsgInfo *msginfo;
        guint list_len;
        Compose *compose = NULL;
+       GtkItemFactory *ifactory = NULL;
+       
        g_return_val_if_fail(msginfo_list != NULL, NULL);
 
        msginfo = (MsgInfo*)g_slist_nth_data(msginfo_list, 0);
@@ -1165,10 +1260,44 @@ Compose *compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar *body)
        default:
                g_warning("compose_reply(): invalid Compose Mode: %d\n", mode);
        }
+       
+       ifactory = gtk_item_factory_from_widget(compose->menubar);
+
+       compose->rmode = mode;
+       switch (compose->rmode) {
+       case COMPOSE_REPLY:
+       case COMPOSE_REPLY_WITH_QUOTE:
+       case COMPOSE_REPLY_WITHOUT_QUOTE:
+       case COMPOSE_FOLLOWUP_AND_REPLY_TO:
+               debug_print("reply mode Normal\n");
+               menu_set_active(ifactory, "/Options/Reply mode/Normal", TRUE);
+               compose_reply_change_mode(compose, COMPOSE_REPLY, NULL); /* force update */
+               break;
+       case COMPOSE_REPLY_TO_SENDER:
+       case COMPOSE_REPLY_TO_SENDER_WITH_QUOTE:
+       case COMPOSE_REPLY_TO_SENDER_WITHOUT_QUOTE:
+               debug_print("reply mode Sender\n");
+               menu_set_active(ifactory, "/Options/Reply mode/Sender", TRUE);
+               break;
+       case COMPOSE_REPLY_TO_ALL:
+       case COMPOSE_REPLY_TO_ALL_WITH_QUOTE:
+       case COMPOSE_REPLY_TO_ALL_WITHOUT_QUOTE:
+               debug_print("reply mode All\n");
+               menu_set_active(ifactory, "/Options/Reply mode/All", TRUE);
+               break;
+       case COMPOSE_REPLY_TO_LIST:
+       case COMPOSE_REPLY_TO_LIST_WITH_QUOTE:
+       case COMPOSE_REPLY_TO_LIST_WITHOUT_QUOTE:
+               debug_print("reply mode List\n");
+               menu_set_active(ifactory, "/Options/Reply mode/Mailing-list", TRUE);
+               break;
+       default:
+               break;
+       }
        return compose;
 }
 
-Compose *compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all,
+static Compose *compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all,
                   gboolean to_ml, gboolean to_sender, 
                   const gchar *body)
 {
@@ -1176,7 +1305,7 @@ Compose *compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all,
                              to_sender, FALSE, body);
 }
 
-Compose *compose_followup_and_reply_to(MsgInfo *msginfo, gboolean quote,
+static Compose *compose_followup_and_reply_to(MsgInfo *msginfo, gboolean quote,
                                   gboolean to_all,
                                   gboolean to_sender,
                                   const gchar *body)
@@ -1244,7 +1373,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        g_return_val_if_fail(msginfo->folder != NULL, NULL);
 
        account = account_get_reply_account(msginfo, prefs_common.reply_account_autosel);
-       
+
        g_return_val_if_fail(account != NULL, NULL);
 
        if (to_sender && account->protocol == A_NNTP &&
@@ -1287,9 +1416,6 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        }
 
        if (compose_parse_header(compose, msginfo) < 0) return NULL;
-       compose_reply_set_entry(compose, msginfo, to_all, to_ml, 
-                               to_sender, followup_and_reply_to);
-       compose_show_first_last_header(compose, TRUE);
 
        textview = (GTK_TEXT_VIEW(compose->text));
        textbuf = gtk_text_view_get_buffer(textview);
@@ -1297,12 +1423,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
 
        undo_block(compose->undostruct);
 #ifdef USE_ASPELL
-       if (msginfo->folder && msginfo->folder->prefs && 
-           msginfo->folder->prefs && 
-           msginfo->folder->prefs->enable_default_dictionary &&
-           compose->gtkaspell)
-               gtkaspell_change_dict(compose->gtkaspell, 
-                   msginfo->folder->prefs->default_dictionary);
+               compose_set_dictionaries_from_folder_prefs(compose, msginfo->folder);
 #endif
 
        if (quote) {
@@ -1315,7 +1436,9 @@ static Compose *compose_generic_reply(MsgInfo *msginfo, gboolean quote,
 
                compose_quote_fmt(compose, compose->replyinfo,
                                  prefs_common.quotefmt,
-                                 qmark, body, FALSE);
+                                 qmark, body, FALSE, TRUE,
+                                         _("Message reply format error."));
+               quote_fmt_reset_vartable();
        }
        if (procmime_msginfo_is_encrypted(compose->replyinfo)) {
                compose_force_encryption(compose, account, FALSE);
@@ -1430,7 +1553,9 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 
                compose_quote_fmt(compose, full_msginfo,
                                  prefs_common.fw_quotefmt,
-                                 qmark, body, FALSE);
+                                 qmark, body, FALSE, TRUE,
+                                         _("Message forward format error."));
+               quote_fmt_reset_vartable();
                compose_attach_parts(compose, msginfo);
 
                procmsg_msginfo_free(full_msginfo);
@@ -1480,7 +1605,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
 
 #undef INSERT_FW_HEADER
 
-Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_list)
+static Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_list)
 {
        Compose *compose;
        GtkTextView *textview;
@@ -1639,6 +1764,8 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
        gboolean use_signing = FALSE;
        gboolean use_encryption = FALSE;
        gchar *privacy_system = NULL;
+       int priority = PRIORITY_NORMAL;
+       MsgInfo *replyinfo = NULL, *fwdinfo = NULL;
 
        g_return_val_if_fail(msginfo != NULL, NULL);
        g_return_val_if_fail(msginfo->folder != NULL, NULL);
@@ -1653,6 +1780,11 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
                gint id, param;
 
                /* Select Account from queue headers */
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
+                                            sizeof(queueheader_buf), "X-Claws-Account-Id:")) {
+                       id = atoi(&queueheader_buf[strlen("X-Claws-Account-Id:")]);
+                       account = account_find_from_id(id);
+               }
                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "X-Sylpheed-Account-Id:")) {
                        id = atoi(&queueheader_buf[strlen("X-Sylpheed-Account-Id:")]);
@@ -1672,17 +1804,32 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
                                                                sizeof(queueheader_buf), "S:")) {
                        account = account_find_from_address(queueheader_buf);
                }
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
+                                            sizeof(queueheader_buf), "X-Claws-Sign:")) {
+                       param = atoi(&queueheader_buf[strlen("X-Claws-Sign:")]);
+                       use_signing = param;
+                       
+               }
                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "X-Sylpheed-Sign:")) {
                        param = atoi(&queueheader_buf[strlen("X-Sylpheed-Sign:")]);
                        use_signing = param;
                        
                }
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
+                                            sizeof(queueheader_buf), "X-Claws-Encrypt:")) {
+                       param = atoi(&queueheader_buf[strlen("X-Claws-Encrypt:")]);
+                       use_encryption = param;
+               }
                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "X-Sylpheed-Encrypt:")) {
                        param = atoi(&queueheader_buf[strlen("X-Sylpheed-Encrypt:")]);
                        use_encryption = param;
                }
+                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
+                                            sizeof(queueheader_buf), "X-Claws-Privacy-System:")) {
+                        privacy_system = g_strdup(&queueheader_buf[strlen("X-Claws-Privacy-System:")]);
+                }
                 if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "X-Sylpheed-Privacy-System:")) {
                         privacy_system = g_strdup(&queueheader_buf[strlen("X-Sylpheed-Privacy-System:")]);
@@ -1690,7 +1837,29 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
                if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
                                             sizeof(queueheader_buf), "X-Priority: ")) {
                        param = atoi(&queueheader_buf[strlen("X-Priority: ")]); /* mind the space */
-                       compose->priority = param;
+                       priority = param;
+               }
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
+                                            sizeof(queueheader_buf), "RMID:")) {
+                       gchar **tokens = g_strsplit(&queueheader_buf[strlen("RMID:")], "\t", 0);
+                       if (tokens[0] && tokens[1] && tokens[2]) {
+                               FolderItem *orig_item = folder_find_item_from_identifier(tokens[0]);
+                               if (orig_item != NULL) {
+                                       replyinfo = folder_item_get_msginfo_by_msgid(orig_item, tokens[2]);
+                               }
+                       }
+                       g_strfreev(tokens);
+               }
+               if (!procheader_get_header_from_msginfo(msginfo, queueheader_buf, 
+                                            sizeof(queueheader_buf), "FMID:")) {
+                       gchar **tokens = g_strsplit(&queueheader_buf[strlen("FMID:")], "\t", 0);
+                       if (tokens[0] && tokens[1] && tokens[2]) {
+                               FolderItem *orig_item = folder_find_item_from_identifier(tokens[0]);
+                               if (orig_item != NULL) {
+                                       fwdinfo = folder_item_get_msginfo_by_msgid(orig_item, tokens[2]);
+                               }
+                       }
+                       g_strfreev(tokens);
                }
        } else {
                account = msginfo->folder->folder->account;
@@ -1710,8 +1879,12 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
 
        compose = compose_create(account, COMPOSE_REEDIT, batch);
        
+       compose->replyinfo = replyinfo;
+       compose->fwdinfo = fwdinfo;
+
        compose->updating = TRUE;
-       
+       compose->priority = priority;
+
        if (privacy_system != NULL) {
                compose->privacy_system = privacy_system;
                compose_use_signing(compose, use_signing);
@@ -1875,7 +2048,9 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
                                   msginfo->subject);
        gtk_editable_set_editable(GTK_EDITABLE(compose->subject_entry), FALSE);
 
-       compose_quote_fmt(compose, msginfo, "%M", NULL, NULL, FALSE);
+       compose_quote_fmt(compose, msginfo, "%M", NULL, NULL, FALSE, FALSE,
+                                         _("Message redirect format error."));
+       quote_fmt_reset_vartable();
        gtk_text_view_set_editable(GTK_TEXT_VIEW(compose->text), FALSE);
 
        compose_colorize_signature(compose);
@@ -1930,7 +2105,7 @@ GList *compose_get_compose_list(void)
 void compose_entry_append(Compose *compose, const gchar *address,
                          ComposeEntryType type)
 {
-       gchar *header;
+       const gchar *header;
        gchar *cur, *begin;
        gboolean in_quote = FALSE;
        if (!address || *address == '\0') return;
@@ -1956,7 +2131,7 @@ void compose_entry_append(Compose *compose, const gchar *address,
                header = N_("To:");
                break;
        }
-       header = prefs_common.trans_hdr ? gettext(header) : header;
+       header = prefs_common_translated_header_name(header);
        
        cur = begin = (gchar *)address;
        
@@ -1992,7 +2167,7 @@ void compose_entry_append(Compose *compose, const gchar *address,
        }
 }
 
-void compose_entry_mark_default_to(Compose *compose, const gchar *mailto)
+static void compose_entry_mark_default_to(Compose *compose, const gchar *mailto)
 {
        static GdkColor yellow;
        static GdkColor black;
@@ -2080,9 +2255,10 @@ static void compose_entries_set(Compose *compose, const gchar *mailto)
        gchar *subject = NULL;
        gchar *body = NULL;
        gchar *temp = NULL;
-       gint  len = 0;
-
-       scan_mailto_url(mailto, &to, &cc, NULL, &subject, &body);
+       gsize  len = 0;
+       gchar *attach = NULL;
+       
+       scan_mailto_url(mailto, &to, &cc, NULL, &subject, &body, &attach);
 
        if (to)
                compose_entry_append(compose, to, COMPOSE_TO);
@@ -2123,10 +2299,22 @@ static void compose_entries_set(Compose *compose, const gchar *mailto)
                        compose_wrap_all(compose);
        }
 
+       if (attach) {
+               gchar *utf8_filename = conv_filename_to_utf8(attach);
+               if (utf8_filename) {
+                       if (compose_attach_append(compose, attach, utf8_filename, NULL)) {
+                               alertpanel_notice(_("The file '%s' has been attached."), attach);
+                       } 
+                       g_free(utf8_filename);
+               } else {
+                       alertpanel_error(_("Couldn't attach a file (charset conversion failed)."));
+               }
+       }
        g_free(to);
        g_free(cc);
        g_free(subject);
        g_free(body);
+       g_free(attach);
 }
 
 static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
@@ -2211,7 +2399,7 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
                extract_address(hentry[H_LIST_POST].body);
                if (hentry[H_LIST_POST].body[0] != '\0') {
                        scan_mailto_url(hentry[H_LIST_POST].body,
-                                       &to, NULL, NULL, NULL, NULL);
+                                       &to, NULL, NULL, NULL, NULL, NULL);
                        if (to) {
                                g_free(compose->ml_post);
                                compose->ml_post = to;
@@ -2320,9 +2508,11 @@ static gchar *compose_parse_references(const gchar *ref, const gchar *msgid)
 
 static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                                const gchar *fmt, const gchar *qmark,
-                               const gchar *body, gboolean rewrap)
+                               const gchar *body, gboolean rewrap,
+                               gboolean need_unescape,
+                               const gchar *err_msg)
 {
-       static MsgInfo dummyinfo;
+       MsgInfo* dummyinfo = NULL;
        gchar *quote_str = NULL;
        gchar *buf;
        gboolean prev_autowrap;
@@ -2336,11 +2526,13 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
 
        SIGNAL_BLOCK(buffer);
 
-       if (!msginfo)
-               msginfo = &dummyinfo;
+       if (!msginfo) {
+               dummyinfo = compose_msginfo_new_from_compose(compose);
+               msginfo = dummyinfo;
+       }
 
        if (qmark != NULL) {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
                quote_fmt_scan_string(qmark);
                quote_fmt_parse();
 
@@ -2352,17 +2544,29 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
        }
 
        if (fmt && *fmt != '\0') {
-               while (trimmed_body && strlen(trimmed_body) > 1
-                       && trimmed_body[0]=='\n')
-                       *trimmed_body++;
 
-               quote_fmt_init(msginfo, quote_str, trimmed_body, FALSE);
-               quote_fmt_scan_string(fmt);
-               quote_fmt_parse();
+               if (trimmed_body)
+                       while (*trimmed_body == '\n')
+                               trimmed_body++;
+
+               quote_fmt_init(msginfo, quote_str, trimmed_body, FALSE, compose->account);
+               if (need_unescape) {
+                       gchar *tmp = NULL;
+
+                       /* decode \-escape sequences in the internal representation of the quote format */
+                       tmp = malloc(strlen(fmt)+1);
+                       pref_get_unescaped_pref(tmp, fmt);
+                       quote_fmt_scan_string(tmp);
+                       quote_fmt_parse();
+                       g_free(tmp);
+               } else {
+                       quote_fmt_scan_string(fmt);
+                       quote_fmt_parse();
+               }
 
                buf = quote_fmt_get_buffer();
                if (buf == NULL) {
-                       alertpanel_error(_("Message reply/forward format error."));
+                       alertpanel_error(err_msg);
                        goto error;
                }
        } else
@@ -2409,6 +2613,7 @@ error:
 ok:
        SIGNAL_UNBLOCK(buffer);
 
+       procmsg_msginfo_free( dummyinfo );
 
        return buf;
 }
@@ -2463,7 +2668,7 @@ static gboolean same_address(const gchar *addr1, const gchar *addr2)
        extract_address(my_addr1);
        extract_address(my_addr2);
        
-       return !strcmp(my_addr1, my_addr2);
+       return !strcasecmp(my_addr1, my_addr2);
 }
 
 static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
@@ -2535,13 +2740,21 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                          msginfo->from ? msginfo->from : "",
                                          COMPOSE_TO);
                        else if (!to_all && !to_sender) {
-                               /* reply to the last list of recipients */
-                               compose_entry_append(compose,
-                                         msginfo->to ? msginfo->to : "",
-                                         COMPOSE_TO);
-                               compose_entry_append(compose,
-                                         msginfo->cc ? msginfo->cc : "",
-                                         COMPOSE_CC);
+                               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)) {
+                                       compose_entry_append(compose,
+                                                 msginfo->from ? msginfo->from : "",
+                                                 COMPOSE_TO);
+                               } else {
+                                       /* replying to own mail, use original recp */
+                                       compose_entry_append(compose,
+                                                 msginfo->to ? msginfo->to : "",
+                                                 COMPOSE_TO);
+                                       compose_entry_append(compose,
+                                                 msginfo->cc ? msginfo->cc : "",
+                                                 COMPOSE_CC);
+                               }
                        }
                }
        } else {
@@ -2576,7 +2789,7 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
 
        if (msginfo->subject && *msginfo->subject) {
                gchar *buf, *buf2;
-               guchar *p;
+               gchar *p;
 
                buf = p = g_strdup(msginfo->subject);
                p += subject_get_prefix_length(p);
@@ -2613,17 +2826,17 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
 
        to_table = g_hash_table_new(g_str_hash, g_str_equal);
        if (replyto)
-               g_hash_table_insert(to_table, g_strdup(replyto), GINT_TO_POINTER(1));
-       if (compose->account)
-               g_hash_table_insert(to_table, g_strdup(compose->account->address),
+               g_hash_table_insert(to_table, g_utf8_strdown(replyto, -1), GINT_TO_POINTER(1));
+       if (compose->account) {
+               g_hash_table_insert(to_table, g_utf8_strdown(compose->account->address, -1),
                                    GINT_TO_POINTER(1));
-
+       }
        /* remove address on To: and that of current account */
        for (cur = cc_list; cur != NULL; ) {
                GSList *next = cur->next;
                gchar *addr;
 
-               addr = g_strdup(cur->data);
+               addr = g_utf8_strdown(cur->data, -1);
                extract_address(addr);
 
                if (GPOINTER_TO_INT(g_hash_table_lookup(to_table, addr)) == 1)
@@ -2896,7 +3109,7 @@ static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *fi
                return COMPOSE_INSERT_SUCCESS;
 }
 
-static void compose_attach_append(Compose *compose, const gchar *file,
+static gboolean compose_attach_append(Compose *compose, const gchar *file,
                                  const gchar *filename,
                                  const gchar *content_type)
 {
@@ -2911,20 +3124,31 @@ static void compose_attach_append(Compose *compose, const gchar *file,
        gboolean has_binary = FALSE;
 
        if (!is_file_exist(file)) {
-               g_warning("File %s doesn't exist\n", filename);
-               return;
+               gchar *file_from_uri = g_filename_from_uri(file, NULL, NULL);
+               gboolean result = FALSE;
+               if (file_from_uri && is_file_exist(file_from_uri)) {
+                       result = compose_attach_append(
+                                               compose, file_from_uri,
+                                               filename,
+                                               content_type);
+               }
+               g_free(file_from_uri);
+               if (result)
+                       return TRUE;
+               alertpanel_error("File %s doesn't exist\n", filename);
+               return FALSE;
        }
        if ((size = get_file_size(file)) < 0) {
-               g_warning("Can't get file size of %s\n", filename);
-               return;
+               alertpanel_error("Can't get file size of %s\n", filename);
+               return FALSE;
        }
        if (size == 0) {
-               alertpanel_notice(_("File %s is empty."), filename);
-               return;
+               alertpanel_error(_("File %s is empty."), filename);
+               return FALSE;
        }
        if ((fp = g_fopen(file, "rb")) == NULL) {
                alertpanel_error(_("Can't read %s."), filename);
-               return;
+               return FALSE;
        }
        fclose(fp);
 
@@ -2978,6 +3202,12 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                g_free(name);
        }
 
+       if (ainfo->name != NULL
+       &&  !strcmp(ainfo->name, ".")) {
+               g_free(ainfo->name);
+               ainfo->name = NULL;
+       }
+
        if (!strcmp(ainfo->content_type, "unknown") || has_binary) {
                g_free(ainfo->content_type);
                ainfo->content_type = g_strdup("application/octet-stream");
@@ -2999,6 +3229,7 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                           -1);
        
        g_auto_pointer_free(auto_ainfo);
+       return TRUE;
 }
 
 static void compose_use_signing(Compose *compose, gboolean use_signing)
@@ -3070,6 +3301,8 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
      
        child = (MimeInfo *) mimeinfo->node->children->data;
        while (child != NULL) {
+               gint err;
+
                if (child == encrypted) {
                        /* skip this part of tree */
                        NEXT_PART_NOT_CHILD(child);
@@ -3088,8 +3321,8 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
                }
 
                outfile = procmime_get_tmp_file_name(child);
-               if (procmime_get_part(outfile, child) < 0)
-                       g_warning("Can't get the part of multipart message.");
+               if ((err = procmime_get_part(outfile, child)) < 0)
+                       g_warning("Can't get the part of multipart message. (%s)", strerror(-err));
                else {
                        gchar *content_type;
 
@@ -3097,7 +3330,9 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
 
                        /* if we meet a pgp signature, we don't attach it, but
                         * we force signing. */
-                       if (strcmp(content_type, "application/pgp-signature")) {
+                       if (strcmp(content_type, "application/pgp-signature") &&
+                           strcmp(content_type, "application/pkcs7-signature") &&
+                           strcmp(content_type, "application/x-pkcs7-signature")) {
                                partname = procmime_mimeinfo_get_parameter(child, "filename");
                                if (partname == NULL)
                                        partname = procmime_mimeinfo_get_parameter(child, "name");
@@ -3545,12 +3780,6 @@ static void compose_beautify_paragraph(Compose *compose, GtkTextIter *par_iter,
                quote_str = compose_get_quote_str(buffer, &iter, &quote_len);
 
                if (quote_str) {
-                       if (!wrap_quote) {
-                               if (startq_offset == -1) {
-                                       startq_offset = gtk_text_iter_get_offset(&iter);
-                               }
-                               goto colorize;
-                       }
                        debug_print("compose_beautify_paragraph(): quote_str = '%s'\n", quote_str);
                        if (startq_offset == -1) 
                                startq_offset = gtk_text_iter_get_offset(&iter);
@@ -3562,6 +3791,9 @@ static void compose_beautify_paragraph(Compose *compose, GtkTextIter *par_iter,
                                else
                                        quotelevel = 2;
                        }
+                       if (!wrap_quote) {
+                               goto colorize;
+                       }
                } else {
                        if (startq_offset == -1)
                                noq_offset = gtk_text_iter_get_offset(&iter);
@@ -3679,6 +3911,7 @@ colorize:
                        gtk_text_buffer_get_iter_at_offset(
                                buffer, &startquote, startq_offset);
                        endquote = iter;
+
                        switch (quotelevel) {
                        case 0: gtk_text_buffer_apply_tag_by_name(
                                        buffer, "quote0", &startquote, &endquote);
@@ -3767,11 +4000,16 @@ static void compose_set_title(Compose *compose)
        subject = gtk_editable_get_chars(
                        GTK_EDITABLE(compose->subject_entry), 0, -1);
 
+#ifndef MAEMO
        if (subject && strlen(subject))
                str = g_strdup_printf(_("%s - Compose message%s"),
                                      subject, edited); 
        else
                str = g_strdup_printf(_("[no subject] - Compose message%s"), edited);
+#else
+       str = g_strdup(_("Compose message"));
+#endif
+
        gtk_window_set_title(GTK_WINDOW(compose->window), str);
        g_free(str);
        g_free(subject);
@@ -3902,6 +4140,21 @@ static void compose_select_account(Compose *compose, PrefsAccount *account,
                compose_insert_sig(compose, TRUE);
                undo_unblock(compose->undostruct);
        }
+
+#ifdef USE_ASPELL
+       /* use account's dict info if set */
+       if (compose->gtkaspell) {
+               if (account->enable_default_dictionary)
+                       gtkaspell_change_dict(compose->gtkaspell,
+                                       account->default_dictionary, FALSE);
+               if (account->enable_default_alt_dictionary)
+                       gtkaspell_change_alt_dict(compose->gtkaspell,
+                                       account->default_alt_dictionary);
+               if (account->enable_default_dictionary
+                       || account->enable_default_alt_dictionary)
+                       compose_spell_menu_changed(compose);
+       }
+#endif
 }
 
 gboolean compose_check_for_valid_recipient(Compose *compose) {
@@ -3926,16 +4179,17 @@ gboolean compose_check_for_valid_recipient(Compose *compose) {
                gchar *entry;
                header = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
                entry = gtk_editable_get_chars(GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
+
                g_strstrip(entry);
                if (entry[0] != '\0') {
                        for (strptr = recipient_headers_mail; *strptr != NULL; strptr++) {
-                               if (!strcmp(header, (prefs_common.trans_hdr ? gettext(*strptr) : *strptr))) {
+                               if (!strcmp(header, prefs_common_translated_header_name(*strptr))) {
                                        compose->to_list = address_list_append(compose->to_list, entry);
                                        recipient_found = TRUE;
                                }
                        }
                        for (strptr = recipient_headers_news; *strptr != NULL; strptr++) {
-                               if (!strcmp(header, (prefs_common.trans_hdr ? gettext(*strptr) : *strptr))) {
+                               if (!strcmp(header, prefs_common_translated_header_name(*strptr))) {
                                        compose->newsgroup_list = newsgroup_list_append(compose->newsgroup_list, entry);
                                        recipient_found = TRUE;
                                }
@@ -3960,7 +4214,7 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
                        header = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
                        g_strstrip(entry);
                        if (strcmp(entry, compose->account->auto_cc)
-                       ||  strcmp(header, (prefs_common.trans_hdr ? gettext("Cc:") : "Cc:"))) {
+                       ||  strcmp(header, prefs_common_translated_header_name("Cc:"))) {
                                found_other = TRUE;
                                g_free(entry);
                                break;
@@ -3990,8 +4244,8 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
                        entry = gtk_editable_get_chars(GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
                        header = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
                        g_strstrip(entry);
-                       if (strcmp(entry, compose->account->auto_cc)
-                       ||  strcmp(header, (prefs_common.trans_hdr ? gettext("Bcc:") : "Bcc:"))) {
+                       if (strcmp(entry, compose->account->auto_bcc)
+                       ||  strcmp(header, prefs_common_translated_header_name("Bcc:"))) {
                                found_other = TRUE;
                                g_free(entry);
                                break;
@@ -4014,7 +4268,7 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
        return TRUE;
 }
 
-static gboolean compose_check_entries(Compose *compose, gboolean check_subject)
+static gboolean compose_check_entries(Compose *compose, gboolean check_everything)
 {
        const gchar *str;
 
@@ -4032,7 +4286,8 @@ static gboolean compose_check_entries(Compose *compose, gboolean check_subject)
 
        if (!compose->batch) {
                str = gtk_entry_get_text(GTK_ENTRY(compose->subject_entry));
-               if (*str == '\0' && check_subject == TRUE) {
+               if (*str == '\0' && check_everything == TRUE && 
+                   compose->mode != COMPOSE_REDIRECT) {
                        AlertValue aval;
 
                        aval = alertpanel(_("Send"),
@@ -4043,6 +4298,9 @@ static gboolean compose_check_entries(Compose *compose, gboolean check_subject)
                }
        }
 
+       if (check_everything && hooks_invoke(COMPOSE_CHECK_BEFORE_SEND_HOOKLIST, compose))
+               return FALSE;
+
        return TRUE;
 }
 
@@ -4054,6 +4312,10 @@ gint compose_send(Compose *compose)
        gchar *msgpath = NULL;
        gboolean discard_window = FALSE;
        gchar *errstr = NULL;
+       gchar *tmsgid = NULL;
+       MainWindow *mainwin = mainwindow_get_mainwindow();
+       gboolean queued_removed = FALSE;
+
        if (prefs_common.send_dialog_mode != SEND_DIALOG_ALWAYS
                        || compose->batch == TRUE)
                discard_window = TRUE;
@@ -4068,6 +4330,7 @@ gint compose_send(Compose *compose)
                goto bail;
        }
 
+       inc_lock();
        val = compose_queue(compose, &msgnum, &folder, &msgpath, TRUE);
 
        if (val) {
@@ -4077,6 +4340,9 @@ gint compose_send(Compose *compose)
                if (val == -4) {
                        alertpanel_error(_("Could not queue message for sending:\n\n"
                                           "Charset conversion failed."));
+               } else if (val == -5) {
+                       alertpanel_error(_("Could not queue message for sending:\n\n"
+                                          "Couldn't get recipient encryption key."));
                } else if (val == -3) {
                        if (privacy_peek_error())
                        alertpanel_error(_("Could not queue message for sending:\n\n"
@@ -4089,6 +4355,7 @@ gint compose_send(Compose *compose)
                goto bail;
        }
 
+       tmsgid = g_strdup(compose->msgid);
        if (discard_window) {
                compose->sending = FALSE;
                compose_close(compose);
@@ -4104,15 +4371,16 @@ gint compose_send(Compose *compose)
                if (!discard_window) {
                        goto bail;
                }
+               inc_unlock();
+               g_free(tmsgid);
                return -1;
        }
-       
        if (msgpath == NULL) {
                msgpath = folder_item_fetch_msg(folder, msgnum);
-               val = procmsg_send_message_queue(msgpath, &errstr);
+               val = procmsg_send_message_queue(msgpath, &errstr, folder, msgnum, &queued_removed);
                g_free(msgpath);
        } else {
-               val = procmsg_send_message_queue(msgpath, &errstr);
+               val = procmsg_send_message_queue(msgpath, &errstr, folder, msgnum, &queued_removed);
                g_unlink(msgpath);
                g_free(msgpath);
        }
@@ -4120,14 +4388,34 @@ gint compose_send(Compose *compose)
                compose->sending = FALSE;
                compose_allow_user_actions (compose, TRUE);
                if (val != 0) {
-                       folder_item_remove_msg(folder, msgnum);
+                       if (!queued_removed)
+                               folder_item_remove_msg(folder, msgnum);
                        folder_item_scan(folder);
+                       if (tmsgid) {
+                               /* make sure we delete that */
+                               MsgInfo *tmp = folder_item_get_msginfo_by_msgid(folder, tmsgid);
+                               if (tmp) {
+                                       debug_print("removing %d via %s\n", tmp->msgnum, tmsgid);
+                                       folder_item_remove_msg(folder, tmp->msgnum);
+                                       procmsg_msginfo_free(tmp);
+                               } 
+                       }
                }
        }
 
        if (val == 0) {
-               folder_item_remove_msg(folder, msgnum);
+               if (!queued_removed)
+                       folder_item_remove_msg(folder, msgnum);
                folder_item_scan(folder);
+               if (tmsgid) {
+                       /* make sure we delete that */
+                       MsgInfo *tmp = folder_item_get_msginfo_by_msgid(folder, tmsgid);
+                       if (tmp) {
+                               debug_print("removing %d via %s\n", tmp->msgnum, tmsgid);
+                               folder_item_remove_msg(folder, tmp->msgnum);
+                               procmsg_msginfo_free(tmp);
+                       }
+               }
                if (!discard_window)
                        compose_close(compose);
        } else {
@@ -4145,15 +4433,24 @@ gint compose_send(Compose *compose)
                if (!discard_window) {
                        goto bail;              
                }
+               inc_unlock();
+               g_free(tmsgid);
                return -1;
        }
-
+       g_free(tmsgid);
+       inc_unlock();
+       toolbar_main_set_sensitive(mainwin);
+       main_window_set_menu_sensitive(mainwin);
        return 0;
 
 bail:
+       inc_unlock();
+       g_free(tmsgid);
        compose_allow_user_actions (compose, TRUE);
        compose->sending = FALSE;
        compose->modified = TRUE; 
+       toolbar_main_set_sensitive(mainwin);
+       main_window_set_menu_sensitive(mainwin);
 
        return -1;
 }
@@ -4175,13 +4472,13 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
        GSList *list;
        ComposeHeaderEntry *headerentry;
        const gchar *headerentryname;
-       gchar *cc_hdr;
-       gchar *to_hdr;
+       const gchar *cc_hdr;
+       const gchar *to_hdr;
 
        debug_print("Writing redirect header\n");
 
-       cc_hdr = prefs_common.trans_hdr ? _("Cc:") : "Cc:";
-       to_hdr = prefs_common.trans_hdr ? _("To:") : "To:";
+       cc_hdr = prefs_common_translated_header_name("Cc:");
+       to_hdr = prefs_common_translated_header_name("To:");
 
        first_to_address = TRUE;
        for (list = compose->header_list; list; list = list->next) {
@@ -4299,26 +4596,40 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest)
        FILE *fp;
        size_t len;
        gchar buf[BUFFSIZE];
-
+       int i = 0;
+       gboolean skip = FALSE;
+       gchar *not_included[]={
+               "Return-Path:",         "Delivered-To:",        "Received:",
+               "Subject:",             "X-UIDL:",              "AF:",
+               "NF:",                  "PS:",                  "SRH:",
+               "SFN:",                 "DSR:",                 "MID:",
+               "CFG:",                 "PT:",                  "S:",
+               "RQ:",                  "SSV:",                 "NSV:",
+               "SSH:",                 "R:",                   "MAID:",
+               "NAID:",                "RMID:",                "FMID:",
+               "SCF:",                 "RRCPT:",               "NG:",
+               "X-Claws-Privacy",      "X-Claws-Sign:",        "X-Claws-Encrypt",
+               "X-Claws-End-Special-Headers:",                 "X-Claws-Account-Id:",
+               "X-Sylpheed-Privacy",   "X-Sylpheed-Sign:",     "X-Sylpheed-Encrypt",
+               "X-Sylpheed-End-Special-Headers:",              "X-Sylpheed-Account-Id:",
+               NULL
+               };
        if ((fp = g_fopen(compose->redirect_filename, "rb")) == NULL) {
                FILE_OP_ERROR(compose->redirect_filename, "fopen");
                return -1;
        }
 
        while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) {
-               /* should filter returnpath, delivered-to */
-               if (g_ascii_strncasecmp(buf, "Return-Path:",
-                                       strlen("Return-Path:")) == 0 ||
-                   g_ascii_strncasecmp(buf, "Delivered-To:",
-                                       strlen("Delivered-To:")) == 0 ||
-                   g_ascii_strncasecmp(buf, "Received:",
-                                       strlen("Received:")) == 0 ||
-                   g_ascii_strncasecmp(buf, "Subject:",
-                                       strlen("Subject:")) == 0 ||
-                   g_ascii_strncasecmp(buf, "X-UIDL:",
-                                       strlen("X-UIDL:")) == 0)
+               skip = FALSE;
+               for (i = 0; not_included[i] != NULL; i++) {
+                       if (g_ascii_strncasecmp(buf, not_included[i],
+                                               strlen(not_included[i])) == 0) {
+                               skip = TRUE;
+                               break;
+                       }
+               }
+               if (skip)
                        continue;
-
                if (fputs(buf, fdest) == -1)
                        goto error;
 
@@ -4489,17 +4800,23 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
        mimetext = procmime_mimeinfo_new();
        mimetext->content = MIMECONTENT_MEM;
        mimetext->tmp = TRUE; /* must free content later */
-       mimetext->data.mem = buf;
+       /* dup'ed because procmime_encode_content can turn it into a tmpfile
+        * and free the data, which we need later. */
+       mimetext->data.mem = g_strdup(buf); 
        mimetext->type = MIMETYPE_TEXT;
        mimetext->subtype = g_strdup("plain");
        g_hash_table_insert(mimetext->typeparameters, g_strdup("charset"),
                            g_strdup(out_codeset));
+                           
        /* protect trailing spaces when signing message */
        if (action == COMPOSE_WRITE_FOR_SEND && compose->use_signing && 
            privacy_system_can_sign(compose->privacy_system)) {
                encoding = ENC_QUOTED_PRINTABLE;
        }
        
+       debug_print("main text: %d bytes encoded as %s in %d\n",
+               strlen(buf), out_codeset, encoding);
+
        /* check for line length limit */
        if (action == COMPOSE_WRITE_FOR_SEND &&
            encoding != ENC_QUOTED_PRINTABLE && encoding != ENC_BASE64 &&
@@ -4515,6 +4832,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
                aval = alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, GTK_STOCK_OK, NULL);
                g_free(msg);
                if (aval != G_ALERTALTERNATE) {
+                       g_free(buf);
                        return -1;
                }
        }
@@ -4548,6 +4866,8 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
        } else
                g_node_append(mimemsg->node, mimetext->node);
 
+       g_free(buf);
+
        /* sign message if sending */
        if (action == COMPOSE_WRITE_FOR_SEND && compose->use_signing && 
            privacy_system_can_sign(compose->privacy_system))
@@ -4638,7 +4958,7 @@ static gint compose_remove_reedit_target(Compose *compose, gboolean force)
        return 0;
 }
 
-void compose_remove_draft(Compose *compose)
+static void compose_remove_draft(Compose *compose)
 {
        FolderItem *drafts;
        MsgInfo *msginfo = compose->targetinfo;
@@ -4771,8 +5091,8 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
 
        
        if (compose->privacy_system != NULL) {
-               fprintf(fp, "X-Sylpheed-Privacy-System:%s\n", compose->privacy_system);
-               fprintf(fp, "X-Sylpheed-Sign:%d\n", compose->use_signing);
+               fprintf(fp, "X-Claws-Privacy-System:%s\n", compose->privacy_system);
+               fprintf(fp, "X-Claws-Sign:%d\n", compose->use_signing);
                if (compose->use_encryption) {
                        gchar *encdata;
                        if (mailac && mailac->encrypt_to_self) {
@@ -4785,14 +5105,19 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                        }
                        if (encdata != NULL) {
                                if (strcmp(encdata, "_DONT_ENCRYPT_")) {
-                                       fprintf(fp, "X-Sylpheed-Encrypt:%d\n", compose->use_encryption);
-                                       fprintf(fp, "X-Sylpheed-Encrypt-Data:%s\n", 
+                                       fprintf(fp, "X-Claws-Encrypt:%d\n", compose->use_encryption);
+                                       fprintf(fp, "X-Claws-Encrypt-Data:%s\n", 
                                                encdata);
                                } /* else we finally dont want to encrypt */
                        } else {
-                               fprintf(fp, "X-Sylpheed-Encrypt:%d\n", compose->use_encryption);
+                               fprintf(fp, "X-Claws-Encrypt:%d\n", compose->use_encryption);
                                /* and if encdata was null, it means there's been a problem in 
                                 * key selection */
+                               lock = FALSE;
+                               fclose(fp);
+                               g_unlink(tmp);
+                               g_free(tmp);
+                               return -5;
                        }
                        g_free(encdata);
                }
@@ -4828,7 +5153,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        }
 
        /* end of headers */
-       fprintf(fp, "X-Sylpheed-End-Special-Headers: 1\n");
+       fprintf(fp, "X-Claws-End-Special-Headers: 1\n");
 
        if (compose->redirect_filename != NULL) {
                if (compose_redirect_write_to_file(compose, fp) < 0) {
@@ -4941,11 +5266,13 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
                    !g_ascii_strcasecmp(mimepart->subtype, "rfc822")) {
                        mimepart->disposition = DISPOSITIONTYPE_INLINE;
                } else {
-                       g_hash_table_insert(mimepart->typeparameters,
+                       if (ainfo->name) {
+                               g_hash_table_insert(mimepart->typeparameters,
                                            g_strdup("name"), g_strdup(ainfo->name));
-                       g_hash_table_insert(mimepart->dispositionparameters,
+                               g_hash_table_insert(mimepart->dispositionparameters,
                                            g_strdup("filename"), g_strdup(ainfo->name));
-                       mimepart->disposition = DISPOSITIONTYPE_ATTACHMENT;
+                               mimepart->disposition = DISPOSITIONTYPE_ATTACHMENT;
+                       }
                }
 
                if (compose->use_signing) {
@@ -4970,11 +5297,12 @@ static void compose_add_headerfield_from_headerlist(Compose *compose,
                                                    const gchar *fieldname,
                                                    const gchar *seperator)
 {
-       gchar *str, *fieldname_w_colon, *trans_fieldname;
+       gchar *str, *fieldname_w_colon;
        gboolean add_field = FALSE;
        GSList *list;
        ComposeHeaderEntry *headerentry;
-       const gchar * headerentryname;
+       const gchar *headerentryname;
+       const gchar *trans_fieldname;
        GString *fieldstr;
 
        if (IS_IN_CUSTOM_HEADER(fieldname))
@@ -4985,7 +5313,7 @@ static void compose_add_headerfield_from_headerlist(Compose *compose,
        fieldstr = g_string_sized_new(64);
 
        fieldname_w_colon = g_strconcat(fieldname, ":", NULL);
-       trans_fieldname = (prefs_common.trans_hdr ? gettext(fieldname_w_colon) : fieldname_w_colon);
+       trans_fieldname = prefs_common_translated_header_name(fieldname_w_colon);
 
        for (list = compose->header_list; list; list = list->next) {
                headerentry = ((ComposeHeaderEntry *)list->data);
@@ -5219,7 +5547,7 @@ static gchar *compose_get_header(Compose *compose)
                gchar *tmp;
                gchar *headername;
                gchar *headername_wcolon;
-               gchar *headername_trans;
+               const gchar *headername_trans;
                gchar *headervalue;
                gchar **string;
                gboolean standard_header = FALSE;
@@ -5247,8 +5575,8 @@ static gchar *compose_get_header(Compose *compose)
                subst_char(headervalue, '\n', ' ');
                string = std_headers;
                while (*string != NULL) {
-                       headername_trans = prefs_common.trans_hdr ? gettext(*string) : *string;
-                       if (!strcmp(headername_trans,headername_wcolon))
+                       headername_trans = prefs_common_translated_header_name(*string);
+                       if (!strcmp(headername_trans, headername_wcolon))
                                standard_header = TRUE;
                        string++;
                }
@@ -5330,6 +5658,48 @@ static void compose_convert_header(Compose *compose, gchar *dest, gint len, gcha
        g_free(tmpstr);
 }
 
+static void compose_add_to_addressbook_cb(GtkMenuItem *menuitem, gpointer user_data)
+{
+       gchar *address;
+
+       g_return_if_fail(user_data != NULL);
+
+       address = g_strdup(gtk_entry_get_text(GTK_ENTRY(user_data)));
+       g_strstrip(address);
+       if (*address != '\0') {
+               gchar *name = procheader_get_fromname(address);
+               extract_address(address);
+               addressbook_add_contact(name, address, NULL);
+       }
+       g_free(address);
+}
+
+static void compose_entry_popup_extend(GtkEntry *entry, GtkMenu *menu, gpointer user_data)
+{
+       GtkWidget *menuitem;
+       gchar *address;
+
+       g_return_if_fail(menu != NULL);
+       g_return_if_fail(GTK_IS_MENU_SHELL(menu));
+
+       menuitem = gtk_separator_menu_item_new();
+       gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
+       gtk_widget_show(menuitem);
+
+       menuitem = gtk_menu_item_new_with_mnemonic(_("Add to address _book"));
+       gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
+
+       address = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+       g_strstrip(address);
+       if (*address == '\0') {
+               gtk_widget_set_sensitive(GTK_WIDGET(menuitem), FALSE);
+       }
+
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                        G_CALLBACK(compose_add_to_addressbook_cb), entry);
+       gtk_widget_show(menuitem);
+}
+
 static void compose_create_header_entry(Compose *compose) 
 {
        gchar *headers[] = {"To:", "Cc:", "Bcc:", "Newsgroups:", "Reply-To:", "Followup-To:", NULL};
@@ -5348,7 +5718,7 @@ static void compose_create_header_entry(Compose *compose)
        combo = gtk_combo_new();
        string = headers; 
        while(*string != NULL) {
-               combo_list = g_list_append(combo_list, (prefs_common.trans_hdr ? gettext(*string) : *string));
+               combo_list = g_list_append(combo_list, (gchar*)prefs_common_translated_header_name(*string));
                string++;
        }
        gtk_combo_set_popdown_strings(GTK_COMBO(combo), combo_list);
@@ -5357,9 +5727,12 @@ static void compose_create_header_entry(Compose *compose)
        g_signal_connect(G_OBJECT(GTK_COMBO(combo)->entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        gtk_widget_show(combo);
-       gtk_table_attach(GTK_TABLE(compose->header_table), combo, 0, 1, compose->header_nextrow, compose->header_nextrow+1, GTK_SHRINK, GTK_FILL, 0, 0);
+       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) {     
-               const gchar *last_header_entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry));
+               const gchar *last_header_entry = gtk_entry_get_text(
+                               GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry));
                string = headers;
                while (*string != NULL) {
                        if (!strcmp(*string, last_header_entry))
@@ -5372,10 +5745,10 @@ static void compose_create_header_entry(Compose *compose)
        if (!compose->header_last || !standard_header) {
                switch(compose->account->protocol) {
                        case A_NNTP:
-                               header = prefs_common.trans_hdr ? _("Newsgroups:") : "Newsgroups:";
+                               header = prefs_common_translated_header_name("Newsgroups:");
                                break;
                        default:
-                               header = prefs_common.trans_hdr ? _("To:") : "To:";
+                               header = prefs_common_translated_header_name("To:");
                                break;
                }                                                                   
        }
@@ -5390,7 +5763,9 @@ static void compose_create_header_entry(Compose *compose)
        gtk_widget_show(entry);
        gtk_tooltips_set_tip(compose->tooltips, entry,
                _("Use <tab> to autocomplete from addressbook"), NULL);
-       gtk_table_attach(GTK_TABLE(compose->header_table), entry, 1, 2, compose->header_nextrow, compose->header_nextrow+1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+       gtk_table_attach(GTK_TABLE(compose->header_table), entry, 1, 2,
+                       compose->header_nextrow, compose->header_nextrow+1,
+                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
 
         g_signal_connect(G_OBJECT(entry), "key-press-event", 
                         G_CALLBACK(compose_headerentry_key_press_event_cb), 
@@ -5411,8 +5786,11 @@ static void compose_create_header_entry(Compose *compose)
        g_signal_connect(G_OBJECT(entry), "drag-drop",
                         G_CALLBACK(compose_drag_drop),
                         compose);
+       g_signal_connect(G_OBJECT(entry), "populate-popup",
+                        G_CALLBACK(compose_entry_popup_extend),
+                        NULL);
        
-       address_completion_register_entry(GTK_ENTRY(entry));
+       address_completion_register_entry(GTK_ENTRY(entry), TRUE);
 
         headerentry->compose = compose;
         headerentry->combo = combo;
@@ -5420,19 +5798,39 @@ static void compose_create_header_entry(Compose *compose)
         headerentry->headernum = compose->header_nextrow;
 
         compose->header_nextrow++;
-       compose->header_last = headerentry;
+       compose->header_last = headerentry;             
+       compose->header_list =
+               g_slist_append(compose->header_list,
+                              headerentry);
 }
 
-static void compose_add_header_entry(Compose *compose, gchar *header, gchar *text) 
+static void compose_add_header_entry(Compose *compose, const gchar *header, gchar *text) 
 {
        ComposeHeaderEntry *last_header;
        
        last_header = compose->header_last;
-       
+
        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(last_header->combo)->entry), header);
        gtk_entry_set_text(GTK_ENTRY(last_header->entry), text);
 }
 
+static void compose_remove_header_entries(Compose *compose) 
+{
+       GSList *list;
+       for (list = compose->header_list; list; list = list->next) {
+               ComposeHeaderEntry *headerentry = 
+                       (ComposeHeaderEntry *)list->data;
+               gtk_widget_destroy(headerentry->combo);
+               gtk_widget_destroy(headerentry->entry);
+               g_free(headerentry);
+       }
+       compose->header_last = NULL;
+       g_slist_free(compose->header_list);
+       compose->header_list = NULL;
+       compose->header_nextrow = 1;
+       compose_create_header_entry(compose);
+}
+
 static GtkWidget *compose_create_header(Compose *compose) 
 {
        GtkWidget *from_optmenu_hbox;
@@ -5470,7 +5868,18 @@ static GtkWidget *compose_create_header(Compose *compose)
        return header_scrolledwin ;
 }
 
-GtkWidget *compose_create_attach(Compose *compose)
+static gboolean popup_attach_button_pressed(GtkWidget *widget, gpointer data)
+{
+       Compose *compose = (Compose *)data;
+       GdkEventButton event;
+       
+       event.button = 3;
+       event.time = gtk_get_current_event_time();
+
+       return attach_button_pressed(compose->attach_clist, &event, compose);
+}
+
+static GtkWidget *compose_create_attach(Compose *compose)
 {
        GtkWidget *attach_scrwin;
        GtkWidget *attach_clist;
@@ -5518,7 +5927,7 @@ GtkWidget *compose_create_attach(Compose *compose)
        gtk_tree_view_append_column(GTK_TREE_VIEW(attach_clist), column);
 
        gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(attach_clist),
-                                    prefs_common.enable_rules_hint);
+                                    prefs_common.use_stripes_everywhere);
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(attach_clist));
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
 
@@ -5526,6 +5935,15 @@ GtkWidget *compose_create_attach(Compose *compose)
                         G_CALLBACK(attach_selected), compose);
        g_signal_connect(G_OBJECT(attach_clist), "button_press_event",
                         G_CALLBACK(attach_button_pressed), compose);
+#ifndef MAEMO
+       g_signal_connect(G_OBJECT(attach_clist), "popup-menu",
+                        G_CALLBACK(popup_attach_button_pressed), compose);
+#else
+       gtk_widget_tap_and_hold_setup(GTK_WIDGET(attach_clist), NULL, NULL,
+                       GTK_TAP_AND_HOLD_NONE | GTK_TAP_AND_HOLD_NO_INTERNALS);
+       g_signal_connect(G_OBJECT(attach_clist), "tap-and-hold",
+                        G_CALLBACK(popup_attach_button_pressed), compose);
+#endif
        g_signal_connect(G_OBJECT(attach_clist), "key_press_event",
                         G_CALLBACK(attach_key_pressed), compose);
 
@@ -5751,6 +6169,17 @@ static void compose_spell_menu_changed(void *data)
 }
 #endif
 
+static gboolean compose_popup_menu(GtkWidget *widget, gpointer data)
+{
+       Compose *compose = (Compose *)data;
+       GdkEventButton event;
+       
+       event.button = 3;
+       event.time = gtk_get_current_event_time();
+
+       return text_clicked(compose->text, &event, compose);
+}
+
 static gboolean compose_force_window_origin = TRUE;
 static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
                                                 gboolean batch)
@@ -5814,7 +6243,8 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
 
        compose->tooltips = gtk_tooltips_new();
 
-       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "compose");
+
        gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
        gtk_widget_set_size_request(window, -1, prefs_common.compose_height);
 
@@ -5831,11 +6261,12 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        }
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL,
                                      &geometry, GDK_HINT_MIN_SIZE);
-       
+
+#ifndef MAEMO  
        if (compose_force_window_origin)
                gtk_widget_set_uposition(window, prefs_common.compose_x, 
                                 prefs_common.compose_y);
-
+#endif
        g_signal_connect(G_OBJECT(window), "delete_event",
                         G_CALLBACK(compose_delete_cb), compose);
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
@@ -5893,7 +6324,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        gtk_box_pack_start(GTK_BOX(subject_hbox), subject_frame, TRUE, TRUE, 0);
        gtk_widget_show(subject_frame);
 
-       subject = gtk_hbox_new(FALSE, 0);
+       subject = gtk_hbox_new(FALSE, HSPACING_NARROW);
        gtk_container_set_border_width(GTK_CONTAINER(subject), 0);
        gtk_widget_show(subject);
 
@@ -5952,6 +6383,15 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
                         G_CALLBACK(text_inserted), compose);
        g_signal_connect(G_OBJECT(text), "button_press_event",
                         G_CALLBACK(text_clicked), compose);
+#ifndef MAEMO
+       g_signal_connect(G_OBJECT(text), "popup-menu",
+                        G_CALLBACK(compose_popup_menu), compose);
+#else
+       gtk_widget_tap_and_hold_setup(GTK_WIDGET(text), NULL, NULL,
+                       GTK_TAP_AND_HOLD_NONE | GTK_TAP_AND_HOLD_NO_INTERNALS);
+       g_signal_connect(G_OBJECT(text), "tap-and-hold",
+                        G_CALLBACK(compose_popup_menu), compose);
+#endif
        g_signal_connect(G_OBJECT(subject_entry), "changed",
                         G_CALLBACK(compose_changed_cb), compose);
 
@@ -5971,6 +6411,12 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        paned = gtk_vpaned_new();
        gtk_paned_set_gutter_size(GTK_PANED(paned), 12);
        gtk_container_add(GTK_CONTAINER(vbox2), paned);
+#ifdef MAEMO
+       if( maemo_mainwindow_is_fullscreen(mainwindow_get_mainwindow()->window) )
+               gtk_widget_set_size_request(edit_vbox, -1, mode == COMPOSE_NEW ? 300 : 280);
+       else
+               gtk_widget_set_size_request(edit_vbox, -1, mode == COMPOSE_NEW ? 250 : 230);
+#endif
        gtk_paned_add1(GTK_PANED(paned), notebook);
        gtk_paned_add2(GTK_PANED(paned), edit_vbox);
        gtk_widget_show_all(paned);
@@ -6015,6 +6461,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
 
        compose->paned = paned;
 
+       compose->notebook      = notebook;
        compose->edit_vbox     = edit_vbox;
        compose->ruler_hbox    = ruler_hbox;
        compose->ruler         = ruler;
@@ -6029,6 +6476,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        compose->tmpl_menu = tmpl_menu;
 
        compose->mode = mode;
+       compose->rmode = mode;
 
        compose->targetinfo = NULL;
        compose->replyinfo  = NULL;
@@ -6075,11 +6523,13 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
                    strcmp(prefs_common.dictionary, "")) {
                        gtkaspell = gtkaspell_new(prefs_common.aspell_path,
                                                  prefs_common.dictionary,
+                                                 prefs_common.alt_dictionary,
                                                  conv_get_locale_charset_str(),
                                                  prefs_common.misspelled_col,
                                                  prefs_common.check_while_typing,
                                                  prefs_common.recheck_when_changing_dict,
                                                  prefs_common.use_alternate,
+                                                 prefs_common.use_both_dicts,
                                                  GTK_TEXT_VIEW(text),
                                                  GTK_WINDOW(compose->window),
                                                  compose_spell_menu_changed,
@@ -6118,11 +6568,14 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        if (account->set_autoreplyto && account->auto_replyto && mode != COMPOSE_REEDIT)
                compose_entry_append(compose, account->auto_replyto, COMPOSE_REPLYTO);
 
+       menu_set_sensitive(ifactory, "/Options/Reply mode", compose->mode == COMPOSE_REPLY);
 
        if (account->protocol != A_NNTP)
-               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), prefs_common.trans_hdr ? _("To:") : "To:");
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry),
+                               prefs_common_translated_header_name("To:"));
        else
-               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), prefs_common.trans_hdr ? _("Newsgroups:") : "Newsgroups:");
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry),
+                               prefs_common_translated_header_name("Newsgroups:"));
 
        addressbook_set_target_compose(compose);
        
@@ -6160,6 +6613,10 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
                gtk_widget_realize(window);
        } else {
                gtk_widget_show(window);
+#ifdef MAEMO
+               maemo_window_full_screen_if_needed(GTK_WINDOW(window));
+               maemo_connect_key_press_to_mainwindow(GTK_WINDOW(window));
+#endif
        }
        
        return compose;
@@ -6222,6 +6679,9 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        g_signal_connect(G_OBJECT(optmenu), "changed",
                        G_CALLBACK(account_activated),
                        compose);
+       g_signal_connect(G_OBJECT(from_name), "populate-popup",
+                        G_CALLBACK(compose_entry_popup_extend),
+                        NULL);
 
        gtk_box_pack_start(GTK_BOX(hbox), optmenubox, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), from_name, TRUE, TRUE, 0);
@@ -6244,6 +6704,43 @@ static void compose_set_priority_cb(gpointer data,
        compose->priority = action;
 }
 
+static void compose_reply_change_mode(gpointer data,
+                                   ComposeMode action,
+                                   GtkWidget *widget)
+{
+       Compose *compose = (Compose *) data;
+       gboolean was_modified = compose->modified;
+
+       gboolean all = FALSE, ml = FALSE, sender = FALSE, followup = FALSE;
+       
+       g_return_if_fail(compose->replyinfo != NULL);
+       
+       if (action == COMPOSE_REPLY && prefs_common.default_reply_list)
+               ml = TRUE;
+       if (action == COMPOSE_REPLY && compose->rmode == COMPOSE_FOLLOWUP_AND_REPLY_TO)
+               followup = TRUE;
+       if (action == COMPOSE_REPLY_TO_ALL)
+               all = TRUE;
+       if (action == COMPOSE_REPLY_TO_SENDER)
+               sender = TRUE;
+       if (action == COMPOSE_REPLY_TO_LIST)
+               ml = TRUE;
+
+       compose_remove_header_entries(compose);
+       compose_reply_set_entry(compose, compose->replyinfo, all, ml, sender, followup);
+       if (compose->account->set_autocc && compose->account->auto_cc)
+               compose_entry_append(compose, compose->account->auto_cc, COMPOSE_CC);
+
+       if (compose->account->set_autobcc && compose->account->auto_bcc) 
+               compose_entry_append(compose, compose->account->auto_bcc, COMPOSE_BCC);
+       
+       if (compose->account->set_autoreplyto && compose->account->auto_replyto)
+               compose_entry_append(compose, compose->account->auto_replyto, COMPOSE_REPLYTO);
+       compose_show_first_last_header(compose, TRUE);
+       compose->modified = was_modified;
+       compose_set_title(compose);
+}
+
 static void compose_update_priority_menu_item(Compose * compose)
 {
        GtkItemFactory *ifactory;
@@ -6434,7 +6931,7 @@ void compose_update_actions_menu(Compose *compose)
        action_update_compose_menu(ifactory, "/Tools/Actions", compose);
 }
 
-void compose_update_privacy_systems_menu(Compose *compose)
+static void compose_update_privacy_systems_menu(Compose *compose)
 {
        static gchar *branch_path = "/Options/Privacy System";
        GtkItemFactory *ifactory;
@@ -6515,6 +7012,7 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
        gchar *qmark;
        gchar *parsed_str = NULL;
        gint cursor_pos = 0;
+       const gchar *err_msg = _("Template body format error.");
        if (!tmpl) return;
 
        /* process the body */
@@ -6522,32 +7020,59 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
        text = GTK_TEXT_VIEW(compose->text);
        buffer = gtk_text_view_get_buffer(text);
 
-       if (replace)
-               gtk_text_buffer_set_text(buffer, "", -1);
+       if (tmpl->value) {
+               if (prefs_common.quotemark && *prefs_common.quotemark)
+                       qmark = prefs_common.quotemark;
+               else
+                       qmark = "> ";
 
-       mark = gtk_text_buffer_get_insert(buffer);
-       gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
+               if (compose->replyinfo != NULL) {
+
+                       if (replace)
+                               gtk_text_buffer_set_text(buffer, "", -1);
+                       mark = gtk_text_buffer_get_insert(buffer);
+                       gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
+
+                       parsed_str = compose_quote_fmt(compose, compose->replyinfo,
+                                                  tmpl->value, qmark, NULL, FALSE, FALSE, err_msg);
+
+               } else if (compose->fwdinfo != NULL) {
+
+                       if (replace)
+                               gtk_text_buffer_set_text(buffer, "", -1);
+                       mark = gtk_text_buffer_get_insert(buffer);
+                       gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
+
+                       parsed_str = compose_quote_fmt(compose, compose->fwdinfo,
+                                                  tmpl->value, qmark, NULL, FALSE, FALSE, err_msg);
 
-       if (tmpl->value) {
-               if ((compose->replyinfo == NULL) && (compose->fwdinfo == NULL)) {
-                       parsed_str = compose_quote_fmt(compose, NULL, tmpl->value,
-                                                      NULL, NULL, FALSE);
                } else {
-                       if (prefs_common.quotemark && *prefs_common.quotemark)
-                               qmark = prefs_common.quotemark;
-                       else
-                               qmark = "> ";
-
-                       if (compose->replyinfo != NULL)
-                               parsed_str = compose_quote_fmt(compose, compose->replyinfo,
-                                                              tmpl->value, qmark, NULL, FALSE);
-                       else if (compose->fwdinfo != NULL)
-                               parsed_str = compose_quote_fmt(compose, compose->fwdinfo,
-                                                              tmpl->value, qmark, NULL, FALSE);
-                       else
-                               parsed_str = NULL;
-               }
-       }
+                       MsgInfo* dummyinfo = compose_msginfo_new_from_compose(compose);
+
+                       GtkTextIter start, end;
+                       gchar *tmp = NULL;
+
+                       gtk_text_buffer_get_start_iter(buffer, &start);
+                       gtk_text_buffer_get_iter_at_offset(buffer, &end, -1);
+                       tmp = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+
+                       /* clear the buffer now */
+                       if (replace)
+                               gtk_text_buffer_set_text(buffer, "", -1);
+
+                       parsed_str = compose_quote_fmt(compose, dummyinfo,
+                                                          tmpl->value, qmark, tmp, FALSE, FALSE, err_msg);
+                       procmsg_msginfo_free( dummyinfo );
+
+                       g_free( tmp );
+               } 
+       } else {
+               if (replace)
+                       gtk_text_buffer_set_text(buffer, "", -1);
+               mark = gtk_text_buffer_get_insert(buffer);
+               gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
+       }       
+
        if (replace && parsed_str && compose->account->auto_sig)
                compose_insert_sig(compose, FALSE);
 
@@ -6567,14 +7092,15 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
        }
 
        /* process the other fields */
+
        compose_template_apply_fields(compose, tmpl);
-       
+       quote_fmt_reset_vartable();
        compose_changed_cb(NULL, compose);
 }
 
-void compose_template_apply_fields(Compose *compose, Template *tmpl)
+static void compose_template_apply_fields(Compose *compose, Template *tmpl)
 {
-       static MsgInfo dummyinfo;
+       MsgInfo* dummyinfo = NULL;
        MsgInfo *msginfo = NULL;
        gchar *buf = NULL;
 
@@ -6582,43 +7108,45 @@ void compose_template_apply_fields(Compose *compose, Template *tmpl)
                msginfo = compose->replyinfo;
        else if (compose->fwdinfo != NULL)
                msginfo = compose->fwdinfo;
-       else
-               msginfo = &dummyinfo;
+       else {
+               dummyinfo = compose_msginfo_new_from_compose(compose);
+               msginfo = dummyinfo;
+       }
 
        if (tmpl->to && *tmpl->to != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
                quote_fmt_scan_string(tmpl->to);
                quote_fmt_parse();
 
                buf = quote_fmt_get_buffer();
                if (buf == NULL) {
-                       alertpanel_error(_("Message To format error."));
+                       alertpanel_error(_("Template To format error."));
                } else {
                        compose_entry_append(compose, buf, COMPOSE_TO);
                }
        }
 
        if (tmpl->cc && *tmpl->cc != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
                quote_fmt_scan_string(tmpl->cc);
                quote_fmt_parse();
 
                buf = quote_fmt_get_buffer();
                if (buf == NULL) {
-                       alertpanel_error(_("Message Cc format error."));
+                       alertpanel_error(_("Template Cc format error."));
                } else {
                        compose_entry_append(compose, buf, COMPOSE_CC);
                }
        }
 
        if (tmpl->bcc && *tmpl->bcc != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
                quote_fmt_scan_string(tmpl->bcc);
                quote_fmt_parse();
 
                buf = quote_fmt_get_buffer();
                if (buf == NULL) {
-                       alertpanel_error(_("Message Bcc format error."));
+                       alertpanel_error(_("Template Bcc format error."));
                } else {
                        compose_entry_append(compose, buf, COMPOSE_BCC);
                }
@@ -6626,21 +7154,26 @@ void compose_template_apply_fields(Compose *compose, Template *tmpl)
 
        /* process the subject */
        if (tmpl->subject && *tmpl->subject != '\0') {
-               quote_fmt_init(msginfo, NULL, NULL, FALSE);
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account);
                quote_fmt_scan_string(tmpl->subject);
                quote_fmt_parse();
 
                buf = quote_fmt_get_buffer();
                if (buf == NULL) {
-                       alertpanel_error(_("Message subject format error."));
+                       alertpanel_error(_("Template subject format error."));
                } else {
                        gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf);
                }
        }
+
+       procmsg_msginfo_free( dummyinfo );
 }
 
 static void compose_destroy(Compose *compose)
 {
+       GtkTextBuffer *buffer;
+       GtkClipboard *clipboard;
+
        compose_list = g_list_remove(compose_list, compose);
 
        if (compose->updating) {
@@ -6705,6 +7238,10 @@ static void compose_destroy(Compose *compose)
                gtk_widget_destroy(compose->paned);
        gtk_widget_destroy(compose->popupmenu);
 
+       buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(compose->text));
+       clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
+       gtk_text_buffer_remove_selection_clipboard(buffer, clipboard);
+
        gtk_widget_destroy(compose->window);
        toolbar_destroy(compose->toolbar);
        g_free(compose->toolbar);
@@ -6932,7 +7469,7 @@ static void compose_attach_property_create(gboolean *cancelled)
 
        debug_print("Creating attach_property window...\n");
 
-       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "compose_attach_property");
        gtk_widget_set_size_request(window, 480, -1);
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
        gtk_window_set_title(GTK_WINDOW(window), _("Properties"));
@@ -7512,13 +8049,13 @@ static void compose_send_cb(gpointer data, guint action, GtkWidget *widget)
        Compose *compose = (Compose *)data;
        
        if (prefs_common.work_offline && 
-           !inc_offline_should_override(
-               _("Sylpheed-Claws needs network access in order "
+           !inc_offline_should_override(TRUE,
+               _("Claws Mail needs network access in order "
                  "to send this email.")))
                return;
        
        if (compose->draft_timeout_tag != -1) { /* CLAWS: disable draft timeout */
-               gtk_timeout_remove(compose->draft_timeout_tag);
+               g_source_remove(compose->draft_timeout_tag);
                compose->draft_timeout_tag = -1;
        }
 
@@ -7531,10 +8068,13 @@ static void compose_send_later_cb(gpointer data, guint action,
        Compose *compose = (Compose *)data;
        gint val;
 
+       inc_lock();
        val = compose_queue_sub(compose, NULL, NULL, NULL, TRUE, TRUE);
-       if (!val) 
+       inc_unlock();
+
+       if (!val) {
                compose_close(compose);
-       else if (val == -1) {
+       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));
@@ -7545,12 +8085,69 @@ static void compose_send_later_cb(gpointer data, guint action,
        } else if (val == -4) {
                alertpanel_error(_("Could not queue message for sending:\n\n"
                                   "Charset conversion failed."));
+       } else if (val == -5) {
+               alertpanel_error(_("Could not queue message for sending:\n\n"
+                                  "Couldn't get recipient encryption key."));
+       }
+       toolbar_main_set_sensitive(mainwindow_get_mainwindow());
+}
+
+void compose_draft (gpointer data, guint action) 
+{
+       compose_draft_cb(data, action, NULL);   
+}
+
+#define DRAFTED_AT_EXIT "drafted_at_exit"
+void compose_clear_exit_drafts(void)
+{
+       gchar *filepath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                                     DRAFTED_AT_EXIT, NULL);
+       if (is_file_exist(filepath))
+               g_unlink(filepath);
+       
+       g_free(filepath);
+}
+
+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");
+       
+       if (fp) {
+               fprintf(fp, "%s\t%d\n", folder_item_get_identifier(info->folder), 
+                               info->msgnum);
+               fclose(fp);
        }
+               
+       g_free(filepath);       
 }
 
-void compose_draft (gpointer data) 
+void compose_reopen_exit_drafts(void)
 {
-       compose_draft_cb(data, COMPOSE_QUIT_EDITING, NULL);     
+       gchar *filepath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+                                     DRAFTED_AT_EXIT, NULL);
+       FILE *fp = fopen(filepath, "rb");
+       gchar buf[1024];
+       
+       if (fp) {
+               while (fgets(buf, sizeof(buf), fp)) {
+                       gchar **parts = g_strsplit(buf, "\t", 2);
+                       const gchar *folder = parts[0];
+                       int msgnum = parts[1] ? atoi(parts[1]):-1;
+                       
+                       if (folder && *folder && msgnum > -1) {
+                               FolderItem *item = folder_find_item_from_identifier(folder);
+                               MsgInfo *info = folder_item_get_msginfo(item, msgnum);
+                               if (info)
+                                       compose_reedit(info, FALSE);
+                       }
+                       g_strfreev(parts);
+               }       
+               fclose(fp);
+       }       
+       g_free(filepath);
+       compose_clear_exit_drafts();
 }
 
 static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
@@ -7595,7 +8192,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        }
 
        /* Save draft infos */
-       fprintf(fp, "X-Sylpheed-Account-Id:%d\n", compose->account->account_id);
+       fprintf(fp, "X-Claws-Account-Id:%d\n", compose->account->account_id);
        fprintf(fp, "S:%s\n", compose->account->address);
 
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn))) {
@@ -7609,13 +8206,30 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                fprintf(fp, "RRCPT:1\n");
        }
        if (compose->privacy_system) {
-               fprintf(fp, "X-Sylpheed-Sign:%d\n", compose->use_signing);
-               fprintf(fp, "X-Sylpheed-Encrypt:%d\n", compose->use_encryption);
-               fprintf(fp, "X-Sylpheed-Privacy-System:%s\n", compose->privacy_system);
+               fprintf(fp, "X-Claws-Sign:%d\n", compose->use_signing);
+               fprintf(fp, "X-Claws-Encrypt:%d\n", compose->use_encryption);
+               fprintf(fp, "X-Claws-Privacy-System:%s\n", compose->privacy_system);
+       }
+
+       /* Message-ID of message replying to */
+       if ((compose->replyinfo != NULL) && (compose->replyinfo->msgid != NULL)) {
+               gchar *folderid;
+               
+               folderid = folder_item_get_identifier(compose->replyinfo->folder);
+               fprintf(fp, "RMID:%s\t%d\t%s\n", folderid, compose->replyinfo->msgnum, compose->replyinfo->msgid);
+               g_free(folderid);
+       }
+       /* Message-ID of message forwarding to */
+       if ((compose->fwdinfo != NULL) && (compose->fwdinfo->msgid != NULL)) {
+               gchar *folderid;
+               
+               folderid = folder_item_get_identifier(compose->fwdinfo->folder);
+               fprintf(fp, "FMID:%s\t%d\t%s\n", folderid, compose->fwdinfo->msgnum, compose->fwdinfo->msgid);
+               g_free(folderid);
        }
 
        /* end of headers */
-       fprintf(fp, "X-Sylpheed-End-Special-Headers: 1\n");
+       fprintf(fp, "X-Claws-End-Special-Headers: 1\n");
 
        if (compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_STORE, action != COMPOSE_AUTO_SAVE) < 0) {
                fclose(fp);
@@ -7656,12 +8270,15 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                        procmsg_msginfo_set_flags(newmsginfo, 0,
                                                  MSG_HAS_ATTACHMENT);
 
+               if (action == COMPOSE_DRAFT_FOR_EXIT) {
+                       compose_register_draft(newmsginfo);
+               }
                procmsg_msginfo_free(newmsginfo);
        }
        
        folder_item_scan(draft);
        
-       if (action == COMPOSE_QUIT_EDITING) {
+       if (action == COMPOSE_QUIT_EDITING || action == COMPOSE_DRAFT_FOR_EXIT) {
                lock = FALSE;
                g_mutex_unlock(compose->mutex); /* must be done before closing */
                compose_close(compose);
@@ -7784,6 +8401,11 @@ static gint compose_delete_cb(GtkWidget *widget, GdkEventAny *event,
        return TRUE;
 }
 
+void compose_close_toolbar(Compose *compose)
+{
+       compose_close_cb(compose, 0, NULL);
+}
+
 static void compose_close_cb(gpointer data, guint action, GtkWidget *widget)
 {
        Compose *compose = (Compose *)data;
@@ -7910,16 +8532,18 @@ static void entry_paste_clipboard(Compose *compose, GtkWidget *entry,
                GtkTextMark *mark_start = gtk_text_buffer_get_insert(buffer);
                GtkTextIter start_iter, end_iter;
                gint start, end;
-               
                gchar *contents = gtk_clipboard_wait_for_text(gtk_clipboard_get(clip));
 
                if (contents == NULL)
                        return;
 
+               undo_paste_clipboard(GTK_TEXT_VIEW(compose->text), compose->undostruct);
+
                /* we shouldn't delete the selection when middle-click-pasting, or we
                 * can't mid-click-paste our own selection */
-               if (clip != GDK_SELECTION_PRIMARY)
+               if (clip != GDK_SELECTION_PRIMARY) {
                        gtk_text_buffer_delete_selection(buffer, FALSE, TRUE);
+               }
                
                if (insert_place == NULL) {
                        /* if insert_place isn't specified, insert at the cursor.
@@ -7947,7 +8571,6 @@ static void entry_paste_clipboard(Compose *compose, GtkWidget *entry,
                        gtk_text_iter_backward_char(&start_iter);
                        compose_beautify_paragraph(compose, &start_iter, TRUE);
                }
-               
        } else if (GTK_IS_EDITABLE(entry))
                gtk_editable_paste_clipboard (GTK_EDITABLE(entry));
        
@@ -7974,15 +8597,21 @@ static void entry_allsel(GtkWidget *entry)
 
 static void compose_cut_cb(Compose *compose)
 {
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_cut_clipboard(compose->focused_editable);
 }
 
 static void compose_copy_cb(Compose *compose)
 {
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_copy_clipboard(compose->focused_editable);
 }
 
@@ -8002,8 +8631,11 @@ static void compose_paste_cb(Compose *compose)
 static void compose_paste_as_quote_cb(Compose *compose)
 {
        gint wrap_quote = prefs_common.linewrap_quote;
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable)) {
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           ) {
                /* let text_insert() (called directly or at a later time
                 * after the gtk_editable_paste_clipboard) know that 
                 * text is to be inserted as a quotation. implemented
@@ -8027,8 +8659,11 @@ static void compose_paste_no_wrap_cb(Compose *compose)
        gint prev_autowrap;
        GtkTextBuffer *buffer;
        BLOCK_WRAP();
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_paste_clipboard(compose, compose->focused_editable, FALSE,
                        GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
@@ -8039,8 +8674,11 @@ static void compose_paste_wrap_cb(Compose *compose)
        gint prev_autowrap;
        GtkTextBuffer *buffer;
        BLOCK_WRAP();
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_paste_clipboard(compose, compose->focused_editable, TRUE,
                        GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
@@ -8048,8 +8686,11 @@ static void compose_paste_wrap_cb(Compose *compose)
 
 static void compose_allsel_cb(Compose *compose)
 {
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_allsel(compose->focused_editable);
 }
 
@@ -8372,12 +9013,52 @@ static void compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
 
        if (GTK_IS_EDITABLE(widget) || GTK_IS_TEXT_VIEW(widget))
                compose->focused_editable = widget;
+       
+#ifdef MAEMO
+       if (GTK_IS_TEXT_VIEW(widget) 
+           && gtk_paned_get_child1(GTK_PANED(compose->paned)) != compose->edit_vbox) {
+               gtk_widget_ref(compose->notebook);
+               gtk_widget_ref(compose->edit_vbox);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->notebook);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->edit_vbox);
+               gtk_paned_add1(GTK_PANED(compose->paned), compose->edit_vbox);
+               gtk_paned_add2(GTK_PANED(compose->paned), compose->notebook);
+               gtk_widget_unref(compose->notebook);
+               gtk_widget_unref(compose->edit_vbox);
+               g_signal_handlers_block_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+               gtk_widget_grab_focus(widget);
+               g_signal_handlers_unblock_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+       } else if (!GTK_IS_TEXT_VIEW(widget) 
+                  && gtk_paned_get_child1(GTK_PANED(compose->paned)) != compose->notebook) {
+               gtk_widget_ref(compose->notebook);
+               gtk_widget_ref(compose->edit_vbox);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->notebook);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->edit_vbox);
+               gtk_paned_add1(GTK_PANED(compose->paned), compose->notebook);
+               gtk_paned_add2(GTK_PANED(compose->paned), compose->edit_vbox);
+               gtk_widget_unref(compose->notebook);
+               gtk_widget_unref(compose->edit_vbox);
+               g_signal_handlers_block_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+               gtk_widget_grab_focus(widget);
+               g_signal_handlers_unblock_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+       }
+#endif
 }
 
 static void compose_changed_cb(GtkTextBuffer *textbuf, Compose *compose)
 {
        compose->modified = TRUE;
+#ifndef MAEMO
        compose_set_title(compose);
+#endif
 }
 
 static void compose_wrap_cb(gpointer data, guint action, GtkWidget *widget)
@@ -8467,17 +9148,20 @@ static void compose_attach_drag_received_cb (GtkWidget          *widget,
        if (gdk_atom_name(data->type) && 
            !strcmp(gdk_atom_name(data->type), "text/uri-list")
            && gtk_drag_get_source_widget(context) != 
-               mainwindow_get_mainwindow()->summaryview->ctree) {
+               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)
+               for (tmp = list; tmp != NULL; tmp = tmp->next) {
+                       gchar *utf8_filename = conv_filename_to_utf8((const gchar *)tmp->data);
                        compose_attach_append
                                (compose, (const gchar *)tmp->data,
-                                (const gchar *)tmp->data, NULL);
+                                utf8_filename, NULL);
+                       g_free(utf8_filename);
+               }
                if (list) compose_changed_cb(NULL, compose);
                list_free_strings(list);
                g_list_free(list);
        } else if (gtk_drag_get_source_widget(context) 
-                  == mainwindow_get_mainwindow()->summaryview->ctree) {
+                  == summary_get_main_widget(mainwindow_get_mainwindow()->summaryview)) {
                /* comes from our summaryview */
                SummaryView * summaryview = NULL;
                GSList * list = NULL, *cur = NULL;
@@ -8642,7 +9326,7 @@ static void compose_toggle_remove_refs_cb(gpointer data, guint action,
                compose->remove_references = FALSE;
 }
 
-gboolean compose_headerentry_key_press_event_cb(GtkWidget *entry,
+static gboolean compose_headerentry_key_press_event_cb(GtkWidget *entry,
                                            GdkEventKey *event,
                                            ComposeHeaderEntry *headerentry)
 {
@@ -8674,14 +9358,10 @@ gboolean compose_headerentry_key_press_event_cb(GtkWidget *entry,
        return FALSE;
 }
 
-gboolean compose_headerentry_changed_cb(GtkWidget *entry,
+static gboolean compose_headerentry_changed_cb(GtkWidget *entry,
                                    ComposeHeaderEntry *headerentry)
 {
        if (strlen(gtk_entry_get_text(GTK_ENTRY(entry))) != 0) {
-               headerentry->compose->header_list =
-                       g_slist_append(headerentry->compose->header_list,
-                                      headerentry);
-               
                compose_create_header_entry(headerentry->compose);
                g_signal_handlers_disconnect_matched
                        (G_OBJECT(entry), G_SIGNAL_MATCH_DATA,
@@ -8734,7 +9414,9 @@ static void text_inserted(GtkTextBuffer *buffer, GtkTextIter *iter,
                mark = gtk_text_buffer_create_mark(buffer, NULL, iter, FALSE);
                gtk_text_buffer_place_cursor(buffer, iter);
 
-               compose_quote_fmt(compose, NULL, "%Q", qmark, new_text, TRUE);
+               compose_quote_fmt(compose, NULL, "%Q", qmark, new_text, TRUE, FALSE,
+                                                 _("Quote format error."));
+               quote_fmt_reset_vartable();
                g_free(new_text);
                g_object_set_data(G_OBJECT(compose->text), "paste_as_quotation",
                                  GINT_TO_POINTER(paste_as_quotation - 1));
@@ -8766,7 +9448,7 @@ static void text_inserted(GtkTextBuffer *buffer, GtkTextIter *iter,
 
        if (prefs_common.autosave && 
            gtk_text_buffer_get_char_count(buffer) % prefs_common.autosave_length == 0)
-               compose->draft_timeout_tag = gtk_timeout_add
+               compose->draft_timeout_tag = g_timeout_add
                        (500, (GtkFunction) compose_defer_auto_save_draft, compose);
 }
 static gint compose_defer_auto_save_draft(Compose *compose)
@@ -8842,9 +9524,20 @@ static PrefsAccount *compose_guess_forward_account_from_msginfo(MsgInfo *msginfo
        if (!account && prefs_common.forward_account_autosel) {
                gchar cc[BUFFSIZE];
                if (!procheader_get_header_from_msginfo
-                       (msginfo, cc,sizeof cc , "CC:")) { /* Found a CC header */
-                       extract_address(cc);
-                       account = account_find_from_address(cc);
+                       (msginfo, cc,sizeof cc , "Cc:")) { 
+                       gchar *buf = cc + strlen("Cc:");
+                       extract_address(buf);
+                       account = account_find_from_address(buf);
+                }
+       }
+       
+       if (!account && prefs_common.forward_account_autosel) {
+               gchar deliveredto[BUFFSIZE];
+               if (!procheader_get_header_from_msginfo
+                       (msginfo, deliveredto,sizeof deliveredto , "Delivered-To:")) { 
+                       gchar *buf = deliveredto + strlen("Delivered-To:");
+                       extract_address(buf);
+                       account = account_find_from_address(buf);
                 }
        }
        
@@ -8904,7 +9597,7 @@ static void compose_reply_from_messageview_real(MessageView *msgview, GSList *ms
        if (g_slist_length(msginfo_list) == 1 && !opening_multiple) {
                MimeInfo *mimeinfo = messageview_get_selected_mime_part(msgview);
                MsgInfo *orig_msginfo = (MsgInfo *)msginfo_list->data;
-               
+
                if (mimeinfo != NULL && mimeinfo->type == MIMETYPE_MESSAGE && 
                    !g_ascii_strcasecmp(mimeinfo->subtype, "rfc822")) {
                        tmp_msginfo = procmsg_msginfo_new_from_mimeinfo(
@@ -8993,6 +9686,100 @@ gboolean compose_search_string_backward(Compose *compose,
        return gtkut_text_view_search_string_backward(text, str, case_sens);
 }
 
+/* allocate a msginfo structure and populate its data from a compose data structure */
+static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
+{
+       MsgInfo *newmsginfo;
+       GSList *list;
+       gchar buf[BUFFSIZE];
+
+       g_return_val_if_fail( compose != NULL, NULL );
+
+       newmsginfo = procmsg_msginfo_new();
+
+       /* date is now */
+       get_rfc822_date(buf, sizeof(buf));
+       newmsginfo->date = g_strdup(buf);
+
+       /* from */
+       if (compose->from_name) {
+               newmsginfo->from = gtk_editable_get_chars(GTK_EDITABLE(compose->from_name), 0, -1);
+               newmsginfo->fromname = procheader_get_fromname(newmsginfo->from);
+       }
+
+       /* subject */
+       if (compose->subject_entry)
+               newmsginfo->subject = gtk_editable_get_chars(GTK_EDITABLE(compose->subject_entry), 0, -1);
+
+       /* to, cc, reply-to, newsgroups */
+       for (list = compose->header_list; list; list = list->next) {
+               gchar *header = gtk_editable_get_chars(
+                                                               GTK_EDITABLE(
+                                                               GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
+               gchar *entry = gtk_editable_get_chars(
+                                                               GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
+
+               if ( strcasecmp(header, prefs_common_translated_header_name("To:")) == 0 ) {
+                       if ( newmsginfo->to == NULL ) {
+                               newmsginfo->to = g_strdup(entry);
+                       } else {
+                               gchar *tmp = g_strconcat(newmsginfo->to, ", ", entry, NULL);
+                               g_free(newmsginfo->to);
+                               newmsginfo->to = tmp;
+                       }
+               } else
+               if ( strcasecmp(header, prefs_common_translated_header_name("Cc:")) == 0 ) {
+                       if ( newmsginfo->cc == NULL ) {
+                               newmsginfo->cc = g_strdup(entry);
+                       } else {
+                               gchar *tmp = g_strconcat(newmsginfo->cc, ", ", entry, NULL);
+                               g_free(newmsginfo->cc);
+                               newmsginfo->cc = tmp;
+                       }
+               } else
+               if ( strcasecmp(header,
+                                               prefs_common_translated_header_name("Newsgroups:")) == 0 ) {
+                       if ( newmsginfo->newsgroups == NULL ) {
+                               newmsginfo->newsgroups = g_strdup(entry);
+                       } else {
+                               gchar *tmp = g_strconcat(newmsginfo->newsgroups, ", ", entry, NULL);
+                               g_free(newmsginfo->newsgroups);
+                               newmsginfo->newsgroups = tmp;
+                       }
+               }
+
+               g_free(header);
+               g_free(entry);  
+       }
+
+       /* other data is unset */
+
+       return newmsginfo;
+}
+
+#ifdef USE_ASPELL
+/* update compose's dictionaries from folder dict settings */
+static void compose_set_dictionaries_from_folder_prefs(Compose *compose,
+                                               FolderItem *folder_item)
+{
+       g_return_if_fail(compose != NULL);
+
+       if (compose->gtkaspell && folder_item && folder_item->prefs) {
+               FolderItemPrefs *prefs = folder_item->prefs;
+
+               if (prefs->enable_default_dictionary)
+                       gtkaspell_change_dict(compose->gtkaspell,
+                                       prefs->default_dictionary, FALSE);
+               if (folder_item->prefs->enable_default_alt_dictionary)
+                       gtkaspell_change_alt_dict(compose->gtkaspell,
+                                       prefs->default_alt_dictionary);
+               if (prefs->enable_default_dictionary
+                       || prefs->enable_default_alt_dictionary)
+                       compose_spell_menu_changed(compose);
+       }
+}
+#endif
+
 /*
  * End of Source.
  */