2010-12-23 [colin] 3.7.8cvs23
[claws.git] / src / compose.c
index 734ad44ead8669bea66bcd1e5949d306b4063f90..ca3532d6f4e5adef07414ff28a1148f79439c4d5 100644 (file)
@@ -107,8 +107,9 @@ enum
        COL_MIMETYPE = 0,
        COL_SIZE     = 1,
        COL_NAME     = 2,
-       COL_DATA     = 3,
-       COL_AUTODATA = 4,
+       COL_CHARSET  = 3,
+       COL_DATA     = 4,
+       COL_AUTODATA = 5,
        N_COL_COLUMNS
 };
 
@@ -249,7 +250,8 @@ static ComposeInsertResult compose_insert_file      (Compose        *compose,
 static gboolean compose_attach_append          (Compose        *compose,
                                                 const gchar    *file,
                                                 const gchar    *type,
-                                                const gchar    *content_type);
+                                                const gchar    *content_type,
+                                                const gchar    *charset);
 static void compose_attach_parts               (Compose        *compose,
                                                 MsgInfo        *msginfo);
 
@@ -499,7 +501,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
                                  gboolean followup_and_reply_to,
                                  const gchar *body);
 
-static gboolean compose_headerentry_changed_cb    (GtkWidget          *entry,
+static void compose_headerentry_changed_cb        (GtkWidget          *entry,
                                            ComposeHeaderEntry *headerentry);
 static gboolean compose_headerentry_key_press_event_cb(GtkWidget              *entry,
                                            GdkEventKey        *event,
@@ -533,6 +535,8 @@ static void compose_set_dictionaries_from_folder_prefs(Compose *compose,
                                                FolderItem *folder_item);
 #endif
 static void compose_attach_update_label(Compose *compose);
+static void compose_set_folder_prefs(Compose *compose, FolderItem *folder,
+                                    gboolean respect_default_to);
 
 static GtkActionEntry compose_popup_entries[] =
 {
@@ -710,6 +714,7 @@ static GtkRadioActionEntry compose_radio_enc_entries[] =
        ENC_ACTION("Japanese/"CS_ISO_2022_JP_2, C_ISO_2022_JP_2, "ISO-2022-JP-_2"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Japanese/"CS_EUC_JP, C_EUC_JP, "_EUC-JP"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Japanese/"CS_SHIFT_JIS, C_SHIFT_JIS, "_Shift-JIS"), /* RADIO compose_set_encoding_cb */
+       ENC_ACTION("Chinese/"CS_GB18030, C_GB18030, "_GB18030"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Chinese/"CS_GB2312, C_GB2312, "_GB2312"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Chinese/"CS_GBK, C_GBK, "GB_K"), /* RADIO compose_set_encoding_cb */
        ENC_ACTION("Chinese/"CS_BIG5, C_BIG5, "_Big5-JP"), /* RADIO compose_set_encoding_cb */
@@ -1029,24 +1034,8 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                if (mailto && *mailto != '\0') {
                        mfield = compose_entries_set(compose, mailto, COMPOSE_TO);
 
-               } else if (item && item->prefs) {
-                       if (item->prefs->enable_default_bcc) {
-                               compose_entry_append(compose, item->prefs->default_bcc,
-                                               COMPOSE_BCC, PREF_FOLDER);
-                       }
-                       if (item->prefs->enable_default_cc) {
-                               compose_entry_append(compose, item->prefs->default_cc,
-                                               COMPOSE_CC, PREF_FOLDER);
-                       }
-                       if (item->prefs->enable_default_replyto) {
-                               compose_entry_append(compose, item->prefs->default_replyto,
-                                               COMPOSE_REPLYTO, PREF_FOLDER);
-                       }
-                       if (item->prefs->enable_default_to) {
-                               compose_entry_append(compose, item->prefs->default_to,
-                                               COMPOSE_TO, PREF_FOLDER);
-                               compose_entry_mark_default_to(compose, item->prefs->default_to);
-                       }
+               } else {
+                       compose_set_folder_prefs(compose, item, TRUE);
                }
                if (item && item->ret_rcpt) {
                        cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE);
@@ -1160,7 +1149,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
                for (i = 0; i < attach_files->len; i++) {
                        file = g_ptr_array_index(attach_files, i);
-                       compose_attach_append(compose, file, file, NULL);
+                       compose_attach_append(compose, file, file, NULL, NULL);
                }
        }
 
@@ -1310,6 +1299,7 @@ static Compose *compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar
 
        switch (mode) {
        case COMPOSE_REPLY:
+       case COMPOSE_REPLY_TO_ADDRESS:
                compose = compose_reply(msginfo, COMPOSE_QUOTE_CHECK,
                              FALSE, prefs_common.default_reply_list, FALSE, body);
                break;
@@ -1421,6 +1411,9 @@ static Compose *compose_reply_mode(ComposeMode mode, GSList *msginfo_list, gchar
                debug_print("reply mode List\n");
                cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/ReplyMode/List", TRUE);
                break;
+       case COMPOSE_REPLY_TO_ADDRESS:
+               cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options/ReplyMode", FALSE);
+               break;
        default:
                break;
        }
@@ -1432,7 +1425,7 @@ static Compose *compose_reply(MsgInfo *msginfo,
                                   gboolean to_all,
                                   gboolean to_ml,
                                   gboolean to_sender, 
-                  const gchar *body)
+                                  const gchar *body)
 {
        return compose_generic_reply(msginfo, quote_mode, to_all, to_ml, 
                              to_sender, FALSE, body);
@@ -1683,6 +1676,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
        GtkTextView *textview;
        GtkTextBuffer *textbuf;
        GtkTextIter iter;
+       ComposeMode mode;
 
        cm_return_val_if_fail(msginfo != NULL, NULL);
        cm_return_val_if_fail(msginfo->folder != NULL, NULL);
@@ -1692,7 +1686,11 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                                (msginfo)))
                account = cur_account;
 
-       compose = compose_create(account, msginfo->folder, COMPOSE_FORWARD, batch);
+       if (!prefs_common.forward_as_attachment)
+               mode = COMPOSE_FORWARD_INLINE;
+       else
+               mode = COMPOSE_FORWARD;
+       compose = compose_create(account, msginfo->folder, mode, batch);
 
        compose->updating = TRUE;
        compose->fwdinfo = procmsg_msginfo_get_full_info(msginfo);
@@ -1767,7 +1765,7 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                        g_warning("%s: file not exist\n", msgfile);
                else
                        compose_attach_append(compose, msgfile, msgfile,
-                                             "message/rfc822");
+                                             "message/rfc822", NULL);
 
                g_free(msgfile);
        } else {
@@ -1961,7 +1959,7 @@ static Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_
                        g_warning("%s: file not exist\n", msgfile);
                else
                        compose_attach_append(compose, msgfile, msgfile,
-                               "message/rfc822");
+                               "message/rfc822", NULL);
                g_free(msgfile);
        }
        
