sync with 0.8.1cvs12
[claws.git] / src / compose.c
index e8ec3541f481c9312662dbf82bd267feb2936b0a..f8bf9678642e31c8fa5dc742208a1e88c7fa361f 100644 (file)
@@ -84,6 +84,7 @@
 #include "customheader.h"
 #include "prefs_common.h"
 #include "prefs_account.h"
+#include "prefs_actions.h"
 #include "account.h"
 #include "filesel.h"
 #include "procheader.h"
 #include "template.h"
 #include "undo.h"
 #include "foldersel.h"
-#include "prefs_actions.h"
 
 #if USE_GPGME
 #  include "rfc2015.h"
@@ -158,7 +158,8 @@ static GList *compose_list = NULL;
 
 Compose *compose_generic_new                   (PrefsAccount   *account,
                                                 const gchar    *to,
-                                                FolderItem     *item);
+                                                FolderItem     *item,
+                                                GPtrArray      *attach_files);
 
 static Compose *compose_create                 (PrefsAccount   *account,
                                                 ComposeMode     mode);
@@ -365,6 +366,7 @@ static void compose_redo_cb         (Compose        *compose);
 static void compose_cut_cb             (Compose        *compose);
 static void compose_copy_cb            (Compose        *compose);
 static void compose_paste_cb           (Compose        *compose);
