2005-03-04 [paul] 1.0.1cvs21
[claws.git] / src / compose.c
index 49b04cf4c391ce638639c3f2d557fca24819dd10..bc19e2a2a348d2380709d08c2356fa300235e488 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2004 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -425,9 +425,8 @@ static void compose_toggle_sign_cb  (gpointer        data,
 static void compose_toggle_encrypt_cb  (gpointer        data,
                                         guint           action,
                                         GtkWidget      *widget);
-static void compose_set_privacy_system_cb(gpointer        data,
-                                        guint           action,
-                                        GtkWidget      *widget);
+static void compose_set_privacy_system_cb(GtkWidget      *widget,
+                                         gpointer        data);
 static void compose_update_privacy_system_menu_item(Compose * compose);
 static void activate_privacy_system     (Compose *compose, 
                                          PrefsAccount *account);
@@ -512,6 +511,8 @@ static gboolean compose_send_control_enter  (Compose        *compose);
 static gint compose_defer_auto_save_draft      (Compose        *compose);
 static PrefsAccount *compose_guess_forward_account_from_msginfo        (MsgInfo *msginfo);
 
+static void compose_close      (Compose *compose);
+
 static GtkItemFactoryEntry compose_popup_entries[] =
 {
        {N_("/_Add..."),        NULL, compose_attach_cb, 0, NULL},
@@ -647,9 +648,8 @@ static GtkItemFactoryEntry compose_entries[] =
                                        NULL, NULL, 0, "<Branch>"},
 #endif
        {N_("/_Options"),               NULL, NULL, 0, "<Branch>"},
-       {N_("/_Options/---"),           NULL, NULL, 0, "<Separator>"},
        {N_("/_Options/Privacy System"),                NULL, NULL,   0, "<Branch>"},
-       {N_("/_Options/Privacy System/None"),   NULL, compose_set_privacy_system_cb,   0, "<RadioItem>"},
+       {N_("/_Options/Privacy System/None"),   NULL, NULL,   0, "<RadioItem>"},
        {N_("/_Options/Si_gn"),         NULL, compose_toggle_sign_cb   , 0, "<ToggleItem>"},
        {N_("/_Options/_Encrypt"),      NULL, compose_toggle_encrypt_cb, 0, "<ToggleItem>"},
        {N_("/_Options/---"),           NULL,           NULL,   0, "<Separator>"},
@@ -676,6 +676,29 @@ static GtkTargetEntry compose_mime_types[] =
        {"text/uri-list", 0, 0}
 };
 