@@ -2676,7 +2674,7 @@ static MailField compose_entries_set(Compose *compose, const gchar *mailto, Comp
                while (attach[i] != NULL) {
                        gchar *utf8_filename = conv_filename_to_utf8(attach[i]);
                        if (utf8_filename) {
-                               if (compose_attach_append(compose, attach[i], utf8_filename, NULL)) {
+                               if (compose_attach_append(compose, attach[i], utf8_filename, NULL, NULL)) {
                                        gchar *tmp = g_strdup_printf("%s%s\n",
                                                        warn_files?warn_files:"",
                                                        utf8_filename);
@@ -3063,6 +3061,52 @@ static gboolean is_subscription(const gchar *ml_post, const gchar *from)
        return result;
 }
 
+static void compose_set_folder_prefs(Compose *compose, FolderItem *folder,
+                                    gboolean respect_default_to)
+{
+       if (!compose)
+               return;
+       if (!folder || !folder->prefs)
+               return;
+
+       if (respect_default_to && folder->prefs->enable_default_to) {
+               compose_entry_append(compose, folder->prefs->default_to,
+                                       COMPOSE_TO, PREF_FOLDER);
+               compose_entry_mark_default_to(compose, folder->prefs->default_to);
+       }
+       if (folder->prefs->enable_default_cc)
+               compose_entry_append(compose, folder->prefs->default_cc,
+                                       COMPOSE_CC, PREF_FOLDER);
+       if (folder->prefs->enable_default_bcc)
+               compose_entry_append(compose, folder->prefs->default_bcc,
+                                       COMPOSE_BCC, PREF_FOLDER);
+       if (folder->prefs->enable_default_replyto)
+               compose_entry_append(compose, folder->prefs->default_replyto,
+                                       COMPOSE_REPLYTO, PREF_FOLDER);
+}
+
+static void compose_reply_set_subject(Compose *compose, MsgInfo *msginfo)
+{
+       gchar *buf, *buf2;
+       gchar *p;
+       
+       if (!compose || !msginfo)
+               return;
+
+       if (msginfo->subject && *msginfo->subject) {
+               buf = p = g_strdup(msginfo->subject);
+               p += subject_get_prefix_length(p);
+               memmove(buf, p, strlen(p) + 1);
+
+               buf2 = g_strdup_printf("Re: %s", buf);
+               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf2);
+
+               g_free(buf2);
+               g_free(buf);
+       } else
+               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), "Re: ");
+}
+
 static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                    gboolean to_all, gboolean to_ml,
                                    gboolean to_sender,
@@ -3086,20 +3130,8 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                msginfo->folder->prefs->enable_default_reply_to;
 
        if (compose->account->protocol != A_NNTP) {
-               if (msginfo && msginfo->folder && msginfo->folder->prefs) {
-                       if (msginfo->folder->prefs->enable_default_replyto) {
-                               compose_entry_append(compose, msginfo->folder->prefs->default_replyto,
-                                                       COMPOSE_REPLYTO, PREF_FOLDER);
-                       }
-                       if (msginfo->folder->prefs->enable_default_bcc) {
-                               compose_entry_append(compose, msginfo->folder->prefs->default_bcc,
-                                                       COMPOSE_BCC, PREF_FOLDER);
-                       }
-                       if (msginfo->folder->prefs->enable_default_cc) {
-                               compose_entry_append(compose, msginfo->folder->prefs->default_cc,
-                                                       COMPOSE_CC, PREF_FOLDER);
-                       }
-               }
+               compose_set_folder_prefs(compose, msginfo->folder, FALSE);
+
                if (reply_to_ml && !default_reply_to) {
                        
                        gboolean is_subscr = is_subscription(compose->ml_post,
@@ -3197,22 +3229,7 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                 compose->newsgroups ? compose->newsgroups : "",
                                 COMPOSE_NEWSGROUPS, PREF_NONE);
        }
-
-       if (msginfo->subject && *msginfo->subject) {
-               gchar *buf, *buf2;
-               gchar *p;
-
-               buf = p = g_strdup(msginfo->subject);
-               p += subject_get_prefix_length(p);
-               memmove(buf, p, strlen(p) + 1);
-
-               buf2 = g_strdup_printf("Re: %s", buf);
-               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf2);
-
-               g_free(buf2);
-               g_free(buf);
-       } else
-               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), "Re: ");
+       compose_reply_set_subject(compose, msginfo);
 
        if (to_ml && compose->ml_post) return;
        if (!to_all || compose->account->protocol == A_NNTP) return;
