gettextise some forgotten strings
[claws.git] / src / compose.c
index 9c72d7f6e82f97d1309c72d226a23bb3c1fe650d..292f353f806f7dd5ca22299a67bca1b7cb6b5b04 100644 (file)
@@ -170,7 +170,8 @@ static GList *compose_list = NULL;
 Compose *compose_generic_new                   (PrefsAccount   *account,
                                                 const gchar    *to,
                                                 FolderItem     *item,
-                                                GPtrArray      *attach_files);
+                                                GPtrArray      *attach_files,
+                                                GList          *listAddress );
 
 static Compose *compose_create                 (PrefsAccount   *account,
                                                 ComposeMode     mode);
@@ -258,8 +259,7 @@ static void compose_convert_header          (gchar          *dest,
                                                 gchar          *src,
                                                 gint            header_len,
                                                 gboolean        addr_field);
-static void compose_generate_msgid             (Compose        *compose,
-                                                gchar          *buf,
+static void compose_generate_msgid             (gchar          *buf,
                                                 gint            len);
 
 static void compose_attach_info_free           (AttachInfo     *ainfo);
@@ -300,6 +300,9 @@ static void compose_create_header_entry     (Compose *compose);
 static void compose_add_header_entry   (Compose *compose, gchar *header, gchar *text);
 static void compose_update_priority_menu_item(Compose * compose);
 
+static void compose_add_field_list     ( Compose *compose,
+                                         GList *listAddress );
+
 /* callback functions */
 
 static gboolean compose_edit_size_alloc (GtkEditable   *widget,
@@ -482,6 +485,9 @@ void compose_headerentry_changed_cb    (GtkWidget          *entry,
 void compose_headerentry_key_press_event_cb(GtkWidget         *entry,
                                            GdkEventKey        *event,
                                            ComposeHeaderEntry *headerentry);
+static gboolean compose_headerentry_button_pressed (GtkWidget *entry, 
+                                                   GdkEventButton *event,
+                                                   gpointer data);
 
 static void compose_show_first_last_header (Compose *compose, gboolean show_first);
 
@@ -657,7 +663,8 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_Message/---"),           NULL, NULL, 0, "<Separator>"},
        {N_("/_Message/Si_gn"),         NULL, compose_toggle_sign_cb   , 0, "<ToggleItem>"},
        {N_("/_Message/_Encrypt"),      NULL, compose_toggle_encrypt_cb, 0, "<ToggleItem>"},
-       {N_("/_Message/Mode/MIME"),             NULL, compose_set_gnupg_mode_cb,   GNUPG_MODE_DETACH, "<RadioItem>"},   
+       {N_("/_Message/Mode"),          NULL, NULL,   0, "<Branch>"},
+       {N_("/_Message/Mode/MIME"),     NULL, compose_set_gnupg_mode_cb,   GNUPG_MODE_DETACH, "<RadioItem>"},   
        {N_("/_Message/Mode/Inline"),   NULL, compose_set_gnupg_mode_cb,   GNUPG_MODE_INLINE, "/Message/Mode/MIME"},    
 #endif /* USE_GPGME */
        {N_("/_Message/---"),           NULL,           NULL,   0, "<Separator>"},
@@ -687,21 +694,25 @@ static GtkTargetEntry compose_mime_types[] =
 Compose *compose_new(PrefsAccount *account, const gchar *mailto,
                     GPtrArray *attach_files)
 {
-       return compose_generic_new(account, mailto, NULL, attach_files);
+       return compose_generic_new(account, mailto, NULL, attach_files, NULL);
 }
 
 Compose *compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
 {
-       return compose_generic_new(account, NULL, item, NULL);
+       return compose_generic_new(account, NULL, item, NULL, NULL);
+}
+
+Compose *compose_new_with_list( PrefsAccount *account, GList *listAddress )
+{
+       return compose_generic_new( account, NULL, NULL, NULL, listAddress );
 }
 
 Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item,
-                            GPtrArray *attach_files)
+                            GPtrArray *attach_files, GList *listAddress )
 {
        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);
@@ -738,8 +749,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
                } 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;
+                       compose_entry_mark_default_to(compose, item->prefs->default_to);
                }
                if (item && item->ret_rcpt) {
                        menu_set_toggle(ifactory, "/Message/Request Return Receipt", TRUE);
@@ -754,6 +764,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                 */
                menu_set_sensitive(ifactory, "/Message/Request Return Receipt", FALSE); 
        }
