fixed one more umlaut in german translation
[claws.git] / src / compose.c
index a28f66adbbf6c4c579d84789f2d44ed6f706bb3e..50ad6e69783aab48cde8ca9734b73b4fdccbd2dd 100644 (file)
 #include "addr_compl.h"
 #include "quote_fmt.h"
 #include "template.h"
+#include "undo.h"
 
 #if USE_GPGME
 #  include "rfc2015.h"
@@ -123,6 +124,14 @@ static GdkColor quote_color = {0, 0, 0, 0xbfff};
 
 static GList *compose_list = NULL;
 
+static void compose_set_undo                   (UndoMain       *undostruct, 
+                                                 gint            undo_state, 
+                                                gint            redo_state, 
+                                                GtkWidget      *changewidget);
+Compose *compose_generic_new                   (PrefsAccount   *account,
+                                                const gchar    *to,
+                                                FolderItem     *item);
+
 static Compose *compose_create                 (PrefsAccount   *account,
                                                 ComposeMode     mode);
 static void compose_toolbar_create             (Compose        *compose,
@@ -130,8 +139,12 @@ static void compose_toolbar_create         (Compose        *compose,
 static GtkWidget *compose_account_option_menu_create
                                                (Compose        *compose);
 static void compose_set_template_menu          (Compose        *compose);
+static void compose_template_apply             (Compose        *compose,
+                                                Template       *tmpl);
 static void compose_destroy                    (Compose        *compose);
 
+static void compose_entries_set                        (Compose        *compose,
+                                                const gchar    *mailto);
 static gint compose_parse_header               (Compose        *compose,
                                                 MsgInfo        *msginfo);
 static gchar *compose_parse_references         (const gchar    *ref,
@@ -250,8 +263,9 @@ static void toolbar_linewrap_cb             (GtkWidget      *widget,
 static void toolbar_address_cb         (GtkWidget      *widget,
                                         gpointer        data);
 
+static void select_account             (Compose        *compose,
+                                        PrefsAccount   *ac);
 
-static void select_account(Compose * compose, PrefsAccount * ac);
 static void account_activated          (GtkMenuItem    *menuitem,
                                         gpointer        data);
 
@@ -305,6 +319,8 @@ static gint compose_delete_cb               (GtkWidget      *widget,
 static void compose_destroy_cb         (GtkWidget      *widget,
                                         Compose        *compose);
 
+static void compose_undo_cb            (Compose *compose);
+static void compose_redo_cb            (Compose *compose);
 static void compose_cut_cb             (Compose        *compose);
 static void compose_copy_cb            (Compose        *compose);
 static void compose_paste_cb           (Compose        *compose);
@@ -324,6 +340,7 @@ static void compose_key_press_cb    (GtkWidget      *widget,
                                         Compose        *compose);
 #endif
 
+#if 0
 static void compose_toggle_to_cb       (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
@@ -342,6 +359,7 @@ static void compose_toggle_followupto_cb(gpointer    data,
 static void compose_toggle_attach_cb   (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
+#endif
 static void compose_toggle_ruler_cb    (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
@@ -373,6 +391,7 @@ static void compose_insert_drag_received_cb (GtkWidget              *widget,
                                             guint               time,
                                             gpointer            user_data);
 
+#if 0
 static void to_activated               (GtkWidget      *widget,
                                         Compose        *compose);
 static void newsgroups_activated       (GtkWidget      *widget,
@@ -387,23 +406,21 @@ static void replyto_activated             (GtkWidget      *widget,
                                         Compose        *compose);
 static void followupto_activated       (GtkWidget      *widget,
                                         Compose        *compose);
-static void compose_attach_parts(Compose * compose,
-                                MsgInfo * msginfo);
+#endif
+
+static void compose_attach_parts       (Compose        *compose,
+                                        MsgInfo        *msginfo);
 
 static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
                                  gboolean to_all,
                                  gboolean ignore_replyto,
                                  gboolean followup_and_reply_to);
 
-void compose_headerentry_changed_cb    (GtkWidget *entry,
-                                        compose_headerentry *headerentry);
-void compose_headerentry_key_press_event_cb    (GtkWidget *entry,
-                                                GdkEventKey *event,
-                                                compose_headerentry *headerentry);
-
-Compose * compose_generic_new (PrefsAccount    *account,
-                              const gchar      *to,
-                              FolderItem       *item);
+void compose_headerentry_changed_cb       (GtkWidget          *entry,
+                                           ComposeHeaderEntry *headerentry);
+void compose_headerentry_key_press_event_cb(GtkWidget         *entry,
+                                           GdkEventKey        *event,
+                                           ComposeHeaderEntry *headerentry);
 
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
@@ -423,8 +440,8 @@ static GtkItemFactoryEntry compose_entries[] =
        {N_("/_File/_Close"),                   "<alt>W", compose_close_cb, 0, NULL},
 
        {N_("/_Edit"),             NULL, NULL, 0, "<Branch>"},
-       {N_("/_Edit/_Undo"),       "<control>Z", NULL, 0, NULL},
-       {N_("/_Edit/_Redo"),       "<control>Y", NULL, 0, NULL},
+       {N_("/_Edit/_Undo"),       "<control>Z", compose_undo_cb, 0, NULL},
+       {N_("/_Edit/_Redo"),       "<control>Y", compose_redo_cb, 0, NULL},
        {N_("/_Edit/---"),         NULL, NULL, 0, "<Separator>"},
        {N_("/_Edit/Cu_t"),        "<control>X", compose_cut_cb,    0, NULL},
        {N_("/_Edit/_Copy"),       "<control>C", compose_copy_cb,   0, NULL},
@@ -475,15 +492,15 @@ static GtkTargetEntry compose_mime_types[] =
        {"text/uri-list", 0, 0}
 };
 
-Compose * compose_new(PrefsAccount *account)
+Compose *compose_new(PrefsAccount *account)
 {
        return compose_generic_new(account, NULL, NULL);
 }
 
-Compose * compose_bounce(PrefsAccount *account, MsgInfo *msginfo)
+Compose *compose_bounce(PrefsAccount *account, MsgInfo *msginfo)
 {
-       Compose * c;
-       gchar * filename;
+       Compose *c;
+       gchar *filename;
        GtkItemFactory *ifactory;
        
        c = compose_generic_new(account, NULL, NULL);
@@ -532,97 +549,17 @@ Compose * compose_bounce(PrefsAccount *account, MsgInfo *msginfo)
        return c;
 }
 
-Compose * compose_new_with_recipient(PrefsAccount *account, const gchar *to)
+Compose *compose_new_with_recipient(PrefsAccount *account, const gchar *mailto)
 {
-       return compose_generic_new(account, to, NULL);
+       return compose_generic_new(account, mailto, NULL);
 }
 
-Compose * compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
+Compose *compose_new_with_folderitem(PrefsAccount *account, FolderItem *item)
 {
        return compose_generic_new(account, NULL, item);
 }
 
-static void set_compose_entries(Compose * compose, const gchar * mailto)
-{
-       gchar * subject = NULL;
-       gchar * to = NULL;
-       gchar * cc = NULL;
-       gchar * bcc = NULL;
-       gchar * body = NULL;
-       gchar * p;
-       gchar * tmp_mailto;
-       gchar * cur;
-       
-       Xstrdup_a(tmp_mailto, mailto, return);
-
-       cur = tmp_mailto;
-
-       p = strchr(cur, '?');
-       if (p != NULL) {
-               * p = 0;
-               cur = p + 1;
-       }
-       to = tmp_mailto;
-
-       while (p) {
-               char *field, *value;
-               
-               field = cur;
-
-               p = strchr(cur, '=');
-               if (p == NULL)
-                       break;
-               * p = 0;
-               cur = p + 1;
-
-               value = cur;
-
-               p = strchr(cur, '&');
-               if (p != NULL) {
-                       * p = 0;
-                       cur = p + 1;
-               }
-
-               if (value) {
-                       if (g_strcasecmp(field, "subject")==0) {
-                               Xstrdup_a(subject, value, );
-                               if (subject != NULL)
-                                       decode_uri(subject, value);
-                       }
-                       else if (g_strcasecmp(field, "cc")==0)
-                               cc = value;
-                       else if (g_strcasecmp(field, "bcc")==0)
-                               bcc = value;
-                       else if (g_strcasecmp(field, "body")==0) {
-                               Xstrdup_a(body, value, );
-                               if (body != NULL)
-                                       decode_uri(body, value);
-                       }
-               }
-       }                       
-
-       if (to) {
-               compose_entry_append(compose, to, COMPOSE_TO);
-               /*
-               gtk_widget_grab_focus(compose->text);
-               */
-       }
-
-       if (subject)
-               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), subject);
-       if (cc)
-               compose_entry_append(compose, cc, COMPOSE_CC);
-       if (bcc)
-               compose_entry_append(compose, bcc, COMPOSE_BCC);
-       if (body) {
-               gtk_stext_insert(GTK_STEXT(compose->text),
-                                NULL, NULL, NULL, body, -1);
-               gtk_stext_insert(GTK_STEXT(compose->text),
-                                NULL, NULL, NULL, "\n", 1);
-       }
-}      
-
-Compose * compose_generic_new(PrefsAccount *account, const gchar *to, FolderItem *item)
+Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderItem *item)
 {
        Compose *compose;
 
@@ -641,8 +578,8 @@ Compose * compose_generic_new(PrefsAccount *account, const gchar *to, FolderItem
        gtk_stext_set_point(GTK_STEXT(compose->text), 0);
 
        if (account->protocol != A_NNTP) {
-               if (to) {
-                       set_compose_entries(compose, to);
+               if (mailto) {
+                       compose_entries_set(compose, mailto);
 
                } else if(item && item->prefs->enable_default_to) {
                        compose_entry_append(compose, item->prefs->default_to, COMPOSE_TO);
@@ -654,8 +591,8 @@ Compose * compose_generic_new(PrefsAccount *account, const gchar *to, FolderItem
                        menu_set_toggle(ifactory, "/Message/Request Return Receipt", TRUE);
                }
        } else {
-               if (to) {
-                       compose_entry_append(compose, to, COMPOSE_NEWSGROUPS);
+               if (mailto) {
+                       compose_entry_append(compose, mailto, COMPOSE_NEWSGROUPS);
                }
        }
        gtk_widget_grab_focus(compose->subject_entry);
@@ -675,7 +612,7 @@ msginfo->folder->folder->change_flags(msginfo->folder->folder, \
 }
 
 /*
-Compose * compose_new_followup_and_replyto(PrefsAccount *account,
+Compose *compose_new_followup_and_replyto(PrefsAccount *account,
                                           const gchar *followupto, gchar * to)
 {
        Compose *compose;
@@ -812,12 +749,12 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
 
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
-       gtk_editable_set_position(GTK_EDITABLE(text), 0);
-       gtk_stext_set_point(text, 0);
 
-       if (quote && prefs_common.linewrap_quote) {
+       if (quote && prefs_common.linewrap_quote)
                compose_wrap_line_all(compose);
-       }
+
+       gtk_editable_set_position(GTK_EDITABLE(text), 0);
+       gtk_stext_set_point(text, 0);
 
        gtk_stext_thaw(text);
        gtk_widget_grab_focus(compose->text);
@@ -838,20 +775,20 @@ static gchar *procmime_get_file_name(MimeInfo *mimeinfo)
                : mimeinfo->name ? mimeinfo->name : NULL;
 
        if (MIME_TEXT_HTML == mimeinfo->mime_type && base == NULL){
-               filename = g_strdup_printf("%s%smimetmp%i.html",
+               filename = g_strdup_printf("%s%smimetmp.%08x.html",
                                           get_mime_tmp_dir(),
                                           G_DIR_SEPARATOR_S,
-                                          mimeinfo);
+                                          (gint)mimeinfo);
                return filename;
        }
        else {
                base = base ? base : "";
                base = g_basename(base);
                if (*base == '\0') {
-                       filename = g_strdup_printf("%s%smimetmp%i",
+                       filename = g_strdup_printf("%s%smimetmp.%08x",
                                                   get_mime_tmp_dir(),
                                                   G_DIR_SEPARATOR_S,
-                                                  mimeinfo);
+                                                  (gint)mimeinfo);
                        return filename;
                }
        }
@@ -862,11 +799,11 @@ static gchar *procmime_get_file_name(MimeInfo *mimeinfo)
        return filename;
 }
 
-static gchar * mime_extract_file(gchar * source, MimeInfo *partinfo)
+static gchar *mime_extract_file(gchar *source, MimeInfo *partinfo)
 {
        gchar *filename;
 
-       if (!partinfo) return;
+       if (!partinfo) return NULL;
 
        filename = procmime_get_file_name(partinfo);
 
@@ -877,10 +814,8 @@ static gchar * mime_extract_file(gchar * source, MimeInfo *partinfo)
        return filename;
 }
 
-static void compose_attach_parts(Compose * compose,
-                                MsgInfo * msginfo)
+static void compose_attach_parts(Compose *compose, MsgInfo *msginfo)
 {
-
        FILE *fp;
        gchar *file;
        MimeInfo *mimeinfo;
@@ -891,8 +826,8 @@ static void compose_attach_parts(Compose * compose,
        gchar buf[BUFFSIZE];
        glong fpos, prev_fpos;
        gint npart;
-       gchar * source;
-       gchar * filename;
+       gchar *source;
+       gchar *filename;
 
        g_return_if_fail(msginfo != NULL);
        
@@ -1049,7 +984,7 @@ if (msginfo->var && *msginfo->var) { \
        gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1); \
 }
 
-Compose *compose_forward(PrefsAccount * account, MsgInfo *msginfo,
+Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
                         gboolean as_attach)
 {
        Compose *compose;
@@ -1062,7 +997,7 @@ Compose *compose_forward(PrefsAccount * account, MsgInfo *msginfo,
        account = msginfo->folder->folder->account;
         if (!account && msginfo->to && prefs_common.forward_account_autosel) {
                gchar *to;
-               Xstrdup_a(to, msginfo->to, return);
+               Xstrdup_a(to, msginfo->to, return NULL);
                extract_address(to);
                account = account_find_from_address(to);
        }
@@ -1126,6 +1061,10 @@ Compose *compose_forward(PrefsAccount * account, MsgInfo *msginfo,
 
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
+
+       if (prefs_common.linewrap_quote)
+               compose_wrap_line_all(compose);
+
        gtk_editable_set_position(GTK_EDITABLE(compose->text), 0);
        gtk_stext_set_point(GTK_STEXT(compose->text), 0);
 
@@ -1146,8 +1085,7 @@ Compose *compose_forward(PrefsAccount * account, MsgInfo *msginfo,
 
 #undef INSERT_FW_HEADER
 
-Compose * compose_forward_multiple(PrefsAccount * account, 
-                         GSList *msginfo_list) 
+Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_list)
 {
        Compose *compose;
        GtkSText *text;
@@ -1193,6 +1131,10 @@ Compose * compose_forward_multiple(PrefsAccount * account,
 
        if (prefs_common.auto_sig)
                compose_insert_sig(compose);
+
+       if (prefs_common.linewrap_quote)
+               compose_wrap_line_all(compose);
+
        gtk_editable_set_position(GTK_EDITABLE(compose->text), 0);
        gtk_stext_set_point(GTK_STEXT(compose->text), 0);
 
@@ -1318,6 +1260,75 @@ void compose_entry_append(Compose *compose, const gchar *address,
        compose_add_header_entry(compose, header, (gchar *)address);
 }
 
+static void compose_entries_set(Compose *compose, const gchar *mailto)
+{
+       gchar *subject = NULL;
+       gchar *to = NULL;
+       gchar *cc = NULL;
+       gchar *bcc = NULL;
+       gchar *body = NULL;
+       gchar *p;
+       gchar *tmp_mailto;
+
+       Xstrdup_a(tmp_mailto, mailto, return);
+
+       to = tmp_mailto;
+
+       p = strchr(tmp_mailto, '?');
+       if (p) {
+               *p = '\0';
+               p++;
+       }
+
+       while (p) {
+               gchar *field, *value;
+
+               field = p;
+
+               p = strchr(p, '=');
+               if (!p) break;
+               *p = '\0';
+               p++;
+
+               value = p;
+
+               p = strchr(p, '&');
+               if (p) {
+                       *p = '\0';
+                       p++;
+               }
+
+               if (*value == '\0') continue;
+
+               if (!g_strcasecmp(field, "subject")) {
+                       Xalloca(subject, strlen(value) + 1, return);
+                       decode_uri(subject, value);
+               } else if (!g_strcasecmp(field, "cc")) {
+                       cc = value;
+               } else if (!g_strcasecmp(field, "bcc")) {
+                       bcc = value;
+               } else if (!g_strcasecmp(field, "body")) {
+                       Xalloca(body, strlen(value) + 1, return);
+                       decode_uri(body, value);
+               }
+       }
+
+       if (to)
+               compose_entry_append(compose, to, COMPOSE_TO);
+       if (subject)
+               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), subject);
+       if (cc)
+               compose_entry_append(compose, cc, COMPOSE_CC);
+       if (bcc)
+               compose_entry_append(compose, bcc, COMPOSE_BCC);
+       if (body) {
+               gtk_stext_insert(GTK_STEXT(compose->text),
+                               NULL, NULL, NULL, body, -1);
+               gtk_stext_insert(GTK_STEXT(compose->text),
+                               NULL, NULL, NULL, "\n", 1);
+       }
+}
+
 static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
 {
        static HeaderEntry hentry[] = {{"Reply-To:",       NULL, TRUE},
@@ -1362,7 +1373,7 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
        }
        if (hentry[H_X_MAILING_LIST].body != NULL) {
                /* this is good enough to parse debian-devel */
-               char * buf = g_malloc(strlen(hentry[H_X_MAILING_LIST].body) + 1);
+               gchar *buf = g_malloc(strlen(hentry[H_X_MAILING_LIST].body) + 1);
                g_return_val_if_fail(buf != NULL, -1 );
                if (1 == sscanf(hentry[H_X_MAILING_LIST].body, "<%[^>]>", buf))
                        compose->mailinglist = g_strdup(buf);
@@ -1372,7 +1383,7 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
        }
        if (hentry[H_X_BEENTHERE].body != NULL) {
                /* this is good enough to parse the sylpheed-claws lists */
-               char * buf = g_malloc(strlen(hentry[H_X_BEENTHERE].body) + 1);
+               gchar *buf = g_malloc(strlen(hentry[H_X_BEENTHERE].body) + 1);
                g_return_val_if_fail(buf != NULL, -1 );
                if (1 == sscanf(hentry[H_X_BEENTHERE].body, "%[^>]", buf))
                        compose->mailinglist = g_strdup(buf);
@@ -1550,24 +1561,19 @@ static void compose_reply_set_entry(Compose *compose, MsgInfo *msginfo,
                                     ? compose->replyto
                                     : msginfo->from ? msginfo->from : ""),
                                     COMPOSE_TO);
-       if (compose->account->protocol == A_NNTP)
+       if (compose->account->protocol == A_NNTP) {
                if (ignore_replyto)
-                       compose_entry_append(compose,
-                                            msginfo->from ? msginfo->from : "",
-                                            COMPOSE_TO);
+                       compose_entry_append
+                               (compose, msginfo->from ? msginfo->from : "",
+                                COMPOSE_TO);
                else
-                       compose_entry_append(compose,
-                                            compose->followup_to ? compose->followup_to
-                                            : compose->newsgroups ? compose->newsgroups
-                                            : "",
-                                            COMPOSE_NEWSGROUPS);
-       /*
-               compose_entry_append(compose,
-                                    compose->followup_to ? compose->followup_to
-                                    : compose->newsgroups ? compose->newsgroups
-                                    : "",
-                                    COMPOSE_NEWSGROUPS);
-       */
+                       compose_entry_append
+                               (compose,
+                                compose->followup_to ? compose->followup_to
+                                : compose->newsgroups ? compose->newsgroups
+                                : "",
+                                COMPOSE_NEWSGROUPS);
+       }
 
        if (msginfo->subject && *msginfo->subject) {
                gchar *buf, *buf2, *p;
@@ -1906,6 +1912,16 @@ static void compose_attach_append(Compose *compose, const gchar *file,
        compose_attach_info(compose, ainfo, cnttype);
 }
 
+#define GET_CHAR(pos, buf, len)                                                     \
+{                                                                           \
+       if (text->use_wchar)                                                 \
+               len = wctomb(buf, (wchar_t)GTK_STEXT_INDEX(text, (pos)));     \
+       else {                                                               \
+               buf[0] = GTK_STEXT_INDEX(text, (pos));                       \
+               len = 1;                                                     \
+       }                                                                    \
+}
+
 static void compose_wrap_line(Compose *compose)
 {
        GtkSText *text = GTK_STEXT(compose->text);
@@ -1918,13 +1934,6 @@ static void compose_wrap_line(Compose *compose)
        gint line_pos, cur_pos;
        gint line_len, cur_len;
 
-#define GET_STEXT(pos)                                                        \
-       if (text->use_wchar)                                                 \
-               ch_len = wctomb(cbuf, (wchar_t)GTK_STEXT_INDEX(text, (pos))); \
-       else {                                                               \
-               cbuf[0] = GTK_STEXT_INDEX(text, (pos));                       \
-               ch_len = 1;                                                  \
-       }
 
        gtk_stext_freeze(text);
 
@@ -1932,11 +1941,11 @@ static void compose_wrap_line(Compose *compose)
 
        /* check to see if the point is on the paragraph mark (empty line). */
        cur_pos = gtk_stext_get_point(text);
-       GET_STEXT(cur_pos);
+       GET_CHAR(cur_pos, cbuf, ch_len);
        if ((ch_len == 1 && *cbuf == '\n') || cur_pos == text_len) {
                if (cur_pos == 0)
                        goto compose_end; /* on the paragraph mark */
-               GET_STEXT(cur_pos - 1);
+               GET_CHAR(cur_pos - 1, cbuf, ch_len);
                if (ch_len == 1 && *cbuf == '\n')
                        goto compose_end; /* on the paragraph mark */
        }
@@ -1944,7 +1953,7 @@ static void compose_wrap_line(Compose *compose)
        /* find paragraph start. */
        line_end = quoted = 0;
        for (p_start = cur_pos; p_start >= 0; --p_start) {
-               GET_STEXT(p_start);
+               GET_CHAR(p_start, cbuf, ch_len);
                if (ch_len == 1 && *cbuf == '\n') {
                        if (quoted)
                                goto compose_end; /* quoted part */
@@ -1968,7 +1977,7 @@ static void compose_wrap_line(Compose *compose)
        /* find paragraph end. */
        line_end = 0;
        for (p_end = cur_pos; p_end < text_len; p_end++) {
-               GET_STEXT(p_end);
+               GET_CHAR(p_end, cbuf, ch_len);
                if (ch_len == 1 && *cbuf == '\n') {
                        if (line_end) {
                                p_end -= 1;
@@ -1995,7 +2004,7 @@ static void compose_wrap_line(Compose *compose)
        for (cur_pos = p_start; cur_pos < p_end; cur_pos++) {
                guint space = 0;
 
-               GET_STEXT(cur_pos);
+               GET_CHAR(cur_pos, cbuf, ch_len);
 
                if (ch_len < 0) {
                        cbuf[0] = '\0';
@@ -2009,7 +2018,7 @@ static void compose_wrap_line(Compose *compose)
                        guint replace = 0;
                        if (last_ch_len == 1 && !isspace(last_ch)) {
                                if (cur_pos + 1 < p_end) {
-                                       GET_STEXT(cur_pos + 1);
+                                       GET_CHAR(cur_pos + 1, cbuf, ch_len);
                                        if (ch_len == 1 && !isspace(*cbuf))
                                                replace = 1;
                                }
@@ -2040,7 +2049,7 @@ static void compose_wrap_line(Compose *compose)
                    line_len > 0) {
                        gint tlen = ch_len;
 
-                       GET_STEXT(line_pos - 1);
+                       GET_CHAR(line_pos - 1, cbuf, ch_len);
                        if (ch_len == 1 && isspace(*cbuf)) {
                                gtk_stext_set_point(text, line_pos);
                                gtk_stext_backward_delete(text, 1);
@@ -2071,25 +2080,17 @@ static void compose_wrap_line(Compose *compose)
 
 compose_end:
        gtk_stext_thaw(text);
-
-#undef GET_STEXT
 }
 
 /* return indent length */
-static guint get_indent_length(GtkSText *text, guint start_pos,
-                              guint text_len) {
+static guint get_indent_length(GtkSText *text, guint start_pos, guint text_len)
+{
        gint indent_len = 0;
        gint i, ch_len;
-       gchar cbuf[MB_CUR_MAX];
+       gchar cbuf[MB_LEN_MAX];
 
        for (i = start_pos; i < text_len; i++) {
-               if (text->use_wchar)
-                       ch_len = wctomb
-                               (cbuf, (wchar_t)GTK_STEXT_INDEX(text, i));
-               else {
-                       cbuf[0] = GTK_STEXT_INDEX(text, i);
-                       ch_len = 1;
-               }
+               GET_CHAR(i, cbuf, ch_len);
                if (ch_len > 1)
                        break;
                /* allow space, tab, > or | */
@@ -2102,11 +2103,11 @@ static guint get_indent_length(GtkSText *text, guint start_pos,
        return indent_len;
 }
 
-/* insert quotation string when line was wrapped, we know these
-   are single byte characters */
+/* insert quotation string when line was wrapped */
 static guint ins_quote(GtkSText *text, guint quote_len, guint indent_len,
                       guint prev_line_pos, guint text_len,
-                      gchar *quote_fmt) {
+                      gchar *quote_fmt)
+{
        guint i, ins_len;
        gchar ch;
 
@@ -2116,8 +2117,7 @@ static guint ins_quote(GtkSText *text, guint quote_len, guint indent_len,
                        gtk_stext_insert(text, NULL, NULL, NULL, &ch, 1);
                }
                ins_len = indent_len;
-       }
-       else {
+       } else {
                gtk_stext_insert(text, NULL, NULL, NULL, quote_fmt, quote_len);
                ins_len = quote_len;
        }
@@ -2130,18 +2130,17 @@ static guint ins_quote(GtkSText *text, guint quote_len, guint indent_len,
 /* Darko: used when I debug wrapping */
 void dump_text(GtkSText *text, int pos, int tlen, int breakoncr)
 {
-    int i;
-    char ch;
+       gint i;
+       gchar ch;
 
-    printf("%d [", pos);
-    for (i = pos; i < tlen; i++)
-    {
-        ch = GTK_STEXT_INDEX(text, i);
-        if (breakoncr && ch == '\n')
-            break;
-        printf("%c", ch);
-    }
-    printf("]\n");
+       printf("%d [", pos);
+       for (i = pos; i < tlen; i++) {
+               ch = GTK_STEXT_INDEX(text, i);
+               if (breakoncr && ch == '\n')
+                       break;
+               printf("%c", ch);
+       }
+       printf("]\n");
 }
 #endif
 
@@ -2152,7 +2151,7 @@ static void compose_wrap_line_all(Compose *compose)
        guint line_pos = 0, cur_pos = 0, p_pos = 0;
        gint line_len = 0, cur_len = 0;
        gint ch_len;
-       gint is_new_line = 1, do_delete = 0;
+       gboolean is_new_line = TRUE, do_delete = FALSE;
        guint qlen = 0, i_len = 0;
        guint linewrap_quote = prefs_common.linewrap_quote;
        guint linewrap_len = prefs_common.linewrap_len;
@@ -2162,18 +2161,18 @@ static void compose_wrap_line_all(Compose *compose)
        gtk_stext_freeze(text);
 
        /* make text buffer contiguous */
-       gtk_stext_compact_buffer(text);
+       /* gtk_stext_compact_buffer(text); */
 
        tlen = gtk_stext_get_length(text);
 
        for (; cur_pos < tlen; cur_pos++) {
                /* mark position of new line - needed for quotation wrap */
                if (linewrap_quote && is_new_line) {
-                       qlen = gtkstext_str_strcmp(text, cur_pos, tlen, qfmt);
-                       is_new_line = 0;
-                       if (qlen) {
+                       qlen = gtkut_text_str_compare
+                               (text, cur_pos, tlen, qfmt);
+                       is_new_line = FALSE;
+                       if (qlen)
                                i_len = get_indent_length(text, cur_pos, tlen);
-                       }
                        else
                                i_len = 0;
                        p_pos = cur_pos;
@@ -2183,14 +2182,7 @@ static void compose_wrap_line_all(Compose *compose)
 #endif
                }
 
-               /* get character(s) at current position */
-               if (text->use_wchar)
-                       ch_len = wctomb
-                               (cbuf, (wchar_t)GTK_STEXT_INDEX(text, cur_pos));
-               else {
-                       cbuf[0] = GTK_STEXT_INDEX(text, cur_pos);
-                       ch_len = 1;
-               }
+               GET_CHAR(cur_pos, cbuf, ch_len);
 
                /* fix line length for tabs */
                if (ch_len == 1 && *cbuf == '\t') {
@@ -2217,25 +2209,26 @@ static void compose_wrap_line_all(Compose *compose)
                        gchar cb[MB_CUR_MAX];
 
 #ifdef WRAP_DEBUG
-                       printf("found CR at %d\n", cur_pos);
+                       printf("found CR at %d next line is ", cur_pos);
+                       dump_text(text, cur_pos + 1, tlen, 1);
 #endif
                        /* if it's just quotation + newline skip it */
                        if (i_len && (cur_pos + 1 < tlen)) {
                                /* check if text at new line matches indent */
-                               ilen =  gtkstext_strncmp(text, cur_pos + 1,
-                                                        p_pos, i_len, tlen);
+                               ilen =  gtkut_text_str_compare_n
+                                       (text, cur_pos + 1, p_pos, i_len, tlen);
                                if (cur_pos + ilen < tlen) {
-                                       if (text->use_wchar)
-                                               clen = wctomb(cb, (wchar_t)GTK_STEXT_INDEX(text, cur_pos + ilen + 1));
-                                       else {
-                                               cb[0] = GTK_STEXT_INDEX(text,
-                                                           cur_pos + ilen + 1);
-                                               clen = 1;
-                                       }
+                                       GET_CHAR(cur_pos + ilen + 1, cb, clen);
                                        /* no need to join the lines */
-                                       if ((clen == 1) && (cb[0] == '\n'))
-                                               do_delete = 0;
+                                       if (clen == 1 && cb[0] == '\n')
+                                               do_delete = FALSE;
                                }
+                       /* if it's just newline skip it */
+                       } else if (do_delete && (cur_pos + 1 < tlen)) {
+                               GET_CHAR(cur_pos + 1, cb, clen);
+                               /* no need to join the lines */
+                               if (clen == 1 && cb[0] == '\n')
+                                       do_delete = FALSE;
                        }
 
 #ifdef WRAP_DEBUG
@@ -2243,7 +2236,7 @@ static void compose_wrap_line_all(Compose *compose)
                                qlen, line_len, linewrap_len, do_delete);
 #endif
                        /* should we delete to perform smart wrapping */
-                       if (qlen && line_len < linewrap_len && do_delete) {
+                       if (line_len < linewrap_len && do_delete) {
                                /* get rid of newline */
                                gtk_stext_set_point(text, cur_pos);
                                gtk_stext_forward_delete(text, 1);
@@ -2252,38 +2245,31 @@ static void compose_wrap_line_all(Compose *compose)
                                /* if text starts with quote fmt or with
                                   indent string, delete them */
                                if (i_len) {
-                                       ilen =  gtkstext_strncmp(text, cur_pos,
-                                                                p_pos, i_len,
-                                                                tlen);
+                                       ilen =  gtkut_text_str_compare_n
+                                               (text, cur_pos, p_pos, i_len,
+                                                tlen);
                                        if (ilen) {
                                                gtk_stext_forward_delete(text,
                                                                         ilen);
                                                tlen -= ilen;
                                        }
-                               }
-                               else if (qlen) {
-                                       if (gtkstext_str_strcmp(text, cur_pos,
-                                                               tlen, qfmt)) {
-                                               gtk_stext_forward_delete(text,
-                                                                qlen);
+                               } else if (qlen) {
+                                       if (gtkut_text_str_compare
+                                           (text, cur_pos, tlen, qfmt)) {
+                                               gtk_stext_forward_delete
+                                                       (text, qlen);
                                                tlen -= qlen;
                                        }
                                }
 
-                               if (text->use_wchar)
-                                       clen = wctomb
-                                               (cb, (wchar_t)GTK_STEXT_INDEX(text, cur_pos));
-                               else {
-                                       cb[0] = GTK_STEXT_INDEX(text, cur_pos);
-                                       clen = 1;
-                               }
+                               GET_CHAR(cur_pos, cb, clen);
 
                                /* insert space if it's alphanumeric */
                                if ((cur_pos != line_pos) &&
                                    ((clen > 1) || isalnum(cb[0]))) {
                                        gtk_stext_insert(text, NULL, NULL,
-                                                        NULL, " ", 1);
-                                       gtk_stext_compact_buffer(text);
+                                                       NULL, " ", 1);
+                                       /* gtk_text_compact_buffer(text); */
                                        tlen++;
                                }
 
@@ -2292,8 +2278,8 @@ static void compose_wrap_line_all(Compose *compose)
                                line_pos = cur_pos;
                                line_len = cur_len = 0;
                                qlen = 0;
-                               do_delete = 0;
-                               is_new_line = 1;
+                               do_delete = FALSE;
+                               is_new_line = TRUE;
 #ifdef WRAP_DEBUG
                                printf("after delete l_pos=");
                                dump_text(text, line_pos, tlen, 1);
@@ -2305,8 +2291,8 @@ static void compose_wrap_line_all(Compose *compose)
                        line_pos = cur_pos + 1;
                        line_len = cur_len = 0;
                        qlen = 0;
-                       do_delete = 0;
-                       is_new_line = 1;
+                       do_delete = FALSE;
+                       is_new_line = TRUE;
                        continue;
                }
 
@@ -2332,22 +2318,20 @@ static void compose_wrap_line_all(Compose *compose)
 #endif
                        /* force wrapping if it is one long word but not URL */
                        if (p_pos + i_len == line_pos)
-                               if (!is_url_string(text, line_pos, tlen))
+                               if (!gtkut_text_is_uri_string
+                                   (text, line_pos, tlen))
                                        line_pos = cur_pos - 1;
 #ifdef WRAP_DEBUG
                        printf("new line_pos=%d\n", line_pos);
 #endif
 
+                       GET_CHAR(line_pos - 1, cbuf, clen);
+
                        /* if next character is space delete it */
-                       if (text->use_wchar)
-                               clen = wctomb(cbuf, (wchar_t)GTK_STEXT_INDEX(text, line_pos - 1));
-                       else {
-                               cbuf[0] = GTK_STEXT_INDEX(text, line_pos - 1);
-                               clen = 1;
-                       }
                         if (clen == 1 && isspace(*cbuf)) {
                                if (p_pos + i_len != line_pos ||
-                                   !is_url_string(text, line_pos, tlen)) {
+                                   !gtkut_text_is_uri_string
+                                       (text, line_pos, tlen)) {
                                        gtk_stext_set_point(text, line_pos);
                                        gtk_stext_backward_delete(text, 1);
                                        tlen--;
@@ -2360,7 +2344,7 @@ static void compose_wrap_line_all(Compose *compose)
 
                        /* if it is URL at beginning of line don't wrap */
                        if (p_pos + i_len == line_pos &&
-                            is_url_string(text, line_pos, tlen)) {
+                           gtkut_text_is_uri_string(text, line_pos, tlen)) {
 #ifdef WRAP_DEBUG
                                printf("found URL at ");
                                dump_text(text, line_pos, tlen, 1);
@@ -2371,43 +2355,37 @@ static void compose_wrap_line_all(Compose *compose)
                        /* insert CR */
                        gtk_stext_set_point(text, line_pos);
                        gtk_stext_insert(text, NULL, NULL, NULL, "\n", 1);
-                       gtk_stext_compact_buffer(text);
+                       /* gtk_stext_compact_buffer(text); */
                        tlen++;
-                       cur_pos++;
                        line_pos++;
-                       cur_len = cur_len - line_len + ch_len;
+                       /* for loop will increase it */
+                       cur_pos = line_pos - 1;
+                       /* start over with current line */
+                       is_new_line = TRUE;
                        line_len = 0;
+                       cur_len = 0;
+                       do_delete = TRUE;
 #ifdef WRAP_DEBUG
                        printf("after CR insert ");
                        dump_text(text, line_pos, tlen, 1);
+                       dump_text(text, cur_pos, tlen, 1);
 #endif
 
                        /* should we insert quotation ? */
                        if (linewrap_quote && qlen) {
                                /* only if line is not already quoted  */
-                               if (!gtkstext_str_strcmp(text, line_pos,
-                                                        tlen, qfmt)) {
+                               if (!gtkut_text_str_compare
+                                       (text, line_pos, tlen, qfmt)) {
                                        guint ins_len;
 
                                        if (line_pos - p_pos > i_len) {
-                                               ins_len = ins_quote(text,
-                                                                   qlen,
-                                                                   i_len,
-                                                                   p_pos,
-                                                                   tlen,
-                                                                   qfmt);
-
-                                               gtk_stext_compact_buffer(text);
+                                               ins_len = ins_quote
+                                                       (text, qlen, i_len,
+                                                        p_pos, tlen, qfmt);
+
+                                               /* gtk_stext_compact_buffer(text); */
                                                tlen += ins_len;
                                        }
-
-                                       /* for loop will increase it */
-                                       cur_pos = line_pos - 1;
-                                       cur_len = 0;
-                                       line_len = 0;
-                                       /* start over with current line */
-                                       is_new_line = 1;
-                                       do_delete = 1;
 #ifdef WRAP_DEBUG
                                        printf("after quote insert ");
                                        dump_text(text, line_pos, tlen, 1);
@@ -2428,6 +2406,8 @@ static void compose_wrap_line_all(Compose *compose)
        gtk_stext_thaw(text);
 }
 
+#undef GET_CHAR
+
 static void compose_set_title(Compose *compose)
 {
        gchar *str;
@@ -2490,8 +2470,8 @@ gboolean compose_check_for_valid_recipient(Compose *compose) {
        for(list = compose->header_list; list; list = list->next) {
                gchar *header;
                gchar *entry;
-               header = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(((compose_headerentry *)list->data)->combo)->entry));
-               entry = gtk_editable_get_chars(GTK_EDITABLE(((compose_headerentry *)list->data)->entry), 0, -1);
+               header = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry));
+               entry = gtk_editable_get_chars(GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
                g_strstrip(entry);
                if(entry[0] != '\0') {
                        for(strptr = recipient_headers_mail; *strptr != NULL; strptr++) {
@@ -2521,7 +2501,7 @@ gint compose_send(Compose *compose)
        val = compose_queue(compose, &msgnum, &folder);
        if (val) {
                alertpanel_error(_("Could not queue message for sending"));
-               return;
+               return -1;
        }
        
        val = procmsg_send_message_queue(folder_item_fetch_msg(folder, msgnum));
@@ -2658,10 +2638,6 @@ static gboolean compose_use_attach(Compose *compose) {
     return(gtk_clist_get_row_data(GTK_CLIST(compose->attach_clist), 0) != NULL);
 }
 
-
-
-
-
 static gint compose_bounce_write_headers_from_headerlist(Compose *compose, 
                                                         FILE *fp)
 {
@@ -2669,11 +2645,11 @@ static gint compose_bounce_write_headers_from_headerlist(Compose *compose,
        gchar *str;
        gboolean first_address;
        GSList *list;
-       compose_headerentry *headerentry;
-       gchar * headerentryname;
-       gchar * header_w_colon;
-       gchar * cc_hdr;
-       gchar * to_hdr;
+       ComposeHeaderEntry *headerentry;
+       gchar *headerentryname;
+       gchar *header_w_colon;
+       gchar *cc_hdr;
+       gchar *to_hdr;
 
        debug_print(_("Writing bounce header\n"));
 
@@ -2684,7 +2660,7 @@ static gint compose_bounce_write_headers_from_headerlist(Compose *compose,
        
        first_address = TRUE;
        for(list = compose->header_list; list; list = list->next) {
-               headerentry = ((compose_headerentry *)list->data);
+               headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
 
                if(g_strcasecmp(headerentryname, cc_hdr) == 0 
@@ -2706,14 +2682,13 @@ static gint compose_bounce_write_headers_from_headerlist(Compose *compose,
                        }
                }
        }
-       //      if(!first_address) {
+       /* if(!first_address) { */
        fprintf(fp, "\n");
-               //      }
+       /* } */
 
        return(0);
 }
 
-
 static gint compose_bounce_write_headers(Compose *compose, FILE *fp)
 {
        gchar buf[BUFFSIZE];
@@ -2759,7 +2734,7 @@ static gint compose_bounce_write_to_file(Compose *compose, const gchar *file)
                return -1;
        }
 
-       if ((fdest = fopen(file, "a+")) == NULL) {
+       if ((fdest = fopen(file, "w")) == NULL) {
                FILE_OP_ERROR(file, "fopen");
                fclose(fp);
                return -1;
@@ -2812,7 +2787,7 @@ static gint compose_write_to_file(Compose *compose, const gchar *file,
        const gchar *out_codeset;
        EncodingType encoding;
 
-       if ((fp = fopen(file, "a+")) == NULL) {
+       if ((fp = fopen(file, "w")) == NULL) {
                FILE_OP_ERROR(file, "fopen");
                return -1;
        }
@@ -3036,7 +3011,7 @@ static gint compose_remove_reedit_target(Compose *compose)
 static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
 {
        FolderItem *queue;
-       gchar *tmpfilename, *queue_path;
+       gchar *tmp, *tmp2, *queue_path;
        FILE *fp, *src_fp;
        GSList *cur;
        gchar buf[BUFFSIZE];
@@ -3058,27 +3033,10 @@ static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
                                                                        
        if (!compose->to_list && !compose->newsgroup_list) {
                g_warning(_("can't get recipient list."));
-               unlink(tmpfilename);
                lock = FALSE;
                 return -1;
         }
 
-        if (prefs_common.linewrap_at_send)
-               compose_wrap_line_all(compose);
-                       
-       /* write to temporary file */
-       tmpfilename = g_strdup_printf("%s%cqueue.%d", g_get_tmp_dir(),
-                             G_DIR_SEPARATOR, (gint)compose);
-       if ((fp = fopen(tmpfilename, "w")) == NULL) {
-               FILE_OP_ERROR(tmpfilename, "fopen");
-               g_free(tmpfilename);
-               return -1;
-       }
-       if (change_file_mode_rw(fp, tmpfilename) < 0) {
-               FILE_OP_ERROR(tmpfilename, "chmod");
-               g_warning(_("can't change file mode\n"));
-       }
-
        if(compose->to_list) {
                if (compose->account->protocol != A_NNTP)
                        mailac = compose->account;
@@ -3087,7 +3045,6 @@ static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
                else if (cur_account && cur_account->protocol != A_NNTP)
                        mailac = cur_account;
                else if (!(mailac = compose_current_mail_account())) {
-                       unlink(tmpfilename);
                        lock = FALSE;
                        alertpanel_error(_("No account for sending mails available!"));
                        return -1;
@@ -3098,13 +3055,56 @@ static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
                 if (compose->account->protocol == A_NNTP)
                         newsac = compose->account;
                 else if(!(newsac = compose->orig_account) || (newsac->protocol != A_NNTP)) {
-                       unlink(tmpfilename);
                        lock = FALSE;
                        alertpanel_error(_("No account for posting news available!"));
                        return -1;
                }                       
        }
 
+        if (prefs_common.linewrap_at_send)
+               compose_wrap_line_all(compose);
+                       
+       /* write to temporary file */
+       tmp2 = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(),
+                                     G_DIR_SEPARATOR, (gint)compose);
+
+       if (compose->bounce_filename != NULL) {
+               if (compose_bounce_write_to_file(compose, tmp2) < 0) {
+                       unlink(tmp2);
+                       lock = FALSE;
+                       return -1;
+               }
+       }
+       else {
+               if (compose_write_to_file(compose, tmp2, FALSE) < 0) {
+                       unlink(tmp2);
+                       lock = FALSE;
+                       return -1;
+               }
+       }
+
+       /* add queue header */
+       tmp = g_strdup_printf("%s%cqueue.%d", g_get_tmp_dir(),
+                                     G_DIR_SEPARATOR, (gint)compose);
+       if ((fp = fopen(tmp, "w")) == NULL) {
+               FILE_OP_ERROR(tmp, "fopen");
+               g_free(tmp);
+               return -1;
+       }
+       if ((src_fp = fopen(tmp2, "r")) == NULL) {
+               FILE_OP_ERROR(tmp2, "fopen");
+               fclose(fp);
+               unlink(tmp);
+               g_free(tmp);
+               unlink(tmp2);
+               g_free(tmp2);
+               return -1;
+       }
+       if (change_file_mode_rw(fp, tmp) < 0) {
+               FILE_OP_ERROR(tmp, "chmod");
+               g_warning(_("can't change file mode\n"));
+       }
+
        /* queueing variables */
        fprintf(fp, "AF:\n");
        fprintf(fp, "NF:0\n");
@@ -3153,21 +3153,27 @@ static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
                fprintf(fp, "NAID:%d\n", newsac->account_id);
        }
        fprintf(fp, "\n");
-       fclose(fp);
 
-       if (compose->bounce_filename != NULL) {
-               if (compose_bounce_write_to_file(compose, tmpfilename) < 0) {
-                       unlink(tmpfilename);
-                       lock = FALSE;
+       while (fgets(buf, sizeof(buf), src_fp) != NULL) {
+               if (fputs(buf, fp) == EOF) {
+                       FILE_OP_ERROR(tmp, "fputs");
+                       fclose(fp);
+                       fclose(src_fp);
+                       unlink(tmp);
+                       g_free(tmp);
+                       unlink(tmp2);
+                       g_free(tmp2);
                        return -1;
                }
        }
-       else {
-               if (compose_write_to_file(compose, tmpfilename, FALSE) < 0) {
-                       unlink(tmpfilename);
-                       lock = FALSE;
-                       return -1;
-               }
+       fclose(src_fp);
+       if (fclose(fp) == EOF) {
+               FILE_OP_ERROR(tmp, "fclose");
+               unlink(tmp);
+               g_free(tmp);
+               unlink(tmp2);
+               g_free(tmp2);
+               return -1;
        }
                                                
        /* queue message */
@@ -3177,14 +3183,17 @@ static gint compose_queue(Compose *compose, gint *msgnum, FolderItem **item)
        queue_path = folder_item_get_path(queue);
        if (!is_dir_exist(queue_path))
                make_dir_hier(queue_path);
-       if ((num = folder_item_add_msg(queue, tmpfilename, TRUE)) < 0) {
+       if ((num = folder_item_add_msg(queue, tmp, TRUE)) < 0) {
                g_warning(_("can't queue the message\n"));
-               unlink(tmpfilename);
-               g_free(tmpfilename);
+               unlink(tmp);
+               g_free(tmp);
                g_free(queue_path);
                return -1;
        }
-       g_free(tmpfilename);
+       unlink(tmp);
+       g_free(tmp);
+       unlink(tmp2);
+       g_free(tmp2);
 
        if (compose->mode == COMPOSE_REEDIT) {
                compose_remove_reedit_target(compose);
@@ -3294,7 +3303,7 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
        gchar *str, *header_w_colon, *trans_hdr;
        gboolean first_address;
        GSList *list;
-       compose_headerentry *headerentry;
+       ComposeHeaderEntry *headerentry;
        gchar * headerentryname;
 
        if (IS_IN_CUSTOM_HEADER(header)) {
@@ -3308,7 +3317,7 @@ static gint compose_write_headers_from_headerlist(Compose *compose,
 
        first_address = TRUE;
        for(list = compose->header_list; list; list = list->next) {
-               headerentry = ((compose_headerentry *)list->data);
+               headerentry = ((ComposeHeaderEntry *)list->data);
                headerentryname = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(headerentry->combo)->entry));
 
                if(!g_strcasecmp(trans_hdr, headerentryname)) {
@@ -3545,21 +3554,23 @@ 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 (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) {
                                compose_convert_header
                                        (buf, sizeof(buf),
                                         chdr->value ? chdr->value : "",
                                         strlen(chdr->name) + 2);
-                       fprintf(fp, "%s: %s\n", chdr->name, buf);
+                               fprintf(fp, "%s: %s\n", chdr->name, buf);
+                       }
                }
        }
 
@@ -3687,7 +3698,9 @@ static void compose_create_header_entry(Compose *compose) {
        GtkWidget *entry;
        GList *combo_list = NULL;
        gchar **string, *header;
-       compose_headerentry *headerentry = g_new0(compose_headerentry, 1);
+       ComposeHeaderEntry *headerentry;
+
+       headerentry = g_new0(ComposeHeaderEntry, 1);
 
        /* Combo box */
        combo = gtk_combo_new();
@@ -3706,10 +3719,10 @@ static void compose_create_header_entry(Compose *compose) {
        } else {
                switch(compose->account->protocol) {
                        case A_NNTP:
-                               header = _("Newsgroups:");
+                               header = prefs_common.trans_hdr ? _("Newsgroups:") : "Newsgroups:";
                                break;
                        default:
-                               header = _("To:");
+                               header = prefs_common.trans_hdr ? _("To:") : "To:";
                                break;
                }                                                                   
        }
@@ -3735,7 +3748,7 @@ static void compose_create_header_entry(Compose *compose) {
 }
 
 static void compose_add_header_entry(Compose *compose, gchar *header, gchar *text) {
-       compose_headerentry *last_header;
+       ComposeHeaderEntry *last_header;
        
        last_header = compose->header_last;
        
@@ -3791,6 +3804,8 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        GtkWidget *table;
        GtkWidget *hbox;
 
+       UndoMain *undostruct;
+
        gchar *titles[] = {_("MIME type"), _("Size"), _("Name")};
        guint n_menu_entries;
        GtkStyle  *style, *new_style;
@@ -4175,8 +4190,9 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        compose->vbox2         = vbox2;
 
        compose->table_vbox       = table_vbox;
-       compose->table            = table;
+       compose->table            = NULL;
 #if 0 /* NEW COMPOSE GUI */
+       compose->table            = table;
        compose->to_hbox          = to_hbox;
        compose->to_entry         = to_entry;
        compose->newsgroups_hbox  = newsgroups_hbox;
@@ -4257,6 +4273,11 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
         compose->gtkpspell      = gtkpspell;
 #endif
 
+       undostruct = undo_init(text);
+
+       compose->undostruct = undostruct;
+       undo_set_undo_change_funct(undostruct, &compose_set_undo, GTK_WIDGET(compose->menubar));
+
 #if 0 /* NEW COMPOSE GUI */
        if (account->protocol != A_NNTP) {
                menuitem = gtk_item_factory_get_item(ifactory, "/Message/To");
@@ -4571,29 +4592,33 @@ void compose_reflect_prefs_all(void)
        }
 }
 
-static void compose_template_apply(Compose *compose, const gchar *tmpl_str)
+static void compose_template_apply(Compose *compose, Template *tmpl)
 {
        gchar *qmark;
        gchar *parsed_str;
 
-       if (!tmpl_str) return;
+       if (!tmpl || !tmpl->value) return;
 
        gtk_stext_freeze(GTK_STEXT(compose->text));
+        
+       if (tmpl->subject)
+               gtk_entry_set_text(GTK_ENTRY(compose->subject_entry),
+                                  tmpl->subject);
 
        if (compose->replyinfo == NULL) {
                MsgInfo dummyinfo;
 
                memset(&dummyinfo, 0, sizeof(MsgInfo));
-               parsed_str = compose_quote_fmt(compose, &dummyinfo, tmpl_str,
-                                              NULL);
+               parsed_str = compose_quote_fmt(compose, &dummyinfo,
+                                              tmpl->value, NULL);
        } else {
                if (prefs_common.quotemark && *prefs_common.quotemark)
                        qmark = prefs_common.quotemark;
                else
                        qmark = "> ";
 
-               parsed_str = compose_quote_fmt(compose, compose->replyinfo, tmpl_str,
-                                              qmark);
+               parsed_str = compose_quote_fmt(compose, compose->replyinfo,
+                                              tmpl->value, qmark);
        }
 
        if (parsed_str && prefs_common.auto_sig)
@@ -5580,7 +5605,7 @@ static void compose_template_activate_cb(GtkWidget *widget, gpointer data)
        tmpl = gtk_object_get_data(GTK_OBJECT(widget), "template");
        g_return_if_fail(tmpl != NULL);
 
-       compose_template_apply(compose, tmpl->value);
+       compose_template_apply(compose, tmpl);
 }
 
 static void compose_ext_editor_cb(gpointer data, guint action,
@@ -5596,6 +5621,16 @@ static void compose_destroy_cb(GtkWidget *widget, Compose *compose)
        compose_destroy(compose);
 }
 
+static void compose_undo_cb(Compose *compose) 
+{
+       undo_undo(compose->undostruct);
+}
+
+static void compose_redo_cb(Compose *compose) 
+{
+       undo_redo(compose->undostruct);
+}
+
 static void compose_cut_cb(Compose *compose)
 {
        if (compose->focused_editable &&
@@ -5953,23 +5988,106 @@ static void compose_toggle_return_receipt_cb(gpointer data, guint action,
                compose->return_receipt = FALSE;
 }
 
-void compose_headerentry_key_press_event_cb(GtkWidget *entry, GdkEventKey *event, compose_headerentry *headerentry) {
-       if((g_slist_length(headerentry->compose->header_list) > 0) &&
+void compose_headerentry_key_press_event_cb(GtkWidget *entry,
+                                           GdkEventKey *event,
+                                           ComposeHeaderEntry *headerentry)
+{
+       if ((g_slist_length(headerentry->compose->header_list) > 0) &&
            ((headerentry->headernum + 1) != headerentry->compose->header_nextrow) &&
            !(event->state & GDK_MODIFIER_MASK) &&
            (event->keyval == GDK_BackSpace) &&
            (strlen(gtk_entry_get_text(GTK_ENTRY(entry))) == 0)) {
-               gtk_container_remove(GTK_CONTAINER(headerentry->compose->header_table), headerentry->combo);
-               gtk_container_remove(GTK_CONTAINER(headerentry->compose->header_table), headerentry->entry);
-               headerentry->compose->header_list = g_slist_remove(headerentry->compose->header_list, headerentry);
+               gtk_container_remove
+                       (GTK_CONTAINER(headerentry->compose->header_table),
+                        headerentry->combo);
+               gtk_container_remove
+                       (GTK_CONTAINER(headerentry->compose->header_table),
+                        headerentry->entry);
+               headerentry->compose->header_list =
+                       g_slist_remove(headerentry->compose->header_list,
+                                      headerentry);
                g_free(headerentry);
        }
 }
 
-void compose_headerentry_changed_cb(GtkWidget *entry, compose_headerentry *headerentry) {
-       if(strlen(gtk_entry_get_text(GTK_ENTRY(entry))) != 0) {
-               headerentry->compose->header_list = g_slist_append(headerentry->compose->header_list, headerentry);
+void compose_headerentry_changed_cb(GtkWidget *entry,
+                                   ComposeHeaderEntry *headerentry)
+{
+       if (strlen(gtk_entry_get_text(GTK_ENTRY(entry))) != 0) {
+               headerentry->compose->header_list =
+                       g_slist_append(headerentry->compose->header_list,
+                                      headerentry);
                compose_create_header_entry(headerentry->compose);
-               gtk_signal_disconnect_by_func(GTK_OBJECT(entry), GTK_SIGNAL_FUNC(compose_headerentry_changed_cb), headerentry);
+               gtk_signal_disconnect_by_func
+                       (GTK_OBJECT(entry),
+                        GTK_SIGNAL_FUNC(compose_headerentry_changed_cb),
+                        headerentry);
        }
 }
+
+/**
+ * undo_set_undo:
+ *
+ * Change the sensivity of the menuentries undo and redo
+ **/
+static void compose_set_undo(UndoMain *undostruct, gint undo_state, 
+                            gint redo_state, GtkWidget *changewidget) 
+{
+       GtkItemFactory *ifactory;
+        debug_print ("Set_undo.  UNDO:%i  REDO:%i\n",
+                 undo_state,
+                 redo_state);
+
+       g_return_if_fail (changewidget != NULL);
+
+       ifactory = gtk_item_factory_from_widget(changewidget);
+
+       /* Set undo */
+        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);
+                }
+                break;
+        case UNDO_STATE_FALSE:
+                if (undostruct->undo_state) {
+                        undostruct->undo_state = FALSE;
+                       menu_set_sensitive(ifactory, "/Edit/Undo", FALSE);
+                }
+                break;
+        case UNDO_STATE_UNCHANGED:
+                break;
+        case UNDO_STATE_REFRESH:
+               menu_set_sensitive(ifactory, "/Edit/Undo", undostruct->undo_state);
+                break;
+        default:
+                g_warning ("Undo state not recognized");
+               break;
+        }
+
+        /* Set redo*/
+        switch (redo_state) {
+        case UNDO_STATE_TRUE:
+                if (!undostruct->redo_state) {
+                        undostruct->redo_state = TRUE;
+                       menu_set_sensitive(ifactory, "/Edit/Redo", TRUE);
+                }
+                break;
+        case UNDO_STATE_FALSE:
+                if (undostruct->redo_state) {
+                        undostruct->redo_state = FALSE;
+                       menu_set_sensitive(ifactory, "/Edit/Redo", FALSE);
+                }
+                break;
+        case UNDO_STATE_UNCHANGED:
+                break;
+        case UNDO_STATE_REFRESH:
+               menu_set_sensitive(ifactory, "/Edit/Redo", undostruct->redo_state);
+                break;
+        default:
+                g_warning ("Redo state not recognized");
+               break;
+        }
+}