@@ -3282,7 +3299,6 @@ static void compose_reedit_set_entry(Compose *compose, MsgInfo *msginfo)
        SET_ADDRESS(COMPOSE_REPLYTO, compose->replyto);
        SET_ADDRESS(COMPOSE_NEWSGROUPS, compose->newsgroups);
        SET_ADDRESS(COMPOSE_FOLLOWUPTO, compose->followup_to);
-       SET_ADDRESS(COMPOSE_INREPLYTO, compose->inreplyto);
 
        compose_update_priority_menu_item(compose);
        compose_update_privacy_system_menu_item(compose, FALSE);
@@ -3503,7 +3519,8 @@ static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *fi
 
 static gboolean compose_attach_append(Compose *compose, const gchar *file,
                                  const gchar *filename,
-                                 const gchar *content_type)
+                                 const gchar *content_type,
+                                 const gchar *charset)
 {
        AttachInfo *ainfo;
        GtkTreeIter iter;
@@ -3521,8 +3538,8 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
                if (file_from_uri && is_file_exist(file_from_uri)) {
                        result = compose_attach_append(
                                                compose, file_from_uri,
-                                               filename,
-                                               content_type);
+                                               filename, content_type,
+                                               charset);
                }
                g_free(file_from_uri);
                if (result)
@@ -3570,10 +3587,12 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
 
                        procmsg_msginfo_free(msginfo);
                } else {
-                       if (!g_ascii_strncasecmp(content_type, "text", 4))
+                       if (!g_ascii_strncasecmp(content_type, "text/", 5)) {
+                               ainfo->charset = g_strdup(charset);
                                ainfo->encoding = procmime_get_encoding_for_text_file(file, &has_binary);
-                       else
+                       } else {
                                ainfo->encoding = ENC_BASE64;
+                       }
                        name = g_path_get_basename(filename ? filename : file);
                        ainfo->name = g_strdup(name);
                }
@@ -3584,7 +3603,7 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
                        ainfo->content_type =
                                g_strdup("application/octet-stream");
                        ainfo->encoding = ENC_BASE64;
-               } else if (!g_ascii_strncasecmp(ainfo->content_type, "text", 4))
+               } else if (!g_ascii_strncasecmp(ainfo->content_type, "text/", 5))
                        ainfo->encoding =
                                procmime_get_encoding_for_text_file(file, &has_binary);
                else
