2010-09-19 [pawel] 3.7.6cvs40
[claws.git] / src / compose.c
index bffd79cb82ece814cccb2643cc37ec39db199732..7e97e46a3498626bd8cdded5691eba3c9ea6b9da 100644 (file)
@@ -533,6 +533,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 +712,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 */
@@ -949,7 +952,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
        /* check if mailto defines a from */
        if (mailto && *mailto != '\0') {
-               scan_mailto_url(mailto, &mailto_from, NULL, NULL, NULL, NULL, NULL, NULL);
+               scan_mailto_url(mailto, &mailto_from, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
                /* mailto defines a from, check if we can get account prefs from it,
                   if not, the account prefs will be guessed using other ways, but we'll keep
                   the from anyway */
@@ -1029,24 +1032,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);
@@ -1059,6 +1046,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                                mfield = compose_entries_set(compose, mailto, COMPOSE_TO);
                } else if (item && FOLDER_CLASS(item->folder) == news_get_class()) {
                        compose_entry_append(compose, item->path, COMPOSE_NEWSGROUPS, PREF_FOLDER);
+                       mfield = TO_FIELD_PRESENT;
                }
                /*
                 * CLAWS: just don't allow return receipt request, even if the user
@@ -1115,6 +1103,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
                        g_free(subject);
                        g_free(tmp);
+                       mfield = SUBJECT_FIELD_PRESENT;
                }
 
                if ( body_format
@@ -1142,6 +1131,11 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                        quote_fmt_reset_vartable();
 
                        g_free(tmp);
+#ifdef USE_ENCHANT
+                       if (compose->gtkaspell && compose->gtkaspell->check_while_typing)
+                               gtkaspell_highlight_all(compose->gtkaspell);
+#endif
+                       mfield = BODY_FIELD_PRESENT;
                }
 
        }
@@ -1172,16 +1166,24 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        /* Place cursor according to provided input (mfield) */
        switch (mfield) { 
                case NO_FIELD_PRESENT:
-                       gtk_widget_grab_focus(compose->header_last->entry);
+                       if (compose->header_last)
+                               gtk_widget_grab_focus(compose->header_last->entry);
                        break;
                case TO_FIELD_PRESENT:
-                       buf = g_strdup("");
-                       gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf);     
+                       buf = gtk_editable_get_chars(GTK_EDITABLE(compose->subject_entry), 0, -1);
+                       if (buf) {
+                               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf);
+                               g_free(buf);
+                       }
                        gtk_widget_grab_focus(compose->subject_entry);
                        break;
                case SUBJECT_FIELD_PRESENT:
                        textview = GTK_TEXT_VIEW(compose->text);
+                       if (!textview)
+                               break;
                        textbuf = gtk_text_view_get_buffer(textview);
+                       if (!textbuf)
+                               break;
                        mark = gtk_text_buffer_get_insert(textbuf);
                        gtk_text_buffer_get_iter_at_mark(textbuf, &iter, mark);
                        gtk_text_buffer_insert(textbuf, &iter, "", -1);
@@ -1208,6 +1210,9 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
        compose->modified = FALSE;
        compose_set_title(compose);
+
+  hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
+
         return compose;
 }
 
@@ -1292,6 +1297,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;
@@ -1403,6 +1409,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;
        }
@@ -1414,7 +1423,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);
@@ -1526,7 +1535,9 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
                compose_destroy(compose);
                return NULL;
        }
-
+       if (!compose->ml_post)
+               cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options/ReplyMode/List", FALSE);
+       
        /* override from name according to folder properties */
        if (msginfo->folder && msginfo->folder->prefs &&
                msginfo->folder->prefs->reply_with_format &&
@@ -1601,6 +1612,10 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
                                          _("The body of the \"Reply\" template has an error at line %d."));
                compose_attach_from_list(compose, quote_fmt_get_attachments_list(), FALSE);
                quote_fmt_reset_vartable();
+#ifdef USE_ENCHANT
+               if (compose->gtkaspell && compose->gtkaspell->check_while_typing)
+                       gtkaspell_highlight_all(compose->gtkaspell);
+#endif
        }
 
        if (MSG_IS_ENCRYPTED(compose->replyinfo->flags)) {
@@ -1641,6 +1656,7 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
                return NULL;
        }
        END_TIMING();
+
        return compose;
 }
 