+static void compose_paste_as_quote_cb  (Compose        *compose);
 static void compose_allsel_cb          (Compose        *compose);
 
 static void compose_gtk_stext_action_cb        (Compose                   *compose,
@@ -443,8 +445,6 @@ static void to_activated            (GtkWidget      *widget,
                                         Compose        *compose);
 static void newsgroups_activated       (GtkWidget      *widget,
                                         Compose        *compose);
-static void subject_activated          (GtkWidget      *widget,
-                                        Compose        *compose);
 static void cc_activated               (GtkWidget      *widget,
                                         Compose        *compose);
 static void bcc_activated              (GtkWidget      *widget,
@@ -453,8 +453,17 @@ static void replyto_activated              (GtkWidget      *widget,
                                         Compose        *compose);
 static void followupto_activated       (GtkWidget      *widget,
                                         Compose        *compose);
+static void subject_activated          (GtkWidget      *widget,
+                                        Compose        *compose);
 #endif
 
+static void text_activated             (GtkWidget      *widget,
+                                        Compose        *compose);
+static void text_inserted              (GtkWidget      *widget,
+                                        const gchar    *text,
+                                        gint            length,
+                                        gint           *position,
+                                        Compose        *compose);
 static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                                  gboolean to_all,
                                  gboolean ignore_replyto,
@@ -476,9 +485,7 @@ static void compose_check_backwards    (Compose *compose);
 static void compose_check_forwards_go     (Compose *compose);
 #endif
 
-static gboolean compose_send_control_enter (Compose *compose);
-static void text_activated                (GtkWidget   *widget,
-                                           Compose     *compose);
+static gboolean compose_send_control_enter     (Compose        *compose);
 
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
@@ -504,6 +511,8 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Edit/Cu_t"),             "<control>X", compose_cut_cb,    0, NULL},
        {N_("/_Edit/_Copy"),            "<control>C", compose_copy_cb,   0, NULL},
        {N_("/_Edit/_Paste"),           "<control>V", compose_paste_cb,  0, NULL},
+       {N_("/_Edit/Paste as _quotation"),
+                                       NULL, compose_paste_as_quote_cb, 0, NULL},
        {N_("/_Edit/Select _all"),      "<control>A", compose_allsel_cb, 0, NULL},
        {N_("/_Edit/A_dvanced"),        NULL, NULL, 0, "<Branch>"},
        {N_("/_Edit/A_dvanced/Move a character backward"),
@@ -642,12 +651,12 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Message/_Encrypt"),      NULL, compose_toggle_encrypt_cb, 0, "<ToggleItem>"},
 #endif /* USE_GPGME */
        {N_("/_Message/---"),           NULL,           NULL,   0, "<Separator>"},
-       {N_("/_Message/Priority"),      NULL,           NULL,   0, "<Branch>"},
-       {N_("/_Message/Priority/Highest"), NULL, compose_set_priority_cb, PRIORITY_HIGHEST, "<RadioItem>"},
-       {N_("/_Message/Priority/High"),    NULL, compose_set_priority_cb, PRIORITY_HIGH, "/Message/Priority/Highest"},
-       {N_("/_Message/Priority/Normal"),  NULL, compose_set_priority_cb, PRIORITY_NORMAL, "/Message/Priority/Highest"},
-       {N_("/_Message/Priority/Low"),     NULL, compose_set_priority_cb, PRIORITY_LOW, "/Message/Priority/Highest"},
-       {N_("/_Message/Priority/Lowest"),  NULL, compose_set_priority_cb, PRIORITY_LOWEST, "/Message/Priority/Highest"},
+       {N_("/_Message/_Priority"),     NULL,           NULL,   0, "<Branch>"},
+       {N_("/_Message/Priority/_Highest"), NULL, compose_set_priority_cb, PRIORITY_HIGHEST, "<RadioItem>"},
+       {N_("/_Message/Priority/Hi_gh"),    NULL, compose_set_priority_cb, PRIORITY_HIGH, "/Message/Priority/Highest"},
+       {N_("/_Message/Priority/_Normal"),  NULL, compose_set_priority_cb, PRIORITY_NORMAL, "/Message/Priority/Highest"},
+       {N_("/_Message/Priority/Lo_w"),    NULL, compose_set_priority_cb, PRIORITY_LOW, "/Message/Priority/Highest"},
+       {N_("/_Message/Priority/_Lowest"),  NULL, compose_set_priority_cb, PRIORITY_LOWEST, "/Message/Priority/Highest"},
        {N_("/_Message/---"),           NULL,           NULL,   0, "<Separator>"},
        {N_("/_Message/_Request Return Receipt"),       NULL, compose_toggle_return_receipt_cb, 0, "<ToggleItem>"},
        {N_("/_Tools"),                 NULL, NULL, 0, "<Branch>"},
@@ -664,24 +673,19 @@ static GtkTargetEntry compose_mime_types[] =
        {"text/uri-list", 0, 0}
 };
 
-Compose *compose_new(PrefsAccount *account)
-{
-       return compose_generic_new(account, NULL, NULL);
-}
-
-Compose *compose_bounce(PrefsAccount *account, MsgInfo *msginfo)
+Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
 {
        Compose *c;
        gchar *filename;
        GtkItemFactory *ifactory;
        
-       c = compose_generic_new(account, NULL, NULL);
+       c = compose_generic_new(account, NULL, NULL, NULL);
 
        filename = procmsg_get_message_file(msginfo);
        if (filename == NULL)
                return NULL;
 
-       c->bounce_filename = filename;
+       c->redirect_filename = filename;
 
        if (msginfo->subject)
                gtk_entry_set_text(GTK_ENTRY(c->subject_entry),
@@ -721,19 +725,24 @@ Compose *compose_bounce(PrefsAccount *account, MsgInfo *msginfo)
        return c;
 }
 
-Compose *compose_new_with_recipient(PrefsAccount *account, const gchar *mailto)
+Compose *compose_new(PrefsAccount *account, const gchar *mailto,
+                    GPtrArray *attach_files)
 {
-       return compose_generic_new(account, mailto, NULL);
+       return compose_generic_new(account, mailto, NULL, attach_files);
 }
 
 Compose *compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
 {
-       return compose_generic_new(account, NULL, item);
+       return compose_generic_new(account, NULL, item, NULL);
 }
 
-Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item)
+Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item,
+                            GPtrArray *attach_files)
 {
        Compose *compose;
+       GtkSText *text;
+       GtkItemFactory *ifactory;
+       gboolean grab_focus_on_last = TRUE;
 
        if (item && item->prefs && item->prefs->enable_default_account)
                account = account_find_from_id(item->prefs->default_account);
@@ -742,31 +751,57 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        g_return_val_if_fail(account != NULL, NULL);
 
        compose = compose_create(account, COMPOSE_NEW);
+       ifactory = gtk_item_factory_from_widget(compose->menubar);
+
        compose->replyinfo = NULL;
 
+       text = GTK_STEXT(compose->text);
+       gtk_stext_freeze(text);
+
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
-       gtk_editable_set_position(GTK_EDITABLE(compose->text), 0);
-       gtk_stext_set_point(GTK_STEXT(compose->text), 0);
+       gtk_editable_set_position(GTK_EDITABLE(text), 0);
+       gtk_stext_set_point(text, 0);
+
+       gtk_stext_thaw(text);
+
+       /* workaround for initial XIM problem */
+       gtk_widget_grab_focus(compose->text);
+       gtkut_widget_wait_for_draw(compose->text);
 
        if (account->protocol != A_NNTP) {
-               if (mailto) {
+               if (mailto && *mailto != '\0') {
                        compose_entries_set(compose, mailto);
 
                } else if(item && item->prefs->enable_default_to) {
                        compose_entry_append(compose, item->prefs->default_to, COMPOSE_TO);
+                       compose_entry_select(compose, item->prefs->default_to);
+                       grab_focus_on_last = FALSE;
                }
                if (item && item->ret_rcpt) {
-                       GtkItemFactory *ifactory;
-               
-                       ifactory = gtk_item_factory_from_widget(compose->menubar);
                        menu_set_toggle(ifactory, "/Message/Request Return Receipt", TRUE);
                }
        } else {
                if (mailto) {
                        compose_entry_append(compose, mailto, COMPOSE_NEWSGROUPS);
                }
+               /*
+                * CLAWS: just don't allow return receipt request, even if the user
+                * may want to send an email. simple but foolproof.
+                */
+               menu_set_sensitive(ifactory, "/Message/Request Return Receipt", FALSE); 
+       }
+
+       if (attach_files) {
+               gint i;
+               gchar *file;
+
+               for (i = 0; i < attach_files->len; i++) {
+                       file = g_ptr_array_index(attach_files, i);
+                       compose_attach_append(compose, file, file, NULL);
+               }
        }
+
        compose_show_first_last_header(compose, TRUE);
 
        /* Set save folder */
@@ -778,8 +813,10 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
                g_free(folderidentifier);
        }
-
-       gtk_widget_grab_focus(compose->header_last->entry);
+       
+       /* Grab focus on last header only if no default_to was set */
+       if(grab_focus_on_last)
+               gtk_widget_grab_focus(compose->header_last->entry);
 
        if (prefs_common.auto_exteditor)
                compose_exec_ext_editor(compose);
@@ -894,14 +931,8 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        } else
                reply_account = account;
 
-       MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
-       MSG_SET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
-       if (MSG_IS_IMAP(msginfo->flags))
-               imap_msg_set_perm_flags(msginfo, MSG_REPLIED);
-       CHANGE_FLAGS(msginfo);
-
        compose = compose_create(account, COMPOSE_REPLY);
-       compose->replyinfo = procmsg_msginfo_copy(msginfo);
+       compose->replyinfo = procmsg_msginfo_new_ref(msginfo);
 
 #if 0 /* NEW COMPOSE GUI */
        if (followup_and_reply_to) {
@@ -968,58 +999,6 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
 
 static void set_toolbar_style(Compose *compose);
 
-static gchar *procmime_get_file_name(MimeInfo *mimeinfo)
-{
-       gchar *base;
-       gchar *filename;
-
-       g_return_val_if_fail(mimeinfo != NULL, NULL);
-
-       base = mimeinfo->filename ? mimeinfo->filename
-               : mimeinfo->name ? mimeinfo->name : NULL;
-
-       if (MIME_TEXT_HTML == mimeinfo->mime_type && base == NULL){
-               filename = g_strdup_printf("%s%smimetmp.%08x.html",
-                                          get_mime_tmp_dir(),
-                                          G_DIR_SEPARATOR_S,
-                                          (gint)mimeinfo);
-               return filename;
-       }
-       else {
-               base = base ? base : "";
-               base = g_basename(base);
-               if (*base == '\0') {
-                       filename = g_strdup_printf("%s%smimetmp.%08x",
-                                                  get_mime_tmp_dir(),
-                                                  G_DIR_SEPARATOR_S,
-                                                  (gint)mimeinfo);
-                       return filename;
-               }
-       }
-
-       filename = g_strconcat(get_mime_tmp_dir(), G_DIR_SEPARATOR_S,
-                              base, NULL);
-
-       return filename;
-}
-
-static gchar *mime_extract_file(gchar *source, MimeInfo *partinfo)
-{
-       gchar *filename;
-
-       if (!partinfo) return NULL;
-
-       filename = procmime_get_file_name(partinfo);
-
-       if (procmime_get_part(filename, source, partinfo) < 0)
-               alertpanel_error
-                       (_("Can't get the part of multipart message."));
-
-       return filename;
-}
-
-
-
 #define INSERT_FW_HEADER(var, hdr) \
 if (msginfo->var && *msginfo->var) { \
        gtk_stext_insert(text, NULL, NULL, NULL, hdr, -1); \
@@ -1286,8 +1265,6 @@ GList *compose_get_compose_list(void)
 void compose_entry_append(Compose *compose, const gchar *address,
                          ComposeEntryType type)
 {
-       GtkEntry *entry;
-       const gchar *text;
        gchar *header;
 
        if (!address || *address == '\0') return;
@@ -1341,6 +1318,20 @@ void compose_entry_append(Compose *compose, const gchar *address,
        compose_add_header_entry(compose, header, (gchar *)address);
 }
 
+void compose_entry_select (Compose *compose, const gchar *mailto)
+{
+       GSList *header_list;
+               
+       for (header_list = compose->header_list; header_list != NULL; header_list = header_list->next) {
+               GtkEntry * entry = GTK_ENTRY(((ComposeHeaderEntry *)header_list->data)->entry);
+
+               if (gtk_entry_get_text(entry) && !g_strcasecmp(gtk_entry_get_text(entry), mailto)) {
+                       gtk_entry_select_region(entry, 0, -1);
+                       gtk_widget_grab_focus(GTK_WIDGET(entry));
+               }
+       }
+}
+
 static void compose_entries_set(Compose *compose, const gchar *mailto)
 {
        gchar *subject = NULL;
@@ -1595,11 +1586,15 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                                const gchar *body)
 {
        GtkSText *text = GTK_STEXT(compose->text);
+       static MsgInfo dummyinfo;
        gchar *quote_str = NULL;
        gchar *buf;
        gchar *p, *lastp;
        gint len;
 
+       if (!msginfo)
+               msginfo = &dummyinfo;
+
        if (qmark != NULL) {
                quote_fmt_init(msginfo, NULL, NULL);
                quote_fmt_scan_string(qmark);
@@ -1801,9 +1796,6 @@ static void compose_reedit_set_entry(Compose *compose, MsgInfo *msginfo)
 
 static void compose_exec_sig(Compose *compose, gchar *sigfile)
 {
-       FILE *tmpfp;
-       pid_t thepid;
-       gchar *sigtext;
        FILE  *sigprg;
        gchar  *buf;
        size_t buf_len = 128;
@@ -1956,16 +1948,24 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                                (_("Message: %s"),
                                 g_basename(filename ? filename : file));
                } else {
-                       ainfo->encoding = ENC_BASE64;
+                       if (!g_strncasecmp(content_type, "text", 4))
+                               ainfo->encoding =
+                                       procmime_get_encoding_for_file(file);
+                       else
+                               ainfo->encoding = ENC_BASE64;
                        ainfo->name = g_strdup
                                (g_basename(filename ? filename : file));
                }
        } else {
                ainfo->content_type = procmime_get_mime_type(file);
-               if (!ainfo->content_type)
+               if (!ainfo->content_type) {
                        ainfo->content_type =
                                g_strdup("application/octet-stream");
-               ainfo->encoding = ENC_BASE64;
+                       ainfo->encoding = ENC_BASE64;
+               } else if (!g_strncasecmp(ainfo->content_type, "text", 4))
+                       ainfo->encoding = procmime_get_encoding_for_file(file);
+               else
+                       ainfo->encoding = ENC_BASE64;
                ainfo->name = g_strdup(g_basename(filename ? filename : file)); 
        }
        ainfo->size = size;
@@ -2309,7 +2309,7 @@ static guint ins_quote(GtkSText *text, guint indent_len,
                       guint prev_line_pos, guint text_len,
                       gchar *quote_fmt)
 {
-       guint i, ins_len;
+       guint i, ins_len = 0;
        gchar ch;
 
        if (indent_len) {
@@ -2400,7 +2400,7 @@ static void compose_wrap_line_all(Compose *compose)
                /* we have encountered line break */
                if (ch_len == 1 && *cbuf == '\n') {
                        gint clen;
-                       gchar cb[MB_CUR_MAX];
+                       gchar cb[MB_LEN_MAX];
 
                        /* should we join the next line */
                        if ((i_len != cur_len) && do_delete &&
@@ -2654,7 +2654,7 @@ gboolean compose_check_for_valid_recipient(Compose *compose) {
        for(list = compose->header_list; list; list = list->next) {
                gchar *header;
                gchar *entry;
-               header = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->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') {
@@ -2671,6 +2671,7 @@ gboolean compose_check_for_valid_recipient(Compose *compose) {
                                }
                        }
                }
+               g_free(header);
                g_free(entry);
        }
        return recipient_found;
@@ -2851,8 +2852,8 @@ static gboolean compose_use_attach(Compose *compose) {
     return(gtk_clist_get_row_data(GTK_CLIST(compose->attach_clist), 0) != NULL);
 }
 
-static gint compose_bounce_write_headers_from_headerlist(Compose *compose, 
-                                                        FILE *fp)
+static gint compose_redirect_write_headers_from_headerlist(Compose *compose, 
+                                                          FILE *fp)
 {
        gchar buf[BUFFSIZE];
        gchar *str;
@@ -2860,17 +2861,14 @@ static gint compose_bounce_write_headers_from_headerlist(Compose *compose,
        GSList *list;
        ComposeHeaderEntry *headerentry;
        gchar *headerentryname;
-       gchar *header_w_colon;
        gchar *cc_hdr;
        gchar *to_hdr;
 
-       debug_print(_("Writing bounce header\n"));
+       debug_print(_("Writing redirect header\n"));
+
+       cc_hdr = prefs_common.trans_hdr ? _("Cc:") : "Cc:";
+       to_hdr = prefs_common.trans_hdr ? _("To:") : "To:";
 
-       header_w_colon = g_strconcat("To:", NULL);
-       to_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
-       header_w_colon = g_strconcat("Cc:", NULL);
-       cc_hdr = (prefs_common.trans_hdr ? gettext(header_w_colon) : header_w_colon);
-       
        first_address = TRUE;
        for(list = compose->header_list; list; list = list->next) {
                headerentry = ((ComposeHeaderEntry *)list->data);
@@ -2902,7 +2900,7 @@ static gint compose_bounce_write_headers_from_headerlist(Compose *compose,
        return(0);
 }
 
-static gint compose_bounce_write_headers(Compose *compose, FILE *fp)
+static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
 {
        gchar buf[BUFFSIZE];
        gchar *str;
@@ -2912,11 +2910,11 @@ static gint compose_bounce_write_headers(Compose *compose, FILE *fp)
        g_return_val_if_fail(compose->account != NULL, -1);
        g_return_val_if_fail(compose->account->address != NULL, -1);
 
-       /* Date */
+       /* Resent-Date */
        get_rfc822_date(buf, sizeof(buf));
        fprintf(fp, "Resent-Date: %s\n", buf);
 
-       /* From */
+       /* Resent-From */
        if (compose->account->name && *compose->account->name) {
                compose_convert_header
                        (buf, sizeof(buf), compose->account->name,
@@ -2926,8 +2924,26 @@ static gint compose_bounce_write_headers(Compose *compose, FILE *fp)
        } else
                fprintf(fp, "Resent-From: %s\n", compose->account->address);
 
-       /* To */
-       compose_bounce_write_headers_from_headerlist(compose, fp);
+       /* Subject */
+       str = gtk_entry_get_text(GTK_ENTRY(compose->subject_entry));
+       if (*str != '\0') {
+               Xstrdup_a(str, str, return -1);
+               g_strstrip(str);
+               if (*str != '\0') {
+                       compose_convert_header(buf, sizeof(buf), str,
+                                              strlen("Subject: "));
+                       fprintf(fp, "Subject: %s\n", buf);
+               }
+       }
+
+       /* Resent-Message-ID */
+       if (compose->account->gen_msgid) {
+               compose_generate_msgid(compose, buf, sizeof(buf));
+               fprintf(fp, "Resent-Message-Id: <%s>\n", buf);
+               compose->msgid = g_strdup(buf);
+       }
+
+       compose_redirect_write_headers_from_headerlist(compose, fp);
 
        /* separator between header and body */
        fputs("\n", fp);
@@ -2935,14 +2951,14 @@ static gint compose_bounce_write_headers(Compose *compose, FILE *fp)
        return 0;
 }
 
-static gint compose_bounce_write_to_file(Compose *compose, const gchar *file)
+static gint compose_redirect_write_to_file(Compose *compose, const gchar *file)
 {
        FILE *fp;
        FILE *fdest;
        size_t len;
        gchar buf[BUFFSIZE];
 
-       if ((fp = fopen(compose->bounce_filename, "rb")) == NULL) {
+       if ((fp = fopen(compose->redirect_filename, "rb")) == NULL) {
                FILE_OP_ERROR(file, "fopen");
                return -1;
        }
@@ -2961,16 +2977,22 @@ static gint compose_bounce_write_to_file(Compose *compose, const gchar *file)
 
        while (procheader_get_unfolded_line(buf, sizeof(buf), fp)) {
                /* should filter returnpath, delivered-to */
-               if ((g_strncasecmp(buf, "Return-Path:",
-                                  strlen("Return-Path:")) == 0)
-                   || (g_strncasecmp(buf, "Delivered-To:",
-                                     strlen("Delivered-To:")) == 0))
+               if (g_strncasecmp(buf, "Return-Path:",
+                                  strlen("Return-Path:")) == 0 ||
+                   g_strncasecmp(buf, "Delivered-To:",
+                                 strlen("Delivered-To:")) == 0 ||
+                   g_strncasecmp(buf, "Received:",
+                                 strlen("Received:")) == 0 ||
+                   g_strncasecmp(buf, "Subject:",
+                                 strlen("Subject:")) == 0 ||
+                   g_strncasecmp(buf, "X-UIDL:",
+                                 strlen("X-UIDL:")) == 0)
                        continue;
 
                if (fputs(buf, fdest) == -1)
                        goto error;
 
-               if (!prefs_common.bounce_keep_from) {
+               if (!prefs_common.redirect_keep_from) {
                        if (g_strncasecmp(buf, "From:",
                                          strlen("From:")) == 0) {
                                fputs(" (by way of ", fdest);
@@ -2994,7 +3016,7 @@ static gint compose_bounce_write_to_file(Compose *compose, const gchar *file)
                        goto error;
        }
 
-       compose_bounce_write_headers(compose, fdest);
+       compose_redirect_write_headers(compose, fdest);
 
        while ((len = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
                if (fwrite(buf, sizeof(gchar), len, fdest) != len) {
@@ -3020,40 +3042,36 @@ static gint compose_bounce_write_to_file(Compose *compose, const gchar *file)
 }
 
 
-#ifdef USE_GPGME
-/*
- * interfaces to rfc2015 to keep out the prefs stuff there.
+#if USE_GPGME
+/* interfaces to rfc2015 to keep out the prefs stuff there.
  * returns 0 on success and -1 on error. */
-static int compose_create_signers_list (Compose *compose, GSList **pkey_list)
+static gint compose_create_signers_list(Compose *compose, GSList **pkey_list)
 {
-       const char *keyid = NULL;
+       const gchar *key_id = NULL;
        GSList *key_list;
 
        switch (compose->account->sign_key) {
        case SIGN_KEY_DEFAULT:
                *pkey_list = NULL;
-               return 0;               /* nothing to do */
-
+               return 0;
        case SIGN_KEY_BY_FROM:
-               keyid = compose->account->address;
+               key_id = compose->account->address;
                break;
-
        case SIGN_KEY_CUSTOM:
-               keyid = compose->account->sign_key_id;
+               key_id = compose->account->sign_key_id;
                break;
-
        default:
-               g_assert_not_reached ();
+               break;
        }
 
-       key_list = rfc2015_create_signers_list(keyid);
+       key_list = rfc2015_create_signers_list(key_id);
 
        if (!key_list) {
-           alertpanel_error("Could not find any key associated with currently "
-                               "selected keyid `%s'!", keyid);
-           return -1;
+               alertpanel_error(_("Could not find any key associated with "
+                                  "currently selected key id `%s'."), key_id);
+               return -1;
        }
-       
+
        *pkey_list = key_list;
        return 0;
 }
@@ -3159,7 +3177,7 @@ static gint compose_write_to_file(Compose *compose, const gchar *file,
 
                for (i = 0; i < len; i += B64_LINE_SIZE) {
                        l = MIN(B64_LINE_SIZE, len - i);
-                       to64frombits(outbuf, buf + i, l);
+                       base64_encode(outbuf, buf + i, l);
                        fputs(outbuf, fp);
                        fputc('\n', fp);
                }
@@ -3184,16 +3202,16 @@ static gint compose_write_to_file(Compose *compose, const gchar *file,
 #if USE_GPGME
        if (compose->use_signing) {
                GSList *key_list;
-               
-               if (compose_create_signers_list(compose, &key_list) == -1 ||
-                       rfc2015_sign(file, key_list) < 0) {
-                   
+
+               if (compose_create_signers_list(compose, &key_list) < 0 ||
+                   rfc2015_sign(file, key_list) < 0) {
                        unlink(file);
                        return -1;
                }
        }
        if (compose->use_encryption) {
-               if (rfc2015_encrypt(file, compose->to_list, compose->account->ascii_armored) < 0) {
+               if (rfc2015_encrypt(file, compose->to_list,
+                                   compose->account->ascii_armored) < 0) {
                        unlink(file);
                        return -1;
                }
@@ -3253,7 +3271,6 @@ static gint compose_remove_reedit_target(Compose *compose)
        item = msginfo->folder;
        g_return_val_if_fail(item != NULL, -1);
 
-       folder_item_scan(item);
        if (procmsg_msg_exist(msginfo) &&
            (item->stype == F_DRAFT || item->stype == F_QUEUE)) {
                if (folder_item_remove_msg(item, msginfo->msgnum) < 0) {
@@ -3277,7 +3294,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        GSList *cur;
        gchar buf[BUFFSIZE];
        gint num;
-       MsgFlags flag = {0, 0};
         static gboolean lock = FALSE;
        PrefsAccount *mailac = NULL, *newsac = NULL;
        
@@ -3329,8 +3345,8 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        tmp2 = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(),
                                      G_DIR_SEPARATOR, (gint)compose);
 
-       if (compose->bounce_filename != NULL) {
-               if (compose_bounce_write_to_file(compose, tmp2) < 0) {
+       if (compose->redirect_filename != NULL) {
+               if (compose_redirect_write_to_file(compose, tmp2) < 0) {
                        unlink(tmp2);
                        lock = FALSE;
                        return -1;
@@ -3415,11 +3431,19 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        }
        /* Save copy folder */
        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn))) {
-               gchar *str;
+               gchar *savefolderid;
+               
+               savefolderid = gtk_editable_get_chars(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
+               fprintf(fp, "SCF:%s\n", savefolderid);
+               g_free(savefolderid);
+       }
+       /* Message-ID of message replying to */
+       if((compose->replyinfo != NULL) && (compose->replyinfo->msgid != NULL)) {
+               gchar *folderid;
                
-               str = gtk_editable_get_chars(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
-               fprintf(fp, "SCF:%s\n", str);
-               g_free(str);
+               folderid = folder_item_get_identifier(compose->replyinfo->folder);
+               fprintf(fp, "RMID:%s\x7f%d\x7f%s\n", folderid, compose->replyinfo->msgnum, compose->replyinfo->msgid);
+               g_free(folderid);
        }
        fprintf(fp, "\n");
 
@@ -3472,8 +3496,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                                (compose->targetinfo->folder, TRUE);
        }
 
-       procmsg_add_flags(queue, num, flag);
-       folder_item_scan(queue);
        folderview_update_item(queue, TRUE);
 
        if((msgnum != NULL) && (item != NULL)) {
@@ -3538,12 +3560,12 @@ static void compose_write_attach(Compose *compose, FILE *fp)
                        while ((len = fread(inbuf, sizeof(gchar),
                                            B64_LINE_SIZE, attach_fp))
                               == B64_LINE_SIZE) {
-                               to64frombits(outbuf, inbuf, B64_LINE_SIZE);
+                               base64_encode(outbuf, inbuf, B64_LINE_SIZE);
                                fputs(outbuf, fp);
                                fputc('\n', fp);
                        }
                        if (len > 0 && feof(attach_fp)) {
-                               to64frombits(outbuf, inbuf, len);
+                               base64_encode(outbuf, inbuf, len);
                                fputs(outbuf, fp);
                                fputc('\n', fp);
                        }
@@ -3794,14 +3816,14 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                fprintf(fp, "X-Mailer: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
-                       HOST_ALIAS);
+                       TARGET_ALIAS);
                        /* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
        }
        if (g_slist_length(compose->newsgroup_list) && !IS_IN_CUSTOM_HEADER("X-Newsreader")) {
                fprintf(fp, "X-Newsreader: %s (GTK+ %d.%d.%d; %s)\n",
                        prog_version,
                        gtk_major_version, gtk_minor_version, gtk_micro_version,
-                       HOST_ALIAS);
+                       TARGET_ALIAS);
                        /* utsbuf.sysname, utsbuf.release, utsbuf.machine); */
        }
 
@@ -3938,36 +3960,6 @@ static void compose_generate_msgid(Compose *compose, gchar *buf, gint len)
        g_free(addr);
 }
 
-static void compose_add_entry_field(GtkWidget *table, GtkWidget **hbox,
-                                   GtkWidget **entry, gint *count,
-                                   const gchar *label_str,
-                                   gboolean is_addr_entry)
-{
-       GtkWidget *label;
-
-       if (GTK_TABLE(table)->nrows < (*count) + 1)
-               gtk_table_resize(GTK_TABLE(table), (*count) + 1, 2);
-
-       *hbox = gtk_hbox_new(FALSE, 0);
-       label = gtk_label_new
-               (prefs_common.trans_hdr ? gettext(label_str) : label_str);
-       gtk_box_pack_end(GTK_BOX(*hbox), label, FALSE, FALSE, 0);
-       gtk_table_attach(GTK_TABLE(table), *hbox, 0, 1, *count, (*count) + 1,
-                        GTK_FILL, 0, 2, 0);
-       *entry = gtk_entry_new_with_max_length(MAX_ENTRY_LENGTH);
-       gtk_table_attach
-               (GTK_TABLE(table), *entry, 1, 2, *count, (*count) + 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0);
-#if 0 /* NEW COMPOSE GUI */
-       if (GTK_TABLE(table)->nrows > (*count) + 1)
-               gtk_table_set_row_spacing(GTK_TABLE(table), *count, 4);
-#endif
-
-       if (is_addr_entry)
-               address_completion_register_entry(GTK_ENTRY(*entry));
-
-       (*count)++;
-}
-
 static void compose_create_header_entry(Compose *compose) 
 {
        gchar *headers[] = {"To:", "Cc:", "Bcc:", "Newsgroups:", "Reply-To:", "Followup-To:", NULL};
@@ -4325,8 +4317,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        GtkWidget *scrolledwin;
        GtkWidget *text;
 
-       GtkWidget *table;
-
        UndoMain *undostruct;
 
        gchar *titles[N_ATTACH_COLS];
@@ -4483,6 +4473,8 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                           GTK_SIGNAL_FUNC(compose_grab_focus_cb), compose);
        gtk_signal_connect(GTK_OBJECT(text), "activate",
                           GTK_SIGNAL_FUNC(text_activated), compose);
+       gtk_signal_connect(GTK_OBJECT(text), "insert_text",
+                          GTK_SIGNAL_FUNC(text_inserted), compose);
        gtk_signal_connect_after(GTK_OBJECT(text), "button_press_event",
                                 GTK_SIGNAL_FUNC(compose_button_press_cb),
                                 edit_vbox);
@@ -4526,9 +4518,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                new_style = gtk_style_copy(style);
 
        if (prefs_common.textfont) {
-               CharSet charset;
-
-               charset = conv_get_current_charset();
                if (MB_CUR_MAX == 1) {
                        gchar *fontstr, *p;
 
@@ -4649,6 +4638,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        compose->modified = FALSE;
 
        compose->return_receipt = FALSE;
+       compose->paste_as_quotation = FALSE;
 
        compose->to_list        = NULL;
        compose->newsgroup_list = NULL;
@@ -4658,7 +4648,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        compose->exteditor_readdes = -1;
        compose->exteditor_tag     = -1;
 
-       compose->bounce_filename = NULL;
+       compose->redirect_filename = NULL;
        compose->undostruct = undostruct;
 #if USE_PSPELL
        
@@ -4678,7 +4668,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                        GtkWidget *menuitem;
 
                        if (!gtkpspell_set_sug_mode(gtkpspell, prefs_common.pspell_sugmode)) {
-                               debug_print(_("Pspell: could not set suggestion mode %s"),
+                               debug_print(_("Pspell: could not set suggestion mode %s\n"),
                                    gtkpspellcheckers->error_message);
                                gtkpspell_checkers_reset_error();
                        }
@@ -4980,7 +4970,7 @@ static void compose_set_priority_cb(gpointer data,
 static void compose_update_priority_menu_item(Compose * compose)
 {
        GtkItemFactory *ifactory;
-       GtkWidget *menuitem;
+       GtkWidget *menuitem = NULL;
 
        ifactory = gtk_item_factory_from_widget(compose->menubar);
        
@@ -5080,11 +5070,8 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
                gtk_stext_clear(GTK_STEXT(compose->text));
 
        if (compose->replyinfo == NULL) {
-               MsgInfo dummyinfo;
-
-               memset(&dummyinfo, 0, sizeof(MsgInfo));
-               parsed_str = compose_quote_fmt(compose, &dummyinfo,
-                                              tmpl->value, NULL, NULL);
+               parsed_str = compose_quote_fmt(compose, NULL, tmpl->value,
+                                              NULL, NULL);
        } else {
                if (prefs_common.quotemark && *prefs_common.quotemark)
                        qmark = prefs_common.quotemark;
@@ -5140,8 +5127,8 @@ static void compose_destroy(Compose *compose)
        g_free(compose->msgid);
        g_free(compose->boundary);
 
-       if (compose->bounce_filename)
-               g_free(compose->bounce_filename);
+       if (compose->redirect_filename)
+               g_free(compose->redirect_filename);
 
        g_free(compose->exteditor_file);
 
@@ -6071,9 +6058,9 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        FolderItem *draft;
        gchar *tmp;
        gint msgnum;
-       MsgFlags flag = {0, 0};
        static gboolean lock = FALSE;
-
+       MsgInfo *newmsginfo;
+       
        if (lock) return;
 
        draft = account_get_special_folder(compose->account, F_DRAFT);
@@ -6090,7 +6077,6 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                return;
        }
 
-       folder_item_scan(draft);
        if ((msgnum = folder_item_add_msg(draft, tmp, TRUE)) < 0) {
                unlink(tmp);
                g_free(tmp);
@@ -6108,10 +6094,11 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                                               TRUE);
        }
 
-       procmsg_add_flags(draft, msgnum, flag);
-       folder_item_scan(draft);
+       newmsginfo = folder_item_fetch_msginfo(draft, msgnum);
+       procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
        folderview_update_item(draft, TRUE);
-
+       procmsg_msginfo_free(newmsginfo);
+       
        lock = FALSE;
 
        /* 0: quit editing  1: keep editing */
@@ -6132,7 +6119,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
                g_free(path);
 
                procmsg_msginfo_free(compose->targetinfo);
-               compose->targetinfo = g_new0(MsgInfo, 1);
+               compose->targetinfo = procmsg_msginfo_new();
                compose->targetinfo->msgnum = msgnum;
                compose->targetinfo->size = s.st_size;
                compose->targetinfo->mtime = s.st_mtime;
@@ -6146,7 +6133,7 @@ static void compose_attach_cb(gpointer data, guint action, GtkWidget *widget)
        Compose *compose = (Compose *)data;
        GList *file_list;
 
-       if (compose->bounce_filename != NULL)
+       if (compose->redirect_filename != NULL)
                return;
 
        file_list = filesel_select_multiple_files(_("Select file"), NULL);
@@ -6295,19 +6282,23 @@ static void compose_paste_cb(Compose *compose)
                        (GTK_EDITABLE(compose->focused_editable));
 }
 
-static void compose_allsel_cb(Compose *compose)
+static void compose_paste_as_quote_cb(Compose *compose)
 {
        if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
-               gtk_editable_select_region
-                       (GTK_EDITABLE(compose->focused_editable), 0, -1);
+           GTK_WIDGET_HAS_FOCUS(compose->focused_editable)) {
+               compose->paste_as_quotation = TRUE;
+               gtk_editable_paste_clipboard
+                       (GTK_EDITABLE(compose->focused_editable));
+               compose->paste_as_quotation = FALSE;
+       }
 }
 
-static void compose_move_beginning_of_line_cb(Compose *compose)
+static void compose_allsel_cb(Compose *compose)
 {
        if (compose->focused_editable &&
-               GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
-               gtk_stext_move_beginning_of_line(GTK_STEXT(compose->focused_editable));
+           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+               gtk_editable_select_region
+                       (GTK_EDITABLE(compose->focused_editable), 0, -1);
 }
 
 static void compose_gtk_stext_action_cb(Compose *compose, ComposeCallGtkSTextAction action)
@@ -6759,6 +6750,42 @@ static void text_activated(GtkWidget *widget, Compose *compose)
        compose_send_control_enter(compose);
 }
 
+static void text_inserted(GtkWidget *widget, const gchar *text,
+                         gint length, gint *position, Compose *compose)
+{
+       GtkEditable *editable = GTK_EDITABLE(widget);
+
+       gtk_signal_handler_block_by_func(GTK_OBJECT(widget),
+                                        GTK_SIGNAL_FUNC(text_inserted),
+                                        compose);
+       if (compose->paste_as_quotation) {
+               gchar *new_text;
+               gchar *qmark;
+               gint pos;
+
+               new_text = g_strndup(text, length);
+               if (prefs_common.quotemark && *prefs_common.quotemark)
+                       qmark = prefs_common.quotemark;
+               else
+                       qmark = "> ";
+               gtk_stext_set_point(GTK_STEXT(widget), *position);
+               compose_quote_fmt(compose, NULL, "%Q", qmark, new_text);
+               pos = gtk_stext_get_point(GTK_STEXT(widget));
+               gtk_editable_set_position(editable, pos);
+               *position = pos;
+               g_free(new_text);
+       } else
+               gtk_editable_insert_text(editable, text, length, position);
+
+       if (prefs_common.autowrap)
+               compose_wrap_line_all(compose);
+
+       gtk_signal_handler_unblock_by_func(GTK_OBJECT(widget),
+                                          GTK_SIGNAL_FUNC(text_inserted),
+                                          compose);
+       gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert_text");
+}
+
 static gboolean compose_send_control_enter(Compose *compose)
 {
        GdkEvent *ev;