@@ -3603,6 +3622,8 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
        if (!strcmp(ainfo->content_type, "unknown") || has_binary) {
                g_free(ainfo->content_type);
                ainfo->content_type = g_strdup("application/octet-stream");
+               g_free(ainfo->charset);
+               ainfo->charset = NULL;
        }
 
        ainfo->size = (goffset)size;
@@ -3616,6 +3637,7 @@ static gboolean compose_attach_append(Compose *compose, const gchar *file,
                           COL_MIMETYPE, ainfo->content_type,
                           COL_SIZE, size_text,
                           COL_NAME, ainfo->name,
+                          COL_CHARSET, ainfo->charset,
                           COL_DATA, ainfo,
                           COL_AUTODATA, auto_ainfo,
                           -1);
@@ -3719,7 +3741,8 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
                                if (partname == NULL)
                                        partname = "";
                                compose_attach_append(compose, outfile, 
-                                                     partname, content_type);
+                                                     partname, content_type,
+                                                     procmime_mimeinfo_get_parameter(child, "charset"));
                        } else {
                                compose_force_signing(compose, compose->account, NULL);
                        }
@@ -5952,24 +5975,40 @@ static int compose_add_attachments(Compose *compose, MimeInfo *parent)
                if (mimepart->type == MIMETYPE_MESSAGE && 
                    !g_ascii_strcasecmp(mimepart->subtype, "rfc822")) {
                        mimepart->disposition = DISPOSITIONTYPE_INLINE;
-               } else {
-                       if (ainfo->name) {
-                               if (mimepart->type == MIMETYPE_APPLICATION && 
-                                  !strcmp2(mimepart->subtype, "octet-stream"))
-                                       g_hash_table_insert(mimepart->typeparameters,
-                                                   g_strdup("name"), g_strdup(ainfo->name));
-                               g_hash_table_insert(mimepart->dispositionparameters,
-                                           g_strdup("filename"), g_strdup(ainfo->name));
+               } else if (mimepart->type == MIMETYPE_TEXT) {
+                       if (!ainfo->name && compose->mode == COMPOSE_FORWARD_INLINE) {
+                               /* Text parts with no name come from multipart/alternative
+                               * forwards. Make sure the recipient won't look at the 
+                               * original HTML part by mistake. */
                                mimepart->disposition = DISPOSITIONTYPE_ATTACHMENT;
+                               ainfo->name = g_strdup_printf(_("Original %s part"),
+                                                               mimepart->subtype);
                        }
-               }
-
-               if (compose->use_signing) {
+                       if (ainfo->charset)
+                               g_hash_table_insert(mimepart->typeparameters,
+                                                   g_strdup("charset"), g_strdup(ainfo->charset));
+               }
+               if (ainfo->name && mimepart->type != MIMETYPE_MESSAGE) {
+                       if (mimepart->type == MIMETYPE_APPLICATION && 
+                          !strcmp2(mimepart->subtype, "octet-stream"))
+                               g_hash_table_insert(mimepart->typeparameters,
+                                               g_strdup("name"), g_strdup(ainfo->name));
+                       g_hash_table_insert(mimepart->dispositionparameters,
+                                       g_strdup("filename"), g_strdup(ainfo->name));
+                       mimepart->disposition = DISPOSITIONTYPE_ATTACHMENT;
+               }
+
+               if (mimepart->type == MIMETYPE_MESSAGE
+                   || mimepart->type == MIMETYPE_MULTIPART)
+                       ainfo->encoding = ENC_BINARY;
+               else if (compose->use_signing) {
                        if (ainfo->encoding == ENC_7BIT)
                                ainfo->encoding = ENC_QUOTED_PRINTABLE;
                        else if (ainfo->encoding == ENC_8BIT)
                                ainfo->encoding = ENC_BASE64;
                }
+
+               
                
                procmime_encode_content(mimepart, ainfo->encoding);
 
@@ -6117,7 +6156,12 @@ static gchar *compose_get_header(Compose *compose)
        compose_add_headerfield_from_headerlist(compose, header, "Cc", ", ");
 
        /* Bcc */
-       compose_add_headerfield_from_headerlist(compose, header, "Bcc", ", ");
+       /* 
+        * If this account is a NNTP account remove Bcc header from 
+        * message body since it otherwise will be publicly shown
+        */
+       if (compose->account->protocol != A_NNTP)
+               compose_add_headerfield_from_headerlist(compose, header, "Bcc", ", ");
 
        /* Subject */
        str = gtk_editable_get_chars(GTK_EDITABLE(compose->subject_entry), 0, -1);
@@ -6495,13 +6539,9 @@ static void compose_create_header_entry(Compose *compose)
                         G_CALLBACK(compose_grab_focus_cb), compose);
 
        /* Entry field with cleanup button */