@@ -1793,6 +1809,10 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                compose_attach_parts(compose, msginfo);
 
                procmsg_msginfo_free(full_msginfo);
+#ifdef USE_ENCHANT
+               if (compose->gtkaspell && compose->gtkaspell->check_while_typing)
+                       gtkaspell_highlight_all(compose->gtkaspell);
+#endif
        }
 
        SIGNAL_BLOCK(textbuf);
@@ -1836,6 +1856,8 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                return NULL;
        }
 
+       hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
+
         return compose;
 }
 
@@ -1982,6 +2004,8 @@ static Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_
                return NULL;
        }
 
+       hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
+
        return compose;
 }
 
@@ -2088,7 +2112,8 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
        }
 
         if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
-           folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
+           folder_has_parent_of_type(msginfo->folder, F_DRAFT) ||
+           folder_has_parent_of_type(msginfo->folder, F_OUTBOX)) {
                gchar queueheader_buf[BUFFSIZE];
                gint id, param;
 
@@ -2225,7 +2250,8 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
        compose_extract_original_charset(compose);
 
         if (folder_has_parent_of_type(msginfo->folder, F_QUEUE) ||
-           folder_has_parent_of_type(msginfo->folder, F_DRAFT)) {
+           folder_has_parent_of_type(msginfo->folder, F_DRAFT) ||
+           folder_has_parent_of_type(msginfo->folder, F_OUTBOX)) {
                gchar queueheader_buf[BUFFSIZE];
 
                /* Set message save folder */
@@ -2310,6 +2336,8 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
        
        compose->sig_str = account_get_signature_str(compose->account);
        
+       hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
+
        return compose;
 }
 
@@ -2415,6 +2443,8 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo,
                return NULL;
        }
        
+       hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
+
        return compose;
 }
 
@@ -2447,6 +2477,9 @@ void compose_entry_append(Compose *compose, const gchar *address,
        case COMPOSE_FOLLOWUPTO:
                header = N_( "Followup-To:");
                break;
+       case COMPOSE_INREPLYTO:
+               header = N_( "In-Reply-To:");
+               break;
        case COMPOSE_TO:
        default:
                header = N_("To:");
@@ -2579,10 +2612,11 @@ static MailField compose_entries_set(Compose *compose, const gchar *mailto, Comp
        gchar *temp = NULL;
        gsize  len = 0;
        gchar **attach = NULL;
+       gchar *inreplyto = NULL;
        MailField mfield = NO_FIELD_PRESENT;
 
        /* get mailto parts but skip from */
-       scan_mailto_url(mailto, NULL, &to, &cc, &bcc, &subject, &body, &attach);
+       scan_mailto_url(mailto, NULL, &to, &cc, &bcc, &subject, &body, &attach, &inreplyto);
 
        if (to) {
                compose_entry_append(compose, to, to_type, PREF_MAILTO);
@@ -2656,12 +2690,16 @@ static MailField compose_entries_set(Compose *compose, const gchar *mailto, Comp
                        g_free(warn_files);
                }
        }
+       if (inreplyto)
+               compose_entry_append(compose, inreplyto, COMPOSE_INREPLYTO, PREF_MAILTO);
+
        g_free(to);
        g_free(cc);
        g_free(bcc);
        g_free(subject);
        g_free(body);
        g_strfreev(attach);
+       g_free(inreplyto);
        
        return mfield;
 }
@@ -2750,7 +2788,7 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
                        start = strstr(hentry[H_LIST_POST].body, "mailto:");
                        
                        scan_mailto_url(start ? start : hentry[H_LIST_POST].body,
-                                       NULL, &to, NULL, NULL, NULL, NULL, NULL);
+                                       NULL, &to, NULL, NULL, NULL, NULL, NULL, NULL);
 
                        if (to) {
                                g_free(compose->ml_post);
@@ -3018,6 +3056,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,
@@ -3027,6 +3111,7 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
        GSList *cur;
        gchar *from = NULL;
        gchar *replyto = NULL;
+       gchar *ac_email = NULL;
 
        gboolean reply_to_ml = FALSE;
        gboolean default_reply_to = FALSE;
@@ -3040,20 +3125,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,
@@ -3063,7 +3136,7 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                compose_entry_append(compose,
                                           compose->ml_post,
                                           COMPOSE_TO, PREF_ML);
-                               if (to_all && compose->replyto)
+                               if (compose->replyto)
                                        compose_entry_append(compose,
                                                compose->replyto,
                                                COMPOSE_CC, PREF_ML);
@@ -3143,7 +3216,9 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                 compose->followup_to ? compose->followup_to :
                                 compose->newsgroups ? compose->newsgroups : "",
                                 COMPOSE_NEWSGROUPS, PREF_NONE);