+static gboolean compose_put_existing_to_front(MsgInfo *info)
+{
+       GList *compose_list = compose_get_compose_list();
+       GList *elem = NULL;
+       
+       if (compose_list) {
+               for (elem = compose_list; elem != NULL && elem->data != NULL; 
+                    elem = elem->next) {
+                       Compose *c = (Compose*)elem->data;
+
+                       if (!c->targetinfo || !c->targetinfo->msgid ||
+                           !info->msgid)
+                               continue;
+
+                       if (!strcmp(c->targetinfo->msgid, info->msgid)) {
+                               gtkut_window_popup(c->window);
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
 Compose *compose_new(PrefsAccount *account, const gchar *mailto,
                     GPtrArray *attach_files)
 {
@@ -941,8 +964,8 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        compose = compose_create(account, COMPOSE_REPLY);
        ifactory = gtk_item_factory_from_widget(compose->menubar);
 
-       menu_set_active(ifactory, "/Message/Remove references", FALSE);
-       menu_set_sensitive(ifactory, "/Message/Remove references", TRUE);
+       menu_set_active(ifactory, "/Options/Remove references", FALSE);
+       menu_set_sensitive(ifactory, "/Options/Remove references", TRUE);
 
        compose->replyinfo = procmsg_msginfo_get_full_info(msginfo);
        if (!compose->replyinfo)
@@ -1207,6 +1230,9 @@ void compose_reedit(MsgInfo *msginfo)
        g_return_if_fail(msginfo != NULL);
        g_return_if_fail(msginfo->folder != NULL);
 
+       if (compose_put_existing_to_front(msginfo)) 
+               return;
+
         if (msginfo->folder->stype == F_QUEUE || msginfo->folder->stype == F_DRAFT) {
                gchar queueheader_buf[BUFFSIZE];
                gint id, param;
@@ -1332,7 +1358,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
 
        gtk_widget_grab_focus(compose->header_last->entry);
 
-       filename = procmsg_get_message_file(msginfo);
+       filename = procmsg_get_message_file_path(msginfo);
        if (filename == NULL)
                return NULL;
 
@@ -1364,7 +1390,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
        ifactory = gtk_item_factory_from_widget(compose->popupmenu);
        menu_set_sensitive(ifactory, "/Add...", FALSE);
        menu_set_sensitive(ifactory, "/Remove", FALSE);
-       menu_set_sensitive(ifactory, "/Property...", FALSE);
+       menu_set_sensitive(ifactory, "/Properties...", FALSE);
 
        ifactory = gtk_item_factory_from_widget(compose->menubar);
        menu_set_sensitive(ifactory, "/Message/Save", FALSE);
@@ -1372,10 +1398,7 @@ Compose *compose_redirect(PrefsAccount *account, MsgInfo *msginfo)
        menu_set_sensitive(ifactory, "/Message/Attach file", FALSE);
        menu_set_sensitive(ifactory, "/Message/Insert signature", FALSE);
        menu_set_sensitive(ifactory, "/Edit", FALSE);
-       menu_set_sensitive(ifactory, "/Options/Sign", FALSE);
-       menu_set_sensitive(ifactory, "/Options/Encrypt", FALSE);
-       menu_set_sensitive(ifactory, "/Options/Priority", FALSE);
-       menu_set_sensitive(ifactory, "/Options/Request Return Receipt", FALSE);
+       menu_set_sensitive(ifactory, "/Options", FALSE);
        menu_set_sensitive(ifactory, "/Tools/Show ruler", FALSE);
        menu_set_sensitive(ifactory, "/Tools/Actions", FALSE);
        
@@ -1586,6 +1609,7 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
        };
 
        FILE *fp;
+       gchar buf[BUFFSIZE];
 
        g_return_val_if_fail(msginfo != NULL, -1);
 
@@ -1594,13 +1618,16 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
        fclose(fp);
 
        if (hentry[H_REPLY_TO].body != NULL) {
-               conv_unmime_header_overwrite(hentry[H_REPLY_TO].body);
-               compose->replyto = hentry[H_REPLY_TO].body;
+               conv_unmime_header(buf, sizeof(buf), hentry[H_REPLY_TO].body,
+                                  NULL);
+               compose->replyto = g_strdup(buf);
+               g_free(hentry[H_REPLY_TO].body);
                hentry[H_REPLY_TO].body = NULL;
        }
        if (hentry[H_CC].body != NULL) {
-               conv_unmime_header_overwrite(hentry[H_CC].body);
-               compose->cc = hentry[H_CC].body;
+               conv_unmime_header(buf, sizeof(buf), hentry[H_CC].body, NULL);
+               compose->cc = g_strdup(buf);
+               g_free(hentry[H_CC].body);
                hentry[H_CC].body = NULL;
        }
        if (hentry[H_REFERENCES].body != NULL) {
@@ -1615,20 +1642,22 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
        }
        if (hentry[H_BCC].body != NULL) {
                if (compose->mode == COMPOSE_REEDIT) {
-                       conv_unmime_header_overwrite(hentry[H_BCC].body);
-                       compose->bcc = hentry[H_BCC].body;
-               } else
-                       g_free(hentry[H_BCC].body);
+                       conv_unmime_header
+                               (buf, sizeof(buf), hentry[H_BCC].body, NULL);
+                       compose->bcc = g_strdup(buf);
+               }
+               g_free(hentry[H_BCC].body);
                hentry[H_BCC].body = NULL;
        }
        if (hentry[H_NEWSGROUPS].body != NULL) {
-               conv_unmime_header_overwrite(hentry[H_NEWSGROUPS].body);
                compose->newsgroups = hentry[H_NEWSGROUPS].body;
                hentry[H_NEWSGROUPS].body = NULL;
        }
        if (hentry[H_FOLLOWUP_TO].body != NULL) {
-               conv_unmime_header_overwrite(hentry[H_FOLLOWUP_TO].body);
-               compose->followup_to = hentry[H_FOLLOWUP_TO].body;
+               conv_unmime_header
+                       (buf, sizeof(buf), hentry[H_FOLLOWUP_TO].body, NULL);
+               compose->followup_to = g_strdup(buf);
+               g_free(hentry[H_FOLLOWUP_TO].body);
                hentry[H_FOLLOWUP_TO].body = NULL;
        }
        if (hentry[H_LIST_POST].body != NULL) {
@@ -1664,13 +1693,17 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
                        compose->priority =  priority;
                }
  
-       if (compose->mode == COMPOSE_REEDIT && msginfo->inreplyto)
-               compose->inreplyto = g_strdup(msginfo->inreplyto);
-       else if (compose->mode != COMPOSE_REEDIT &&
-                msginfo->msgid && *msginfo->msgid) {
+       if (compose->mode == COMPOSE_REEDIT) {
+               if (msginfo->inreplyto && *msginfo->inreplyto)
+                       compose->inreplyto = g_strdup(msginfo->inreplyto);
+               return 0;
+       }
+
+       if (msginfo->msgid && *msginfo->msgid)
                compose->inreplyto = g_strdup(msginfo->msgid);
 
-               if (!compose->references) {
+       if (!compose->references) {
+               if (msginfo->msgid && *msginfo->msgid) {
                        if (msginfo->inreplyto && *msginfo->inreplyto)
                                compose->references =
                                        g_strdup_printf("<%s>\n\t<%s>",
@@ -1680,6 +1713,10 @@ static gint compose_parse_header(Compose *compose, MsgInfo *msginfo)
                                compose->references =
                                        g_strconcat("<", msginfo->msgid, ">",
                                                    NULL);
+               } else if (msginfo->inreplyto && *msginfo->inreplyto) {
+                       compose->references =
+                               g_strconcat("<", msginfo->inreplyto, ">",
+                                           NULL);
                }
        }
 
@@ -2141,7 +2178,7 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                        MsgFlags flags = {0, 0};
                        gchar *name;
 
-                       if (procmime_get_encoding_for_file(file) == ENC_7BIT)
+                       if (procmime_get_encoding_for_text_file(file) == ENC_7BIT)
                                ainfo->encoding = ENC_7BIT;
                        else
                                ainfo->encoding = ENC_8BIT;
@@ -2157,8 +2194,7 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                        procmsg_msginfo_free(msginfo);
                } else {
                        if (!g_strncasecmp(content_type, "text", 4))
-                               ainfo->encoding =
-                                       procmime_get_encoding_for_file(file);
+                               ainfo->encoding = procmime_get_encoding_for_text_file(file);
                        else
                                ainfo->encoding = ENC_BASE64;
                        ainfo->name = g_strdup
@@ -2171,11 +2207,18 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                                g_strdup("application/octet-stream");
                        ainfo->encoding = ENC_BASE64;
                } else if (!g_strncasecmp(ainfo->content_type, "text", 4))
-                       ainfo->encoding = procmime_get_encoding_for_file(file);
+                       ainfo->encoding =
+                               procmime_get_encoding_for_text_file(file);
                else
                        ainfo->encoding = ENC_BASE64;
                ainfo->name = g_strdup(g_basename(filename ? filename : file)); 
        }
+
+       if (!strcmp(ainfo->content_type, "unknown")) {
+               g_free(ainfo->content_type);
+               ainfo->content_type = g_strdup("application/octet-stream");
+       }
+
        ainfo->size = size;
 
        text[COL_MIMETYPE] = ainfo->content_type;
@@ -2635,7 +2678,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
        gint ch_len;
        gboolean is_new_line = TRUE, do_delete = FALSE;
        guint i_len = 0;
-       gboolean linewrap_quote = TRUE;
+       gboolean linewrap_quote = prefs_common.linewrap_quote;
        gboolean set_editable_pos = FALSE;
        gint editable_pos = 0;
        gboolean frozen = FALSE;
@@ -2707,7 +2750,6 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                        g_print("l_len=%d wrap_len=%d do_del=%d\n",
                                line_len, linewrap_len, do_delete);
 #endif
-                       /* should we delete to perform smart wrapping */
                        if (line_len < linewrap_len && do_delete) {
                                STEXT_FREEZE();
                                /* get rid of newline */
@@ -2730,13 +2772,21 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                                }
 
                                GET_CHAR(cur_pos, cb, clen);
-
-                               /* insert space if it's alphanumeric */
-                               if ((cur_pos != line_pos) &&
-                                   ((clen > 1) || isalnum((guchar)cb[0]))) {
-                                       gtk_stext_insert(text, NULL, NULL,
-                                                       NULL, " ", 1);
-                                       tlen++;
+                               /* insert space between the next line */
+                               if (cur_pos > 0) {
+                                       gint clen_prev;
+                                       gchar cb_prev[MB_LEN_MAX];
+
+                                       GET_CHAR(cur_pos - 1, cb_prev,
+                                                clen_prev);
+                                       if ((clen_prev != clen && clen > 1) ||
+                                           (clen == 1 &&
+                                            !isspace((guchar)cb[0]))) {
+                                               gtk_stext_insert
+                                                       (text, NULL, NULL,
+                                                        NULL, " ", 1);
+                                               tlen++;
+                                       }
                                }
 
                                /* and start over with current line */
@@ -2996,11 +3046,11 @@ static void compose_select_account(Compose *compose, PrefsAccount *account,
 
 #endif
 
-       if (account->default_sign)
+       if (account->default_sign && compose->mode != COMPOSE_REDIRECT)
                menu_set_active(ifactory, "/Options/Sign", TRUE);
        else
                menu_set_active(ifactory, "/Options/Sign", FALSE);
-       if (account->default_encrypt)
+       if (account->default_encrypt && compose->mode != COMPOSE_REDIRECT)
                menu_set_active(ifactory, "/Options/Encrypt", TRUE);
        else
                menu_set_active(ifactory, "/Options/Encrypt", FALSE);
@@ -3100,7 +3150,7 @@ gint compose_send(Compose *compose)
 
        if (prefs_common.send_dialog_mode != SEND_DIALOG_ALWAYS) {
                compose->sending = FALSE;
-               gtk_widget_destroy(compose->window);
+               compose_close(compose);
                /* No more compose access in the normal codepath 
                 * after this point! */
        }
@@ -3133,8 +3183,17 @@ gint compose_send(Compose *compose)
                folder_item_remove_msg(folder, msgnum);
                folder_item_scan(folder);
                if (prefs_common.send_dialog_mode == SEND_DIALOG_ALWAYS)
-                       gtk_widget_destroy(compose->window);
-       }
+                       compose_close(compose);
+       } else {
+               alertpanel_error(_("The message was queued but could not be "
+                                  "sent.\nUse \"Send queued messages\" from "
+                                  "the main window to retry."));
+               if (prefs_common.send_dialog_mode == SEND_DIALOG_ALWAYS) {
+                       compose_allow_user_actions (compose, TRUE);
+                       compose->sending = FALSE;               
+               }
+               return -1;
+       }
 
        return 0;
 
@@ -3250,7 +3309,7 @@ static gint compose_redirect_write_headers(Compose *compose, FILE *fp)
 
        /* Resent-Message-ID */
        if (compose->account->gen_msgid) {
-               generate_msgid(compose->account->address, buf, sizeof(buf));
+               generate_msgid(buf, sizeof(buf));
                fprintf(fp, "Resent-Message-ID: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
@@ -3382,6 +3441,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
 
                if (action == COMPOSE_WRITE_FOR_SEND) {
                        buf = conv_codeset_strdup(chars, src_codeset, out_codeset);
+                       
                        if (!buf) {
                                AlertValue aval;
                                gchar *msg;
@@ -3410,6 +3470,13 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
        }
        g_free(chars);
 
+       if (encoding == ENC_8BIT || encoding == ENC_7BIT) {
+               if (!strncmp(buf, "From ", sizeof("From ")-1) ||
+                   strstr(buf, "\nFrom ") != NULL) {
+                       encoding = ENC_QUOTED_PRINTABLE;
+               }
+       }
+
        mimetext = procmime_mimeinfo_new();
        mimetext->content = MIMECONTENT_MEM;
        mimetext->data.mem = buf;
@@ -3417,6 +3484,15 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
        mimetext->subtype = g_strdup("plain");
        g_hash_table_insert(mimetext->typeparameters, g_strdup("charset"),
                            g_strdup(out_codeset));
+       /* protect trailing spaces when signing message */
+       if (action == COMPOSE_WRITE_FOR_SEND && compose->use_signing && 
+           privacy_system_can_sign(compose->privacy_system))
+               if (encoding == ENC_7BIT)
+                       encoding = ENC_QUOTED_PRINTABLE;
+               else if (encoding == ENC_8BIT)
+                       encoding = ENC_BASE64;
+       if (encoding != ENC_UNKNOWN)
+               procmime_encode_content(mimetext, encoding);
 
        /* append attachment parts */
        if (compose_use_attach(compose)) {
@@ -3438,12 +3514,15 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
        } else
                g_node_append(mimemsg->node, mimetext->node);
 
-       /* sign message */
-       if (compose->use_signing && privacy_system_can_sign(compose->privacy_system))
-               if (!privacy_sign(compose->privacy_system, mimemsg))
+       /* sign message if sending */
+       if (action == COMPOSE_WRITE_FOR_SEND && compose->use_signing && 
+           privacy_system_can_sign(compose->privacy_system))
+               if (!privacy_sign(compose->privacy_system, mimemsg, compose->account))
                        return -1;
 
        procmime_write_mimeinfo(mimemsg, fp);
+       
+       procmime_mimeinfo_free_all(mimemsg);
 
        return 0;
 }
@@ -3645,7 +3724,9 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                        gchar *encdata;
 
                        encdata = privacy_get_encrypt_data(compose->privacy_system, compose->to_list);
-                       fprintf(fp, "X-Sylpheed-Encrypt-Data:%s\n", encdata);
+                       if (encdata != NULL)
+                               fprintf(fp, "X-Sylpheed-Encrypt-Data:%s\n", 
+                                       encdata);
                        g_free(encdata);
                }
        }
@@ -3750,6 +3831,12 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
                mimepart->length = statbuf.st_size;
 
                type = g_strdup(ainfo->content_type);
+
+               if (!strchr(type, '/')) {
+                       g_free(type);
+                       type = g_strdup("application/octet-stream");
+               }
+
                subtype = strchr(type, '/') + 1;
                *(subtype - 1) = '\0';
                mimepart->type = procmime_get_media_type(type);
@@ -3767,6 +3854,13 @@ static void compose_add_attachments(Compose *compose, MimeInfo *parent)
                        mimepart->disposition = DISPOSITIONTYPE_ATTACHMENT;
                }
 
+               if (compose->use_signing) {
+                       if (ainfo->encoding == ENC_7BIT)
+                               ainfo->encoding = ENC_QUOTED_PRINTABLE;
+                       else if (ainfo->encoding == ENC_8BIT)
+                               ainfo->encoding = ENC_BASE64;
+               }
+               
                procmime_encode_content(mimepart, ainfo->encoding);
 
                g_node_append(parent->node, mimepart->node);
@@ -3926,7 +4020,7 @@ static gchar *compose_get_header(Compose *compose)
 
        /* Message-ID */
        if (compose->account->gen_msgid) {
-               generate_msgid(compose->account->address, buf, sizeof(buf));
+               generate_msgid(buf, sizeof(buf));
                g_string_sprintfa(header, "Message-ID: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
@@ -4604,11 +4698,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                GTK_STEXT(text)->cursor_type = GTK_STEXT_CURSOR_BLOCK;
        }
        
-       if (prefs_common.smart_wrapping) {      
-               gtk_stext_set_word_wrap(GTK_STEXT(text), TRUE);
-               gtk_stext_set_wrap_rmargin(GTK_STEXT(text), prefs_common.linewrap_len);
-       }               
-
        gtk_container_add(GTK_CONTAINER(scrolledwin), text);
 
        gtk_signal_connect(GTK_OBJECT(text), "changed",
@@ -4935,15 +5024,18 @@ static void compose_update_priority_menu_item(Compose * compose)
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
 }      
 
-static void compose_set_privacy_system_cb(gpointer data,
-                                         guint action,
-                                         GtkWidget *widget)
+static void compose_set_privacy_system_cb(GtkWidget *widget, gpointer data)
 {
        Compose *compose = (Compose *) data;
        gchar *systemid;
        GtkItemFactory *ifactory;
        gboolean can_sign = FALSE, can_encrypt = FALSE;
 
+       g_return_if_fail(GTK_IS_CHECK_MENU_ITEM(widget));
+
+       if (!GTK_CHECK_MENU_ITEM(widget)->active)
+               return;
+
        systemid = gtk_object_get_data(GTK_OBJECT(widget), "privacy_system");
        g_free(compose->privacy_system);
        compose->privacy_system = NULL;
@@ -4954,9 +5046,15 @@ static void compose_set_privacy_system_cb(gpointer data,
                can_encrypt = privacy_system_can_encrypt(systemid);
        }
 
+       debug_print("activated privacy system: %s\n", systemid != NULL ? systemid : "None");
+
        ifactory = gtk_item_factory_from_widget(compose->menubar);
        menu_set_sensitive(ifactory, "/Options/Sign", can_sign);
+       if (!can_sign)
+               menu_set_active(ifactory, "/Options/Sign", FALSE);
        menu_set_sensitive(ifactory, "/Options/Encrypt", can_encrypt);
+       if (!can_encrypt)
+               menu_set_active(ifactory, "/Options/Encrypt", FALSE);
 }
 
 static void compose_update_privacy_system_menu_item(Compose * compose)
@@ -5038,18 +5136,18 @@ void compose_update_actions_menu(Compose *compose)
 void compose_update_privacy_systems_menu(Compose *compose)
 {
        static gchar *branch_path = "/Options/Privacy System";
+       static gboolean connected = FALSE;
        GtkItemFactory *ifactory;
        GtkWidget *menuitem;
-       gchar *menu_path;
        GSList *systems, *cur;
        GList *amenu;
-       GtkItemFactoryEntry ifentry = {NULL, NULL, NULL, 0, "<Branch>"};
        GtkWidget *widget;
+       GtkWidget *system_none;
+       GSList *group;
 
        ifactory = gtk_item_factory_from_widget(compose->menubar);
 
        /* remove old entries */
-       ifentry.path = branch_path;
        menuitem = gtk_item_factory_get_widget(ifactory, branch_path);
        g_return_if_fail(menuitem != NULL);
 
@@ -5060,26 +5158,29 @@ void compose_update_privacy_systems_menu(Compose *compose)
                amenu = alist;
        }
 
-       ifentry.accelerator     = NULL;
-       ifentry.callback_action = 0;
-       ifentry.callback        = compose_set_privacy_system_cb;
-       ifentry.item_type       = "/Options/Privacy System/None";
+       system_none = gtk_item_factory_get_widget(ifactory,
+               "/Options/Privacy System/None");
+       if (!connected) {
+               gtk_signal_connect(GTK_OBJECT(system_none), "activate",
+                       GTK_SIGNAL_FUNC(compose_set_privacy_system_cb), compose);
+               connected = TRUE;
+       }
 
        systems = privacy_get_system_ids();
        for (cur = systems; cur != NULL; cur = g_slist_next(cur)) {
                gchar *systemid = cur->data;
 
-               menu_path = g_strdup_printf("%s/%s", branch_path,
-                                           privacy_system_get_name(systemid));
-               ifentry.path = menu_path;
-               gtk_item_factory_create_item(ifactory, &ifentry, compose, 1);
-               widget = gtk_item_factory_get_widget(ifactory, menu_path);
-
+               group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(system_none));
+               widget = gtk_radio_menu_item_new_with_label(group,
+                       privacy_system_get_name(systemid));
                gtk_object_set_data_full(GTK_OBJECT(widget), "privacy_system",
                                         g_strdup(systemid), g_free);
+               gtk_signal_connect(GTK_OBJECT(widget), "activate",
+                       GTK_SIGNAL_FUNC(compose_set_privacy_system_cb), compose);
 
+               gtk_menu_append(GTK_MENU(system_none->parent), widget);
+               gtk_widget_show(widget);
                g_free(systemid);
-               g_free(menu_path);
        }
        g_slist_free(systems);
 }
@@ -5222,7 +5323,9 @@ static void compose_destroy(Compose *compose)
        prefs_common.compose_width = compose->scrolledwin->allocation.width;
        prefs_common.compose_height = compose->window->allocation.height;
 
-       gtk_widget_destroy(compose->paned);
+       if (!compose->paned->parent)
+               gtk_widget_destroy(compose->paned);
+       gtk_widget_destroy(compose->popupmenu);
 
        toolbar_destroy(compose->toolbar);
        g_free(compose->toolbar);
@@ -6005,7 +6108,8 @@ static void compose_send_later_cb(gpointer data, guint action,
        gint val;
 
        val = compose_queue_sub(compose, NULL, NULL, TRUE);
-       if (!val) gtk_widget_destroy(compose->window);
+       if (!val) 
+               compose_close(compose);
 }
 
 void compose_draft (gpointer data) 
@@ -6056,7 +6160,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        }
        fprintf(fp, "X-Sylpheed-Sign:%d\n", compose->use_signing);
        fprintf(fp, "X-Sylpheed-Encrypt:%d\n", compose->use_encryption);
-       fprintf(fp, "X-Sylpheed-Gnupg-Mode:%s\n", compose->privacy_system);
+       fprintf(fp, "X-Sylpheed-Privacy-System:%s\n", compose->privacy_system);
        fprintf(fp, "\n");
 
        if (compose_write_to_file(compose, fp, COMPOSE_WRITE_FOR_STORE) < 0) {
@@ -6098,7 +6202,7 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        lock = FALSE;
 
        if (action == COMPOSE_QUIT_EDITING)
-               gtk_widget_destroy(compose->window);
+               compose_close(compose);
        else {
                struct stat s;
                gchar *path;
@@ -6234,7 +6338,7 @@ static void compose_close_cb(gpointer data, guint action, GtkWidget *widget)
                }
        }
 
-       gtk_widget_destroy(compose->window);
+       compose_close(compose);
 }
 
 static void compose_address_cb(gpointer data, guint action, GtkWidget *widget)
@@ -6437,12 +6541,8 @@ static void compose_toggle_encrypt_cb(gpointer data, guint action,
 
 static void activate_privacy_system(Compose *compose, PrefsAccount *account) 
 {
-       /* TODO
-       if (account->default_gnupg_mode)
-               compose->gnupg_mode = GNUPG_MODE_INLINE;
-       else
-               compose->gnupg_mode = GNUPG_MODE_DETACH;
-       */              
+       g_free(compose->privacy_system);
+       compose->privacy_system = g_strdup(account->default_privacy_system);
        compose_update_privacy_system_menu_item(compose);
 }
 
@@ -6829,6 +6929,17 @@ static PrefsAccount *compose_guess_forward_account_from_msginfo(MsgInfo *msginfo
        return account;
 }
 
+static void compose_close(Compose *compose)
+{
+       gint x, y;
+
+       g_return_if_fail(compose);
+       gtkut_widget_get_uposition(compose->window, &x, &y);
+       prefs_common.compose_x = x;
+       prefs_common.compose_y = y;
+       gtk_widget_destroy(compose->window);
+}
+
 /**
  * Add entry field for each address in list.
  * \param compose     E-Mail composition object.
@@ -6845,7 +6956,44 @@ static void compose_add_field_list( Compose *compose, GList *listAddress ) {
        }
 }
 
+void compose_reply_from_messageview(MessageView *msgview, GSList *msginfo_list, 
+                                   guint action)
+{
+       gchar *body;
+       GSList *new_msglist = NULL;
+       MsgInfo *tmp_msginfo = NULL;
+
+       g_return_if_fail(msgview != NULL);
+
+       g_return_if_fail(msginfo_list != NULL);
+
+       if (g_slist_length(msginfo_list) == 1) {
+               MimeInfo *mimeinfo = messageview_get_selected_mime_part(msgview);
+               MsgInfo *orig_msginfo = (MsgInfo *)msginfo_list->data;
+               
+               if (mimeinfo != NULL && mimeinfo->type == MIMETYPE_MESSAGE && 
+                   !g_strcasecmp(mimeinfo->subtype, "rfc822")) {
+                       
+                       tmp_msginfo = procmsg_msginfo_new_from_mimeinfo(
+                                               orig_msginfo, mimeinfo);
+                       if (tmp_msginfo != NULL) {
+                               new_msglist = g_slist_append(NULL, tmp_msginfo);
+                       } 
+               }
+       }
+
+       body = messageview_get_selection(msgview);
+
+       if (new_msglist) {
+               compose_reply_mode((ComposeMode)action, new_msglist, body);
+               procmsg_msginfo_free(tmp_msginfo);
+               g_slist_free(new_msglist);
+       } else
+               compose_reply_mode((ComposeMode)action, msginfo_list, body);
+
+       g_free(body);
+}
+
 /*
  * End of Source.
  */
-