-#if GTK_CHECK_VERSION(2, 8, 0)
        button = gtk_button_new();
        gtk_button_set_image(GTK_BUTTON(button),
                         gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU));
-#else
-       button = gtk_button_new_with_label(_("Clear"));
-#endif
        gtk_widget_show(button);
        CLAWS_SET_TIP(button,
                _("Delete entry contents"));
@@ -6566,8 +6606,15 @@ static void compose_add_header_entry(Compose *compose, const gchar *header,
 {
        ComposeHeaderEntry *last_header = compose->header_last;
        gchar *tmp = g_strdup(text), *email;
-       gboolean replyto_hdr = g_str_has_suffix(header, "-To:");
-       
+       gboolean replyto_hdr;
+       
+       replyto_hdr = (!strcasecmp(header,
+                               prefs_common_translated_header_name("Reply-To:")) ||
+                       !strcasecmp(header,
+                               prefs_common_translated_header_name("Followup-To:")) ||
+                       !strcasecmp(header,
+                               prefs_common_translated_header_name("In-Reply-To:")));
+               
        extract_address(tmp);
        email = g_utf8_strdown(tmp, -1);
        
@@ -6581,7 +6628,7 @@ static void compose_add_header_entry(Compose *compose, const gchar *header,
                return;
        }
        
-       if (!strcmp(header, prefs_common_translated_header_name("In-Reply-To:")))
+       if (!strcasecmp(header, prefs_common_translated_header_name("In-Reply-To:")))
                gtk_entry_set_text(GTK_ENTRY(
                        gtk_bin_get_child(GTK_BIN(last_header->combo))), header);
        else
@@ -6699,6 +6746,7 @@ static GtkWidget *compose_create_attach(Compose *compose)
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
+                                  G_TYPE_STRING,
                                   G_TYPE_POINTER,
                                   G_TYPE_AUTO_POINTER,
                                   -1);
@@ -7032,6 +7080,7 @@ static Compose *compose_create(PrefsAccount *account,
        titles[COL_MIMETYPE] = _("MIME type");
        titles[COL_SIZE]     = _("Size");
        titles[COL_NAME]     = _("Name");
+       titles[COL_CHARSET]  = _("Charset");
 
        compose->batch = batch;
        compose->account = account;
@@ -7243,6 +7292,7 @@ static Compose *compose_create(PrefsAccount *account,
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Encoding/Japanese", CS_SHIFT_JIS, "Options/Encoding/Japanese/"CS_SHIFT_JIS, GTK_UI_MANAGER_MENUITEM)
 
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Encoding", "Chinese", "Options/Encoding/Chinese", GTK_UI_MANAGER_MENU)
+       MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Encoding/Chinese", CS_GB18030, "Options/Encoding/Chinese/"CS_GB18030, GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Encoding/Chinese", CS_GB2312, "Options/Encoding/Chinese/"CS_GB2312, GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Encoding/Chinese", CS_GBK, "Options/Encoding/Chinese/"CS_GBK, GTK_UI_MANAGER_MENUITEM)
        MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Encoding/Chinese", CS_BIG5, "Options/Encoding/Chinese/"CS_BIG5, GTK_UI_MANAGER_MENUITEM)
@@ -7380,6 +7430,10 @@ static Compose *compose_create(PrefsAccount *account,
        gtk_widget_set_size_request(scrolledwin, prefs_common.compose_width, -1);
 
        text = gtk_text_view_new();
+       if (prefs_common.show_compose_margin) {
+               gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 6);
+               gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 6);
+       }
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
        gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD_CHAR);
        gtk_text_view_set_editable(GTK_TEXT_VIEW(text), TRUE);
@@ -7567,7 +7621,7 @@ static Compose *compose_create(PrefsAccount *account,
                        }
                }
        }
-    compose->gtkaspell = gtkaspell;
+       compose->gtkaspell = gtkaspell;
        compose_spell_menu_changed(compose);
        claws_spell_entry_set_gtkaspell(CLAWS_SPELL_ENTRY(subject_entry), gtkaspell);
 #endif
@@ -7708,6 +7762,7 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        CLAWS_SET_TIP(from_name,
                _("Sender address to be used"));
 
+       compose->account_combo = optmenu;
        compose->from_name = from_name;
        
        return hbox;
@@ -7909,6 +7964,7 @@ static void compose_set_out_encoding(Compose *compose)
                case C_ISO_2022_JP_2: branch = "Menu/Options/Encoding/Japanese/" CS_ISO_2022_JP_2; break;
                case C_EUC_JP: branch = "Menu/Options/Encoding/Japanese/" CS_EUC_JP; break;
                case C_SHIFT_JIS: branch = "Menu/Options/Encoding/Japanese/" CS_SHIFT_JIS; break;