-               } 
+               } else if (reply_to_ml)
+                       compose_entry_append(compose,
+                                  compose->ml_post, COMPOSE_TO, PREF_ML); 
                else 
                        compose_entry_append
                                (compose,
@@ -3151,25 +3226,10 @@ 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;
+       if (!to_all) return;
 
        if (compose->replyto) {
                Xstrdup_a(replyto, compose->replyto, return);
@@ -3189,13 +3249,27 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
        cc_list = address_list_append_with_comments(cc_list, msginfo->to);
        cc_list = address_list_append_with_comments(cc_list, compose->cc);
 
+       ac_email = g_utf8_strdown(compose->account->address, -1);
+
        if (cc_list) {
-               for (cur = cc_list; cur != NULL; cur = cur->next)
-                       compose_entry_append(compose, (gchar *)cur->data,
-                                            COMPOSE_CC, PREF_NONE);
+               for (cur = cc_list; cur != NULL; cur = cur->next) {
+                       gchar *addr = g_utf8_strdown(cur->data, -1);
+                       extract_address(addr);
+               
+                       if (strcmp(ac_email, addr))
+                               compose_entry_append(compose, (gchar *)cur->data,
+                                                    COMPOSE_CC, PREF_NONE);
+                       else
+                               debug_print("Cc address same as compose account's, ignoring\n");
+
+                       g_free(addr);
+               }
+               
                slist_free_strings(cc_list);
                g_slist_free(cc_list);
        }
+       
+       g_free(ac_email);
 }
 
 #define SET_ENTRY(entry, str) \
@@ -4597,7 +4671,6 @@ static void compose_select_account(Compose *compose, PrefsAccount *account,
        cm_return_if_fail(account != NULL);
 
        compose->account = account;
-
        if (account->name && *account->name) {
                gchar *buf;
                QUOTE_IF_REQUIRED_NORMAL(buf, account->name, return);
@@ -6057,7 +6130,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);
@@ -6435,13 +6513,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"));
@@ -6506,11 +6580,21 @@ 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;
+       
+       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);
        
-       if (g_hash_table_lookup(compose->email_hashtable, email) != NULL) {
+       if (replyto_hdr == FALSE &&
+           g_hash_table_lookup(compose->email_hashtable, email) != NULL)
+       {
                debug_print("Ignoring duplicate address - %s %s, pref_type: %d\n",
                                header, text, (gint) pref_type);
                g_free(email);
@@ -6518,12 +6602,20 @@ static void compose_add_header_entry(Compose *compose, const gchar *header,
                return;
        }
        
-       combobox_select_by_text(GTK_COMBO_BOX(last_header->combo), header);
+       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
+               combobox_select_by_text(GTK_COMBO_BOX(last_header->combo), header);
        gtk_entry_set_text(GTK_ENTRY(last_header->entry), text);
        last_header->type = pref_type;
 
-       g_hash_table_insert(compose->email_hashtable, email,
-                               GUINT_TO_POINTER(1));
+       if (replyto_hdr == FALSE)
+               g_hash_table_insert(compose->email_hashtable, email,
+                                   GUINT_TO_POINTER(1));
+       else
+               g_free(email);
+       
        g_free(tmp);
 }
 
@@ -6882,7 +6974,8 @@ static void compose_dict_changed(void *data)
 {
        Compose *compose = (Compose *) data;
 
-       if(compose->gtkaspell->recheck_when_changing_dict == FALSE)
+       if(compose->gtkaspell && 
+                  compose->gtkaspell->recheck_when_changing_dict == FALSE)
                return;
 
        gtkaspell_highlight_all(compose->gtkaspell);
@@ -7171,6 +7264,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)
@@ -7308,6 +7402,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);
@@ -7495,7 +7593,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
@@ -7636,6 +7734,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;
@@ -7837,6 +7936,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;
@@ -8079,6 +8179,11 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
        compose_attach_from_list(compose, quote_fmt_get_attachments_list(), FALSE);
        quote_fmt_reset_vartable();
        compose_changed_cb(NULL, compose);
+
+#ifdef USE_ENCHANT
+       if (compose->gtkaspell && compose->gtkaspell->check_while_typing)
+               gtkaspell_highlight_all(compose->gtkaspell);
+#endif
 }
 
 static void compose_template_apply_fields(Compose *compose, Template *tmpl)