+       compose_add_field_list( compose, listAddress );
 
        if (attach_files) {
                gint i;
@@ -777,9 +788,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
                g_free(folderidentifier);
        }
        
-       /* 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);
+       gtk_widget_grab_focus(compose->header_last->entry);
 
        if (prefs_common.auto_exteditor)
                compose_exec_ext_editor(compose);
@@ -1000,13 +1009,20 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        if (account->auto_sig)
                compose_insert_sig(compose, FALSE);
 
-       if (quote && prefs_common.linewrap_quote)
-               compose_wrap_line_all(compose);
+       /* Must thaw here, otherwise the GtkSTextEdit will become confused 
+        * when positioning cursor */
+       gtk_stext_thaw(text);
 
-       gtk_editable_set_position(GTK_EDITABLE(text), 0);
-       gtk_stext_set_point(text, 0);
+       gtk_editable_set_position
+               (GTK_EDITABLE(text), quote_fmt_get_cursor_pos());
+       gtk_stext_set_point(text, quote_fmt_get_cursor_pos());
+
+       if (quote && prefs_common.linewrap_quote) {
+               gtk_stext_freeze(text);
+               compose_wrap_line_all(compose);
+               gtk_stext_thaw(text);
+       }
 
-       gtk_stext_thaw(text);
        gtk_widget_grab_focus(compose->text);
 
        if (prefs_common.auto_exteditor)
@@ -1385,7 +1401,8 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
        gtk_widget_set_sensitive(compose->toolbar->attach_btn, FALSE);
        gtk_widget_set_sensitive(compose->toolbar->sig_btn, FALSE);
        gtk_widget_set_sensitive(compose->toolbar->exteditor_btn, FALSE);
-       gtk_widget_set_sensitive(compose->toolbar->linewrap_btn, FALSE);
+       gtk_widget_set_sensitive(compose->toolbar->linewrap_current_btn, FALSE);
+       gtk_widget_set_sensitive(compose->toolbar->linewrap_all_btn, FALSE);
 
         return compose;
 }
@@ -1451,16 +1468,32 @@ 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)
+void compose_entry_mark_default_to(Compose *compose, const gchar *mailto)
 {
-       GSList *header_list;
+       static GtkStyle *bold_style = NULL;
+       static GdkColor bold_color;
+       static GdkFont *bold_font = NULL;
+       GSList *h_list;
+       GtkEntry *entry;
                
-       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));
+       for (h_list = compose->header_list; h_list != NULL; h_list = h_list->next) {
+               entry = GTK_ENTRY(((ComposeHeaderEntry *)h_list->data)->entry);
+               if (gtk_entry_get_text(entry) && 
+                   !g_strcasecmp(gtk_entry_get_text(entry), mailto)) {
+                       gtk_widget_ensure_style(GTK_WIDGET(entry));
+                       if (!bold_style) {
+                               gtkut_convert_int_to_gdk_color
+                                       (prefs_common.color_new, &bold_color);
+                               bold_style = gtk_style_copy(gtk_widget_get_style
+                                       (GTK_WIDGET(entry)));
+                               if (!bold_font)
+                                       bold_font = gtkut_font_load
+                                               (prefs_common.boldfont);
+                               if (bold_font)
+                                       bold_style->font = bold_font;
+                               bold_style->fg[GTK_STATE_NORMAL] = bold_color;
+                       }
+                       gtk_widget_set_style(GTK_WIDGET(entry), bold_style);
                }
        }
 }
@@ -1494,12 +1527,20 @@ void compose_toolbar_cb(gint action, gpointer data)
        case A_EXTEDITOR:
                compose_ext_editor_cb(compose, 0, NULL);
                break;
-       case A_LINEWRAP:
+       case A_LINEWRAP_CURRENT:
                compose_wrap_line(compose);
                break;
+       case A_LINEWRAP_ALL:
+               compose_wrap_line_all(compose);
+               break;
        case A_ADDRBOOK:
                compose_address_cb(compose, 0, NULL);
                break;
+#ifdef USE_ASPELL
+       case A_CHECK_SPELLING:
+               compose_check_all(compose);
+               break;
+#endif
        default:
                break;
        }