+               case C_GB18030: branch = "Menu/Options/Encoding/Chinese/" CS_GB18030; break;
                case C_GB2312: branch = "Menu/Options/Encoding/Chinese/" CS_GB2312; break;
                case C_GBK: branch = "Menu/Options/Encoding/Chinese/" CS_GBK; break;
                case C_BIG5: branch = "Menu/Options/Encoding/Chinese/" CS_BIG5; break;
@@ -8358,6 +8414,7 @@ static void compose_attach_info_free(AttachInfo *ainfo)
        g_free(ainfo->file);
        g_free(ainfo->content_type);
        g_free(ainfo->name);
+       g_free(ainfo->charset);
        g_free(ainfo);
 }
 
@@ -8562,6 +8619,7 @@ static void compose_attach_property(GtkAction *action, gpointer data)
                                   COL_MIMETYPE, ainfo->content_type,
                                   COL_SIZE, text,
                                   COL_NAME, ainfo->name,
+                                  COL_CHARSET, ainfo->charset,
                                   -1);
                
                break;
@@ -9068,7 +9126,7 @@ static gboolean compose_edit_size_alloc(GtkEditable *widget,
 }
 
 typedef struct {
-       ComposeEntryType        header;
+       gchar                   *header;
        gchar                   *entry;
        ComposePrefType         type;
        gboolean                entry_marked;
@@ -9109,8 +9167,8 @@ static void account_activated(GtkComboBox *optmenu, gpointer data)
                        }
                        
                        state = g_malloc0(sizeof(HeaderEntryState));
-                       state->header = combobox_get_active_data(
-                                       GTK_COMBO_BOX(hentry->combo));
+                       state->header = gtk_editable_get_chars(GTK_EDITABLE(
+                                       gtk_bin_get_child(GTK_BIN(hentry->combo))), 0, -1);
                        state->entry = gtk_editable_get_chars(
                                        GTK_EDITABLE(hentry->entry), 0, -1);
                        state->type = hentry->type;
@@ -9151,12 +9209,14 @@ static void account_activated(GtkComboBox *optmenu, gpointer data)
                for (list = saved_list; list; list = list->next) {
                        state = (HeaderEntryState *) list->data;
                        
-                       compose_entry_append(compose, state->entry,
-                                               state->header, state->type);
+                       compose_add_header_entry(compose, state->header,
+                                               state->entry, state->type);
                        if (state->entry_marked)
                                compose_entry_mark_default_to(compose, state->entry);
-                               
+                       
+                       g_free(state->header);  
                        g_free(state->entry);
+                       g_free(state);
                }
                g_slist_free(saved_list);
                