@@ -8213,6 +8318,8 @@ static void compose_destroy(Compose *compose)
        slist_free_strings(compose->header_list);
        g_slist_free(compose->header_list);
 
+       compose->header_list = compose->newsgroup_list = compose->to_list = NULL;
+
        g_hash_table_destroy(compose->email_hashtable);
 
        procmsg_msginfo_free(compose->targetinfo);
@@ -8989,7 +9096,7 @@ static gboolean compose_edit_size_alloc(GtkEditable *widget,
 }
 
 typedef struct {
-       ComposeEntryType        header;
+       gchar                   *header;
        gchar                   *entry;
        ComposePrefType         type;
        gboolean                entry_marked;
@@ -9030,8 +9137,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;
@@ -9072,12 +9179,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);
                
@@ -9172,7 +9281,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 "
@@ -9541,6 +9650,7 @@ static void compose_insert_file_cb(GtkAction *action, gpointer data)
 {
        Compose *compose = (Compose *)data;
        GList *file_list;
+       gint files_inserted = 0;
 
        file_list = filesel_select_multiple_files_open(_("Select file"));
 
@@ -9561,7 +9671,8 @@ static void compose_insert_file_cb(GtkAction *action, gpointer data)
                                alertpanel_error(_("File '%s' contained invalid characters\n"
                                                        "for the current encoding, insertion may be incorrect."),
                                                        shortfile);
-                       }
+                       } else if (res == COMPOSE_INSERT_SUCCESS)
+                               files_inserted++;
 
                        g_free(shortfile);
                        g_free(filedup);
@@ -9569,6 +9680,12 @@ static void compose_insert_file_cb(GtkAction *action, gpointer data)
                }
                g_list_free(file_list);
        }
+
+#ifdef USE_ENCHANT     
+       if (files_inserted > 0 && compose->gtkaspell && 
+                   compose->gtkaspell->check_while_typing)
+               gtkaspell_highlight_all(compose->gtkaspell);
+#endif
 }
 
 static void compose_insert_sig_cb(GtkAction *action, gpointer data)
@@ -9818,7 +9935,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);
@@ -9829,7 +9946,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);
@@ -9842,11 +9959,18 @@ 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 (gtkut_widget_has_focus(compose->text) &&
+           compose->gtkaspell && 
+            compose->gtkaspell->check_while_typing)
+               gtkaspell_highlight_all(compose->gtkaspell);
+#endif
 }
 
 static void compose_paste_as_quote_cb(GtkAction *action, gpointer data)
@@ -9855,7 +9979,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
@@ -9884,12 +10008,19 @@ 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,
                        GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
+
+#ifdef USE_ENCHANT
+       if (gtkut_widget_has_focus(compose->text) &&
+           compose->gtkaspell && 
+            compose->gtkaspell->check_while_typing)
+               gtkaspell_highlight_all(compose->gtkaspell);
+#endif
 }
 
 static void compose_paste_wrap_cb(GtkAction *action, gpointer data)
@@ -9900,12 +10031,19 @@ 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,
                        GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
+
+#ifdef USE_ENCHANT
+       if (gtkut_widget_has_focus(compose->text) &&
+           compose->gtkaspell &&
+            compose->gtkaspell->check_while_typing)
+               gtkaspell_highlight_all(compose->gtkaspell);
+#endif
 }
 
 static void compose_allsel_cb(GtkAction *action, gpointer data)
@@ -9913,7 +10051,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);
@@ -10217,7 +10355,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) {
@@ -10534,16 +10672,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);
@@ -10784,7 +10912,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
@@ -10809,7 +10937,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
@@ -10824,7 +10952,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
@@ -10979,6 +11107,7 @@ static void compose_reply_from_messageview_real(MessageView *msgview, GSList *ms
        }
        g_free(s_system);
        g_free(body);
+       hooks_invoke(COMPOSE_CREATED_HOOKLIST, compose);
 }
 
 void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list, 
@@ -11016,6 +11145,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);