@@ -1836,7 +1877,8 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
        }
 
        if (msginfo->subject && *msginfo->subject) {
-               gchar *buf, *buf2, *p;
+               gchar *buf, *buf2;
+               guchar *p;
 
                buf = p = g_strdup(msginfo->subject);
                p += subject_get_prefix_length(p);
@@ -2168,71 +2210,122 @@ static void compose_attach_append(Compose *compose, const gchar *file,
        gtk_clist_set_row_data(GTK_CLIST(compose->attach_clist), row, ainfo);
 }
 
-#define IS_FIRST_PART_TEXT(info) \
-       ((info->type == MIMETYPE_TEXT) || \
-        (info->type == MIMETYPE_MULTIPART && info->subtype && \
-         !strcasecmp(info->subtype, "alternative") && \
-         (info->node->children && \
-          (((MimeInfo *) info->node->children->data)->type == MIMETYPE_TEXT))))
+#ifdef USE_GPGME
+static void compose_use_signing(Compose *compose, gboolean use_signing)
+{
+       GtkItemFactory *ifactory;
+       GtkWidget *menuitem = NULL;
+
+       compose->use_signing = use_signing;
+       ifactory = gtk_item_factory_from_widget(compose->menubar);
+       menuitem = gtk_item_factory_get_item
+               (ifactory, "/Message/Sign");
+       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), 
+                                      use_signing);
+       compose_update_gnupg_mode_menu_item(compose);
+}
+#endif /* USE_GPGME */
+
+#define NEXT_PART_NOT_CHILD(info)  \
+{  \
+       node = info->node;  \
+       while (node->children)  \
+               node = g_node_last_child(node);  \
+       info = procmime_mimeinfo_next((MimeInfo *)node->data);  \
+}
 
 static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
 {
        MimeInfo *mimeinfo;
        MimeInfo *child;
-       gchar *infile;
+       MimeInfo *firsttext = NULL;
+       MimeInfo *encrypted = NULL;
+       GNode    *node;
        gchar *outfile;
+       const gchar *partname = NULL;
 
        mimeinfo = procmime_scan_message(msginfo);
        if (!mimeinfo) return;
 
-       /* skip first text (presumably message body) */
-       child = (MimeInfo *) mimeinfo->node->children->data;
-       if (!child || IS_FIRST_PART_TEXT(mimeinfo)) {
+       if (mimeinfo->node->children == NULL) {
                procmime_mimeinfo_free_all(mimeinfo);
                return;
        }
 
-       if (IS_FIRST_PART_TEXT(child))
-               child = (MimeInfo *) child->node->next;
-
-       infile = procmsg_get_message_file_path(msginfo);
-
+       /* find first content part */
+       child = (MimeInfo *) mimeinfo->node->children->data;
+       while (child && child->node->children && (child->type == MIMETYPE_MULTIPART))
+               child = (MimeInfo *)child->node->children->data;
+
+       if (child->type == MIMETYPE_TEXT) {
+               firsttext = child;
+               debug_print("First text part found\n");
+       } else if (compose->mode == COMPOSE_REEDIT &&
+                child->type == MIMETYPE_APPLICATION &&
+                !strcasecmp(child->subtype, "pgp-encrypted")) {
+               AlertValue val;
+               val = alertpanel(_("Encrypted message"),
+                                _("Cannot re-edit an encrypted message. \n"
+                                  "Discard encrypted part?"),
+                                _("Yes"), _("No"), NULL);
+               if (val == G_ALERTDEFAULT) 
+                       encrypted = (MimeInfo *)child->node->parent->data;
+       }
+     
+       child = (MimeInfo *) mimeinfo->node->children->data;
        while (child != NULL) {
-               if (child->node->children || child->type == MIMETYPE_MULTIPART) {
+               if (child == encrypted) {
+                       /* skip this part of tree */
+                       NEXT_PART_NOT_CHILD(child);
+                       continue;
+               }
+
+               if (child->type == MIMETYPE_MULTIPART) {
+                       /* get the actual content */
                        child = procmime_mimeinfo_next(child);
                        continue;
                }
-               if (child->node->parent && child->node->parent->parent
-               && (((MimeInfo *) child->node->parent->parent->data)->type == MIMETYPE_MULTIPART)
-               && !strcasecmp(((MimeInfo *) child->node->parent->parent->data)->subtype, "signed")
-               && child->type == MIMETYPE_TEXT) {
-                       /* this is the main text part of a signed message */
+                   
+               if (child == firsttext) {
+                       child = procmime_mimeinfo_next(child);
+                       continue;
+               }
+
+               if ((compose->mode == COMPOSE_REEDIT || 
+                    compose->mode == COMPOSE_FORWARD_INLINE ||
+                    compose->mode == COMPOSE_FORWARD )  &&
+                   (child->type == MIMETYPE_APPLICATION) && 
+                   !strcmp(child->subtype, "pgp-signature")) {
+#ifdef USE_GPGME
+                       if (compose->mode == COMPOSE_REEDIT) {
+                               compose->gnupg_mode  = GNUPG_MODE_DETACH;
+                               compose_use_signing(compose, TRUE);
+                       }
+#endif
                        child = procmime_mimeinfo_next(child);
                        continue;
                }
                outfile = procmime_get_tmp_file_name(child);
                if (procmime_get_part(outfile, child) < 0)
                        g_warning("Can't get the part of multipart message.");
-               else if (compose->mode != COMPOSE_REEDIT || 
-                   !((child->type == MIMETYPE_APPLICATION) && !strcmp(child->subtype, "pgp-signature"))) {
+               else {
                        gchar *content_type;
 
-                       content_type = g_strdup_printf("%s/%s", procmime_get_type_str(child->type), child->subtype);
-                       compose_attach_append
-                               (compose, outfile,
-                                child->filename ? child->filename : child->name,
-                                content_type);
+                       content_type = procmime_get_content_type_str(child->type, child->subtype);
+                       partname = procmime_mimeinfo_get_parameter(child, "name");
+                       if (partname == NULL)
+                               partname = "";
+                       compose_attach_append(compose, outfile, 
+                                             partname, content_type);
                        g_free(content_type);
                }
-
-               child = child->node->next != NULL ? (MimeInfo *) child->node->next->data : NULL;
+               g_free(outfile);
+               NEXT_PART_NOT_CHILD(child);
        }
-
-       g_free(infile);
        procmime_mimeinfo_free_all(mimeinfo);
 }
 
-#undef IS_FIRST_PART_TEXT
+#undef NEXT_PART_NOT_CHILD
 
 #define GET_CHAR(pos, buf, len)                                                     \
 {                                                                           \
@@ -2248,7 +2341,6 @@ static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
        ((len > 2 && conv_get_current_charset() == C_UTF_8) ? 2 : \
         (len == 2 && conv_get_current_charset() == C_UTF_8) ? 1 : len)
 
-#define INDENT_CHARS   ">|#"
 #define SPACE_CHARS    " \t"
 
 static void compose_wrap_line(Compose *compose)
@@ -2294,7 +2386,7 @@ static void compose_wrap_line(Compose *compose)
                        if (ch_len == 1 
                            && strchr(prefs_common.quote_chars, *cbuf))
                                quoted = 1;
-                       else if (ch_len != 1 || !isspace(*cbuf))
+                       else if (ch_len != 1 || !isspace(*(guchar *)cbuf))
                                quoted = 0;
 
                        line_end = 0;
@@ -2341,15 +2433,16 @@ static void compose_wrap_line(Compose *compose)
                        ch_len = 1;
                }
 
-               if (ch_len == 1 && isspace(*cbuf))
+               if (ch_len == 1 && isspace(*(guchar *)cbuf))
                        space = 1;
 
                if (ch_len == 1 && *cbuf == '\n') {
                        guint replace = 0;
-                       if (last_ch_len == 1 && !isspace(last_ch)) {
+                       if (last_ch_len == 1 && !isspace((guchar)last_ch)) {
                                if (cur_pos + 1 < p_end) {
                                        GET_CHAR(cur_pos + 1, cbuf, ch_len);
-                                       if (ch_len == 1 && !isspace(*cbuf))
+                                       if (ch_len == 1 &&
+                                           !isspace(*(guchar *)cbuf))
                                                replace = 1;
                                }
                        }
@@ -2380,7 +2473,7 @@ static void compose_wrap_line(Compose *compose)
                        gint tlen = ch_len;
 
                        GET_CHAR(line_pos - 1, cbuf, ch_len);
-                       if (ch_len == 1 && isspace(*cbuf)) {
+                       if (ch_len == 1 && isspace(*(guchar *)cbuf)) {
                                gtk_stext_set_point(text, line_pos);
                                gtk_stext_backward_delete(text, 1);
                                p_end--;
@@ -2476,7 +2569,7 @@ static guint get_indent_length(GtkSText *text, guint start_pos, guint text_len)
                        break;
                case WAIT_FOR_INDENT_CHAR_OR_SPACE:
                        if (is_indent == FALSE && is_space == FALSE &&
-                           !isupper(cbuf[0]))
+                           !isupper((guchar)cbuf[0]))
                                goto out;
                        if (is_space == TRUE) {
                                alnum_cnt = 0;
@@ -2490,7 +2583,7 @@ static guint get_indent_length(GtkSText *text, guint start_pos, guint text_len)
                        }
                        break;
                case WAIT_FOR_INDENT_CHAR:
-                       if (is_indent == FALSE && !isupper(cbuf[0]))
+                       if (is_indent == FALSE && !isupper((guchar)cbuf[0]))
                                goto out;
                        if (is_indent == TRUE) {
                                if (alnum_cnt > 0 
@@ -2667,7 +2760,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
 
                                /* insert space if it's alphanumeric */
                                if ((cur_pos != line_pos) &&
-                                   ((clen > 1) || isalnum(cb[0]))) {
+                                   ((clen > 1) || isalnum((guchar)cb[0]))) {
                                        gtk_stext_insert(text, NULL, NULL,
                                                        NULL, " ", 1);
                                        tlen++;
@@ -2708,7 +2801,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                }
 
                /* possible line break */
-               if (ch_len == 1 && isspace(*cbuf)) {
+               if (ch_len == 1 && isspace(*(guchar *)cbuf)) {
                        line_pos = cur_pos + 1;
                        line_len = cur_len + ch_len;
                }
@@ -2734,7 +2827,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                        GET_CHAR(line_pos - 1, cbuf, clen);
 
                        /* if next character is space delete it */
-                       if (clen == 1 && isspace(*cbuf)) {
+                       if (clen == 1 && isspace(*(guchar *)cbuf)) {
                                if (p_pos + i_len != line_pos ||
                                    !gtk_stext_is_uri_string
                                        (text, line_pos, tlen)) {
@@ -3184,7 +3277,8 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
 {
        gchar buf[BUFFSIZE];
        gchar *str;
-       gboolean first_address;
+       gboolean first_to_address;
+       gboolean first_cc_address;
        GSList *list;
        ComposeHeaderEntry *headerentry;
        gchar *headerentryname;
@@ -3196,7 +3290,8 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
        cc_hdr = prefs_common.trans_hdr ? _("Cc:") : "Cc:";
        to_hdr = prefs_common.trans_hdr ? _("To:") : "To:";
 
-       first_address = TRUE;
+       first_to_address = TRUE;
+       first_cc_address = TRUE;
        for (list = compose->header_list; list; list = list->next) {
                headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
@@ -3210,12 +3305,24 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
                                compose_convert_header
                                        (buf, sizeof(buf), str,
                                        strlen("Resent-To") + 2, TRUE);
-                               if (first_address) {
-                                       fprintf(fp, "Resent-To: ");
-                                       first_address = FALSE;
-                               } else {
-                                       fprintf(fp, ",");
+                               if (g_strcasecmp(headerentryname, to_hdr) == 0) {
+                                       if (first_to_address) {
+                                               fprintf(fp, "Resent-To: ");
+                                               first_to_address = FALSE;
+                                       } else {
+                                               fprintf(fp, ",");
+                                       }
                                }
+                               if (g_strcasecmp(headerentryname, cc_hdr) == 0) {
+                                       if (first_cc_address) {
+                                               fprintf(fp, "\n");
+                                               fprintf(fp, "Resent-Cc: ");
+                                               first_cc_address = FALSE;
+                                       } else {
+                                               fprintf(fp, ",");
+                                       }
+                               }
+                               
                                fprintf(fp, "%s", buf);
                        }
                }
@@ -3265,7 +3372,7 @@ static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
 
        /* Resent-Message-ID */
        if (compose->account->gen_msgid) {
-               compose_generate_msgid(compose, buf, sizeof(buf));
+               compose_generate_msgid(buf, sizeof(buf));
                fprintf(fp, "Resent-Message-Id: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
@@ -3302,7 +3409,7 @@ static gint compose_redirect_write_to_file(Compose *compose, const gchar *file)
                g_warning("can't change file mode\n");
        }
 
-       while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
+       while (procheader_get_one_field_asis(buf, sizeof(buf), fp) != -1) {
                /* should filter returnpath, delivered-to */
                if (g_strncasecmp(buf, "Return-Path:",
                                   strlen("Return-Path:")) == 0 ||
@@ -3458,7 +3565,6 @@ static gint compose_write_to_file(Compose *compose, const gchar *file,
 
        /* get all composed text */
        chars = gtk_editable_get_chars(GTK_EDITABLE(compose->text), 0, -1);
-       len = strlen(chars);
        if (is_ascii_str(chars)) {
                buf = chars;
                chars = NULL;
@@ -4149,17 +4255,15 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
        }
 
        /* From */
-       if (!IS_IN_CUSTOM_HEADER("From")) {
-               if (compose->account->name && *compose->account->name) {
-                       compose_convert_header
-                               (buf, sizeof(buf), compose->account->name,
-                                strlen("From: "), TRUE);
-                       QUOTE_IF_REQUIRED(name, buf);
-                       fprintf(fp, "From: %s <%s>\n",
-                               name, compose->account->address);
-               } else
-                       fprintf(fp, "From: %s\n", compose->account->address);
-       }
+       if (compose->account->name && *compose->account->name) {
+               compose_convert_header
+                       (buf, sizeof(buf), compose->account->name,
+                        strlen("From: "), TRUE);
+               QUOTE_IF_REQUIRED(name, buf);
+               fprintf(fp, "From: %s <%s>\n",
+                       name, compose->account->address);
+       } else
+               fprintf(fp, "From: %s\n", compose->account->address);
        
        /* To */
        compose_write_headers_from_headerlist(compose, fp, "To", ", ");
@@ -4222,7 +4326,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
 
        /* Message-ID */
        if (compose->account->gen_msgid) {
-               compose_generate_msgid(compose, buf, sizeof(buf));
+               compose_generate_msgid(buf, sizeof(buf));
                fprintf(fp, "Message-Id: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
@@ -4307,17 +4411,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
                     cur = cur->next) {
                        CustomHeader *chdr = (CustomHeader *)cur->data;
 
-                       if (strcasecmp(chdr->name, "Date")         != 0 &&
-                           strcasecmp(chdr->name, "From")         != 0 &&
-                           strcasecmp(chdr->name, "To")           != 0 &&
-                        /* strcasecmp(chdr->name, "Sender")       != 0 && */
-                           strcasecmp(chdr->name, "Message-Id")   != 0 &&
-                           strcasecmp(chdr->name, "In-Reply-To")  != 0 &&
-                           strcasecmp(chdr->name, "References")   != 0 &&
-                           strcasecmp(chdr->name, "Mime-Version") != 0 &&
-                           strcasecmp(chdr->name, "Content-Type") != 0 &&
-                           strcasecmp(chdr->name, "Content-Transfer-Encoding")
-                           != 0) {
+                       if (custom_header_is_allowed(chdr->name)) {
                                compose_convert_header
                                        (buf, sizeof(buf),
                                         chdr->value ? chdr->value : "",
@@ -4446,7 +4540,7 @@ static void compose_convert_header(gchar *dest, gint len, gchar *src,
        conv_encode_header(dest, len, src, header_len, addr_field);
 }
 
-static void compose_generate_msgid(Compose *compose, gchar *buf, gint len)
+static void compose_generate_msgid(gchar *buf, gint len)
 {
        struct tm *lt;
        time_t t;
@@ -4455,18 +4549,9 @@ static void compose_generate_msgid(Compose *compose, gchar *buf, gint len)
        t = time(NULL);
        lt = localtime(&t);
 
-       if (compose->account && compose->account->address &&
-           *compose->account->address) {
-               if (strchr(compose->account->address, '@'))
-                       addr = g_strdup(compose->account->address);
-               else
-                       addr = g_strconcat(compose->account->address, "@",
-                                          get_domain_name(), NULL);
-       } else
-               addr = g_strconcat(g_get_user_name(), "@", get_domain_name(),
-                                  NULL);
+       addr = g_strconcat("@", get_domain_name(), NULL);
 
-       g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x.%s",
+       g_snprintf(buf, len, "%04d%02d%02d%02d%02d%02d.%08x%s",
                   lt->tm_year + 1900, lt->tm_mon + 1,
                   lt->tm_mday, lt->tm_hour,
                   lt->tm_min, lt->tm_sec,
@@ -4534,6 +4619,9 @@ static void compose_create_header_entry(Compose *compose)
         gtk_signal_connect(GTK_OBJECT(entry), "key-press-event", GTK_SIGNAL_FUNC(compose_headerentry_key_press_event_cb), headerentry);
        gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(compose_headerentry_changed_cb), headerentry);
        gtk_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(text_activated), compose);
+       gtk_signal_connect(GTK_OBJECT(entry), "button-press-event", 
+                          GTK_SIGNAL_FUNC(compose_headerentry_button_pressed),
+                          NULL);
 
        address_completion_register_entry(GTK_ENTRY(entry));
 
@@ -4887,7 +4975,8 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        }
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL,
                                      &geometry, GDK_HINT_MAX_SIZE);
-
+       gtk_widget_set_uposition(window, prefs_common.compose_x, 
+               prefs_common.compose_y);
        gtk_signal_connect(GTK_OBJECT(window), "delete_event",
                           GTK_SIGNAL_FUNC(compose_delete_cb), compose);
        gtk_signal_connect(GTK_OBJECT(window), "destroy",
@@ -5101,9 +5190,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        }
 #endif
 
-       action_update_compose_menu(ifactory, compose);
-
-
        undostruct = undo_init(text);
        undo_set_change_state_func(undostruct, &compose_undo_state_changed,
                                   menubar);
@@ -5170,6 +5256,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        compose->exteditor_pid     = -1;
        compose->exteditor_readdes = -1;
        compose->exteditor_tag     = -1;
+       compose->draft_timeout_tag = -1;
 
 #if USE_ASPELL
        menu_set_sensitive(ifactory, "/Spelling", FALSE);
@@ -5207,14 +5294,11 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                        }
                }
        }
+        compose->gtkaspell = gtkaspell;
 #endif
 
        compose_select_account(compose, account, TRUE);
 
-#if USE_ASPELL
-        compose->gtkaspell      = gtkaspell;
-#endif
-
        if (account->set_autocc && account->auto_cc && mode != COMPOSE_REEDIT)
                compose_entry_append(compose, account->auto_cc, COMPOSE_CC);
 
@@ -5231,7 +5315,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), prefs_common.trans_hdr ? _("Newsgroups:") : "Newsgroups:");
 
        addressbook_set_target_compose(compose);
-       action_update_compose_menu(ifactory, compose);
        
        if (mode != COMPOSE_REDIRECT)
                compose_set_template_menu(compose);
@@ -5249,7 +5332,10 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        /* Priority */
        compose->priority = PRIORITY_NORMAL;
        compose_update_priority_menu_item(compose);
-       
+
+       /* Actions menu */
+       compose_update_actions_menu(compose);
+
 #if USE_GPGME
        activate_gnupg_mode(compose, account);
 #endif 
@@ -5403,6 +5489,14 @@ static void compose_set_template_menu(Compose *compose)
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(compose->tmpl_menu), menu);
 }
 
+void compose_update_actions_menu(Compose *compose)
+{
+       GtkItemFactory *ifactory;
+
+       ifactory = gtk_item_factory_from_widget(compose->menubar);
+       action_update_compose_menu(ifactory, "/Tools/Actions", compose);
+}
+
 void compose_reflect_prefs_all(void)
 {
        GList *cur;
@@ -6100,7 +6194,8 @@ static void compose_set_ext_editor_sensitive(Compose *compose,
        gtk_widget_set_sensitive(compose->toolbar->insert_btn,    sensitive);
        gtk_widget_set_sensitive(compose->toolbar->sig_btn,       sensitive);
        gtk_widget_set_sensitive(compose->toolbar->exteditor_btn, sensitive);
-       gtk_widget_set_sensitive(compose->toolbar->linewrap_btn,  sensitive);
+       gtk_widget_set_sensitive(compose->toolbar->linewrap_current_btn,  sensitive);
+       gtk_widget_set_sensitive(compose->toolbar->linewrap_all_btn,  sensitive);
 }
 
 /**
@@ -6116,14 +6211,11 @@ static void compose_undo_state_changed(UndoMain *undostruct, gint undo_state,
 
        g_return_if_fail(widget != NULL);
 
-       debug_print("Set_undo.  UNDO:%i  REDO:%i\n", undo_state, redo_state);
-
        ifactory = gtk_item_factory_from_widget(widget);
 
        switch (undo_state) {
        case UNDO_STATE_TRUE:
                if (!undostruct->undo_state) {
-                       debug_print ("Set_undo - Testpoint\n");
                        undostruct->undo_state = TRUE;
                        menu_set_sensitive(ifactory, "/Edit/Undo", TRUE);
                }
@@ -6216,6 +6308,7 @@ static void account_activated(GtkMenuItem *menuitem, gpointer data)
        Compose *compose = (Compose *)data;
 
        PrefsAccount *ac;
+       gchar *folderidentifier;
 
        ac = account_find_from_id(
                GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(menuitem))));
@@ -6223,6 +6316,21 @@ static void account_activated(GtkMenuItem *menuitem, gpointer data)
 
        if (ac != compose->account)
                compose_select_account(compose, ac, FALSE);
+
+       /* Set message save folder */
+       if (account_get_special_folder(compose->account, F_OUTBOX)) {
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compose->savemsg_checkbtn), prefs_common.savemsg);
+       }
+       gtk_signal_connect(GTK_OBJECT(compose->savemsg_checkbtn), "toggled",
+                          GTK_SIGNAL_FUNC(compose_savemsg_checkbtn_cb), compose);
+                          
+       gtk_editable_delete_text(GTK_EDITABLE(compose->savemsg_entry), 0, -1);
+       if (account_get_special_folder(compose->account, F_OUTBOX)) {
+               folderidentifier = folder_item_get_identifier(account_get_special_folder
+                                 (compose->account, F_OUTBOX));
+               gtk_entry_set_text(GTK_ENTRY(compose->savemsg_entry), folderidentifier);
+               g_free(folderidentifier);
+       }
 }
 
 static void attach_selected(GtkCList *clist, gint row, gint column,
@@ -6298,6 +6406,11 @@ static void compose_send_cb(gpointer data, guint action, GtkWidget *widget)
                               _("Yes"), _("No"), NULL) != G_ALERTDEFAULT)
                        return;
        
+       if (compose->draft_timeout_tag != -1) { /* CLAWS: disable draft timeout */
+               gtk_timeout_remove(compose->draft_timeout_tag);
+               compose->draft_timeout_tag = -1;
+       }
+
        compose_allow_user_actions (compose, FALSE);
        compose->sending = TRUE;
        val = compose_send(compose);
@@ -6470,7 +6583,13 @@ static void compose_insert_sig_cb(gpointer data, guint action,
 static gint compose_delete_cb(GtkWidget *widget, GdkEventAny *event,
                              gpointer data)
 {
+       gint x, y;
        Compose *compose = (Compose *)data;
+
+       gtkut_widget_get_uposition(widget, &x, &y);
+       prefs_common.compose_x = x;
+       prefs_common.compose_y = y;
+
        if (compose->sending)
                return TRUE;
        compose_close_cb(compose, 0, NULL);
@@ -6481,7 +6600,7 @@ static void compose_close_cb(gpointer data, guint action, GtkWidget *widget)
 {
        Compose *compose = (Compose *)data;
        AlertValue val;
-       
+
        if (compose->exteditor_tag != -1) {
                if (!compose_ext_editor_kill(compose))
                        return;
@@ -7045,6 +7164,15 @@ void compose_headerentry_changed_cb(GtkWidget *entry,
        }
 }
 
+static gboolean compose_headerentry_button_pressed
+       (GtkWidget *entry, GdkEventButton *event, gpointer data)
+{
+       /* if this is a lclick, grab the focus */
+       if (event->button == 1)
+               gtk_widget_grab_focus(entry);
+       return FALSE;
+}
+
 static void compose_show_first_last_header(Compose *compose, gboolean show_first)
 {
        GtkAdjustment *vadj;
@@ -7103,11 +7231,13 @@ static void text_inserted(GtkWidget *widget, const gchar *text,
 
        if (prefs_common.autosave && 
            gtk_stext_get_length(GTK_STEXT(widget)) % prefs_common.autosave_length == 0)
-               gtk_timeout_add(500, (GtkFunction) compose_defer_auto_save_draft, compose);
+               compose->draft_timeout_tag = gtk_timeout_add
+                       (500, (GtkFunction) compose_defer_auto_save_draft, compose);
 }
 
 static gint compose_defer_auto_save_draft(Compose *compose)
 {
+       compose->draft_timeout_tag = -1;
        compose_draft_cb((gpointer)compose, 2, NULL);
        return FALSE;
 }
@@ -7131,6 +7261,9 @@ static gboolean compose_send_control_enter(Compose *compose)
        if (!(kev->keyval == GDK_Return && (kev->state & GDK_CONTROL_MASK)))
                return FALSE;
 
+       if (compose->exteditor_tag != -1)
+               return FALSE;
+
        ifactory = gtk_item_factory_from_widget(compose->menubar);
        send_menu = gtk_item_factory_get_widget(ifactory, "/Message/Send");
        list = gtk_accel_group_entries_from_object(GTK_OBJECT(send_menu));
@@ -7186,3 +7319,23 @@ static void compose_check_forwards_go(Compose *compose)
 }
 #endif
 
+/**
+ * Add entry field for each address in list.
+ * \param compose     E-Mail composition object.
+ * \param listAddress List of (formatted) E-Mail addresses.
+ */
+static void compose_add_field_list( Compose *compose, GList *listAddress ) {
+       GList *node;
+       gchar *addr;
+       node = listAddress;
+       while( node ) {
+               addr = ( gchar * ) node->data;
+               compose_entry_append( compose, addr, COMPOSE_TO );
+               node = g_list_next( node );
+       }
+}
+
+/*
+ * End of Source.
+ */
+