@@ -9251,7 +9311,7 @@ static void compose_allow_user_actions (Compose *compose, gboolean allow)
 static void compose_send_cb(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
-       
+
        if (prefs_common.work_offline && 
            !inc_offline_should_override(TRUE,
                _("Claws Mail needs network access in order "
@@ -9589,7 +9649,7 @@ void compose_attach_from_list(Compose *compose, GList *file_list, gboolean free_
                for ( tmp = file_list; tmp; tmp = tmp->next) {
                        gchar *file = (gchar *) tmp->data;
                        gchar *utf8_filename = conv_filename_to_utf8(file);
-                       compose_attach_append(compose, file, utf8_filename, NULL);
+                       compose_attach_append(compose, file, utf8_filename, NULL, NULL);
                        compose_changed_cb(NULL, compose);
                        if (free_data) {
                        g_free(file);
@@ -9905,7 +9965,7 @@ static void compose_cut_cb(GtkAction *action, gpointer data)
        Compose *compose = (Compose *)data;
        if (compose->focused_editable 
 #ifndef GENERIC_UMPC
-           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+           && gtkut_widget_has_focus(compose->focused_editable)
 #endif
            )
                entry_cut_clipboard(compose->focused_editable);
@@ -9916,7 +9976,7 @@ static void compose_copy_cb(GtkAction *action, gpointer data)
        Compose *compose = (Compose *)data;
        if (compose->focused_editable 
 #ifndef GENERIC_UMPC
-           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+           && gtkut_widget_has_focus(compose->focused_editable)
 #endif
            )
                entry_copy_clipboard(compose->focused_editable);
@@ -9929,14 +9989,14 @@ static void compose_paste_cb(GtkAction *action, gpointer data)
        GtkTextBuffer *buffer;
        BLOCK_WRAP();
        if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+           gtkut_widget_has_focus(compose->focused_editable))
                entry_paste_clipboard(compose, compose->focused_editable, 
                                prefs_common.linewrap_pastes,
                                GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
 
 #ifdef USE_ENCHANT
-       if (GTK_WIDGET_HAS_FOCUS(compose->text) &&
+       if (gtkut_widget_has_focus(compose->text) &&
            compose->gtkaspell && 
             compose->gtkaspell->check_while_typing)
                gtkaspell_highlight_all(compose->gtkaspell);
@@ -9949,7 +10009,7 @@ static void compose_paste_as_quote_cb(GtkAction *action, gpointer data)
        gint wrap_quote = prefs_common.linewrap_quote;
        if (compose->focused_editable 
 #ifndef GENERIC_UMPC
-           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+           && gtkut_widget_has_focus(compose->focused_editable)
 #endif
            ) {
                /* let text_insert() (called directly or at a later time
@@ -9978,7 +10038,7 @@ static void compose_paste_no_wrap_cb(GtkAction *action, gpointer data)
        BLOCK_WRAP();
        if (compose->focused_editable 
 #ifndef GENERIC_UMPC
-           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+           && gtkut_widget_has_focus(compose->focused_editable)
 #endif
            )
                entry_paste_clipboard(compose, compose->focused_editable, FALSE,
@@ -9986,7 +10046,7 @@ static void compose_paste_no_wrap_cb(GtkAction *action, gpointer data)
        UNBLOCK_WRAP();
 
 #ifdef USE_ENCHANT
-       if (GTK_WIDGET_HAS_FOCUS(compose->text) &&
+       if (gtkut_widget_has_focus(compose->text) &&
            compose->gtkaspell && 
             compose->gtkaspell->check_while_typing)
                gtkaspell_highlight_all(compose->gtkaspell);
@@ -10001,7 +10061,7 @@ static void compose_paste_wrap_cb(GtkAction *action, gpointer data)
        BLOCK_WRAP();
        if (compose->focused_editable 
 #ifndef GENERIC_UMPC
-           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+           && gtkut_widget_has_focus(compose->focused_editable)
 #endif
            )
                entry_paste_clipboard(compose, compose->focused_editable, TRUE,
@@ -10009,7 +10069,7 @@ static void compose_paste_wrap_cb(GtkAction *action, gpointer data)
        UNBLOCK_WRAP();
 
 #ifdef USE_ENCHANT
-       if (GTK_WIDGET_HAS_FOCUS(compose->text) &&
+       if (gtkut_widget_has_focus(compose->text) &&
            compose->gtkaspell &&
             compose->gtkaspell->check_while_typing)
                gtkaspell_highlight_all(compose->gtkaspell);
@@ -10021,7 +10081,7 @@ static void compose_allsel_cb(GtkAction *action, gpointer data)
        Compose *compose = (Compose *)data;
        if (compose->focused_editable 
 #ifndef GENERIC_UMPC
-           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+           && gtkut_widget_has_focus(compose->focused_editable)
 #endif
            )
                entry_allsel(compose->focused_editable);
@@ -10325,7 +10385,7 @@ static void compose_advanced_action_cb(GtkAction *gaction, gpointer data)
                {textview_delete_to_line_end}
        };
 
-       if (!GTK_WIDGET_HAS_FOCUS(text)) return;
+       if (!gtkut_widget_has_focus(GTK_WIDGET(text))) return;
 
        if (action >= COMPOSE_CALL_ADVANCED_ACTION_MOVE_BEGINNING_OF_LINE &&
            action <= COMPOSE_CALL_ADVANCED_ACTION_DELETE_TO_LINE_END) {
@@ -10515,7 +10575,7 @@ static void compose_attach_drag_received_cb (GtkWidget          *widget,
                        gchar *utf8_filename = conv_filename_to_utf8((const gchar *)tmp->data);
                        compose_attach_append
                                (compose, (const gchar *)tmp->data,
-                                utf8_filename, NULL);
+                                utf8_filename, NULL, NULL);
                        g_free(utf8_filename);
                }
                if (list) compose_changed_cb(NULL, compose);
@@ -10541,7 +10601,7 @@ static void compose_attach_drag_received_cb (GtkWidget          *widget,
                                        TRUE, TRUE);
                        if (file) {
                                compose_attach_append(compose, (const gchar *)file, 
-                                       (const gchar *)file, "message/rfc822");
+                                       (const gchar *)file, "message/rfc822", NULL);
                                g_free(file);
                        }
                }
@@ -10642,16 +10702,6 @@ static void compose_insert_drag_received_cb (GtkWidget         *widget,
                gtk_drag_finish(drag_context, TRUE, FALSE, time);
                return;
        } else {
-#if GTK_CHECK_VERSION(2, 8, 0)
-               /* do nothing, handled by GTK */
-#else
-               gchar *tmpfile = get_tmp_file();
-               str_write_to_file((const gchar *)data->data, tmpfile);
-               compose_insert_file(compose, tmpfile);
-               claws_unlink(tmpfile);
-               g_free(tmpfile);
-               gtk_drag_finish(drag_context, TRUE, FALSE, time);
-#endif
                return;
        }
        gtk_drag_finish(drag_context, TRUE, FALSE, time);
@@ -10746,7 +10796,15 @@ static gboolean compose_headerentry_key_press_event_cb(GtkWidget *entry,
        return FALSE;
 }
 
-static gboolean compose_headerentry_changed_cb(GtkWidget *entry,
+static gboolean scroll_postpone(gpointer data)
+{
+       Compose *compose = (Compose *)data;
+       GTK_EVENTS_FLUSH();
+       compose_show_first_last_header(compose, FALSE);
+       return FALSE;
+}
+
+static void compose_headerentry_changed_cb(GtkWidget *entry,
                                    ComposeHeaderEntry *headerentry)
 {
        if (strlen(gtk_entry_get_text(GTK_ENTRY(entry))) != 0) {
@@ -10755,12 +10813,8 @@ static gboolean compose_headerentry_changed_cb(GtkWidget *entry,
                        (G_OBJECT(entry), G_SIGNAL_MATCH_DATA,
                         0, 0, NULL, NULL, headerentry);
                
-               /* Automatically scroll down */
-               GTK_EVENTS_FLUSH();
-               compose_show_first_last_header(headerentry->compose, FALSE);
-               
+               g_timeout_add(0, scroll_postpone, headerentry->compose);
        }
-       return FALSE;
 }
 
 static void compose_show_first_last_header(Compose *compose, gboolean show_first)
@@ -10892,7 +10946,7 @@ static void compose_check_all(GtkAction *action, gpointer data)
        if (!compose->gtkaspell)
                return;
                
-       if (GTK_WIDGET_HAS_FOCUS(compose->subject_entry))
+       if (gtkut_widget_has_focus(compose->subject_entry))
                claws_spell_entry_check_all(
                        CLAWS_SPELL_ENTRY(compose->subject_entry));             
        else
@@ -10917,7 +10971,7 @@ static void compose_check_backwards(GtkAction *action, gpointer data)
                return;
        }
 
-       if (GTK_WIDGET_HAS_FOCUS(compose->subject_entry))
+       if (gtkut_widget_has_focus(compose->subject_entry))
                claws_spell_entry_check_backwards(
                        CLAWS_SPELL_ENTRY(compose->subject_entry));
        else
@@ -10932,7 +10986,7 @@ static void compose_check_forwards_go(GtkAction *action, gpointer data)
                return;
        }
 
-       if (GTK_WIDGET_HAS_FOCUS(compose->subject_entry))
+       if (gtkut_widget_has_focus(compose->subject_entry))
                claws_spell_entry_check_forwards_go(
                        CLAWS_SPELL_ENTRY(compose->subject_entry));
        else
@@ -11125,6 +11179,51 @@ void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list,
        }
 }
 
+void compose_check_for_email_account(Compose *compose)
+{
+       PrefsAccount *ac = NULL, *curr = NULL;
+       GList *list;
+       
+       if (!compose)
+               return;
+
+       if (compose->account && compose->account->protocol == A_NNTP) {
+               ac = account_get_cur_account();
+               if (ac->protocol == A_NNTP) {
+                       list = account_get_list();
+                       
+                       for( ; list != NULL ; list = g_list_next(list)) {
+                               curr = (PrefsAccount *) list->data;
+                               if (curr->protocol != A_NNTP) {
+                                       ac = curr;
+                                       break;
+                               }
+                       }
+               }
+               combobox_select_by_data(GTK_COMBO_BOX(compose->account_combo),
+                                       ac->account_id); 
+       }
+}
+
+void compose_reply_to_address(MessageView *msgview, MsgInfo *msginfo, 
+                               const gchar *address)
+{
+       GSList *msginfo_list = NULL;
+       gchar *body =  messageview_get_selection(msgview);
+       Compose *compose;
+       
+       msginfo_list = g_slist_prepend(msginfo_list, msginfo);
+       
+       compose = compose_reply_mode(COMPOSE_REPLY_TO_ADDRESS, msginfo_list, body);
+       compose_check_for_email_account(compose);
+       compose_set_folder_prefs(compose, msginfo->folder, FALSE);
+       compose_entry_append(compose, address, COMPOSE_TO, PREF_NONE);
+       compose_reply_set_subject(compose, msginfo);
+
+       g_free(body);
+       hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
+}
+
 void compose_set_position(Compose *compose, gint pos)
 {
        GtkTextView *text = GTK_TEXT_VIEW(compose->text);