2005-01-03 [colin] 0.9.13cvs25.5
[claws.git] / src / compose.c
index 9eadf1b5211a1b7087c427ab223daa38c99dd1bc..43b3a761993a8d34ceadbb4b11c01130d3a0669d 100644 (file)
@@ -377,9 +377,9 @@ static void compose_allsel_cb               (Compose        *compose);
 static void compose_advanced_action_cb (Compose                   *compose,
                                         ComposeCallAdvancedAction  action);
 
-static gboolean compose_grab_focus_cb  (GtkWidget      *widget,
+static void compose_grab_focus_cb      (GtkWidget      *widget,
                                         Compose        *compose);
-static gboolean compose_grab_focus_before_cb   (GtkWidget      *widget,
+static void compose_grab_focus_before_cb(GtkWidget     *widget,
                                         Compose        *compose);
 
 static void compose_changed_cb         (GtkTextBuffer  *textbuf,
@@ -418,9 +418,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);
@@ -502,6 +501,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},
@@ -638,7 +639,7 @@ static GtkItemFactoryEntry compose_entries[] =
 #endif
        {N_("/_Options"),               NULL, NULL, 0, "<Branch>"},
        {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>"},
@@ -665,6 +666,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)
 {
@@ -990,18 +1014,13 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        if (account->auto_sig)
                compose_insert_sig(compose, FALSE);
 
-       if (quote && prefs_common.linewrap_quote)
-               compose_wrap_line_all(compose);
-
        cursor_pos = quote_fmt_get_cursor_pos();
        gtk_text_buffer_get_start_iter(textbuf, &iter);
        gtk_text_buffer_get_iter_at_offset(textbuf, &iter, cursor_pos);
        gtk_text_buffer_place_cursor(textbuf, &iter);
-
-       if (quote && prefs_common.linewrap_quote) {
+       
+       if (quote && prefs_common.linewrap_quote)
                compose_wrap_line_all(compose);
-               gtk_text_view_set_editable(GTK_TEXT_VIEW(compose->text), TRUE);
-       }
 
        gtk_widget_grab_focus(compose->text);
 
@@ -1207,6 +1226,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;
@@ -1295,6 +1317,10 @@ void compose_reedit(MsgInfo *msginfo)
        g_signal_handlers_block_by_func(G_OBJECT(textbuf),
                                        G_CALLBACK(compose_changed_cb),
                                        compose);
+                                       
+       g_signal_handlers_block_by_func(G_OBJECT(textbuf),
+                                       G_CALLBACK(text_inserted),
+                                       compose);
 
        if ((fp = procmime_get_first_text_content(msginfo)) == NULL)
                g_warning("Can't get text part\n");
@@ -1302,12 +1328,16 @@ void compose_reedit(MsgInfo *msginfo)
                while (fgets(buf, sizeof(buf), fp) != NULL) {
                        strcrchomp(buf);
                        gtk_text_buffer_insert(textbuf, &iter, buf, -1);
+                       gtk_text_buffer_get_iter_at_mark(textbuf, &iter, mark);
                }
                fclose(fp);
        }
        
        compose_attach_parts(compose, msginfo);
 
+       g_signal_handlers_unblock_by_func(G_OBJECT(textbuf),
+                                       G_CALLBACK(text_inserted),
+                                       compose);
        g_signal_handlers_unblock_by_func(G_OBJECT(textbuf),
                                        G_CALLBACK(compose_changed_cb),
                                        compose);
@@ -2210,14 +2240,14 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                        MsgInfo *msginfo;
                        MsgFlags flags = {0, 0};
 
-                       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;
 
                        msginfo = procheader_parse_file(file, flags, FALSE, FALSE);
                        if (msginfo && msginfo->subject)
-                               name = msginfo->subject;
+                               name = g_strdup(msginfo->subject);
                        else
                                name = g_path_get_basename(filename ? filename : file);
 
@@ -2226,8 +2256,7 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                        procmsg_msginfo_free(msginfo);
                } else {
                        if (!g_ascii_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;
                        name = g_path_get_basename(filename ? filename : file);
@@ -2241,7 +2270,8 @@ static void compose_attach_append(Compose *compose, const gchar *file,
                                g_strdup("application/octet-stream");
                        ainfo->encoding = ENC_BASE64;
                } else if (!g_ascii_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;
                name = g_path_get_basename(filename ? filename : file);
@@ -2591,16 +2621,17 @@ static void compose_wrap_line(Compose *compose)
 #undef WRAP_DEBUG
 #ifdef WRAP_DEBUG
 /* Darko: used when I debug wrapping */
-void dump_text(GtkTextBuffer textbuf, int pos, int tlen, int breakoncr)
+void dump_text(GtkTextBuffer *textbuf, int pos, int tlen, int breakoncr)
 {
        gint i, clen;
        gchar cbuf[CHAR_BUF_SIZE];
+       GtkTextIter iter, end_iter;
 
        printf("%d [", pos);
        gtk_text_buffer_get_iter_at_offset(textbuf, &iter, pos);
        gtk_text_buffer_get_iter_at_offset(textbuf, &end_iter, pos + tlen);
        for (; gtk_text_iter_forward_char(&iter) &&
-                    gtk_text_iter_compare(&iter, &end_iter) < 0;)
+                    gtk_text_iter_compare(&iter, &end_iter) < 0;) {
                GET_CHAR(&iter, cbuf, clen);
                if (clen < 0) break;
                if (breakoncr && clen == 1 && cbuf[0] == '\n')
@@ -2793,7 +2824,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;
        guint linewrap_len = prefs_common.linewrap_len;
@@ -2907,7 +2938,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                                is_new_line = TRUE;
 #ifdef WRAP_DEBUG
                                g_print("after delete l_pos=");
-                               dump_text(text, line_pos, tlen, 1);
+                               dump_text(textbuf, line_pos, tlen, 1);
 #endif
                                /* move beginning of line if we are on LF */
                                gtk_text_buffer_get_iter_at_offset(textbuf,
@@ -2948,8 +2979,8 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
 
 #ifdef WRAP_DEBUG
                        g_print("should wrap cur_pos=%d ", cur_pos);
-                       dump_text(text, p_pos, tlen, 1);
-                       dump_text(text, line_pos, tlen, 1);
+                       dump_text(textbuf, p_pos, tlen, 1);
+                       dump_text(textbuf, line_pos, tlen, 1);
 #endif
                        /* force wrapping if it is one long word but not URL */
                        if (line_pos - p_pos <= i_len)
@@ -3001,7 +3032,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                            gtkut_text_buffer_is_uri_string(textbuf, line_pos, tlen)) {
 #ifdef WRAP_DEBUG
                                g_print("found URL at ");
-                               dump_text(text, line_pos, tlen, 1);
+                               dump_text(textbuf, line_pos, tlen, 1);
 #endif
                                continue;
                        }
@@ -3027,8 +3058,8 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                                do_delete = FALSE;
 #ifdef WRAP_DEBUG
                        g_print("after CR insert ");
-                       dump_text(text, line_pos, tlen, 1);
-                       dump_text(text, cur_pos, tlen, 1);
+                       dump_text(textbuf, line_pos, tlen, 1);
+                       dump_text(textbuf, cur_pos, tlen, 1);
 #endif
 
                        /* should we insert quotation ? */
@@ -3048,7 +3079,7 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                                        }
 #ifdef WRAP_DEBUG
                                        g_print("after quote insert ");
-                                       dump_text(text, line_pos, tlen, 1);
+                                       dump_text(textbuf, line_pos, tlen, 1);
 #endif
                                }
                        }
@@ -3278,7 +3309,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! */
        }
@@ -3311,8 +3342,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;
 
@@ -3429,7 +3469,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);
        }
@@ -3601,6 +3641,10 @@ 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))
+               encoding = ENC_QUOTED_PRINTABLE;
        if (encoding != ENC_UNKNOWN)
                procmime_encode_content(mimetext, encoding);
 
@@ -3627,7 +3671,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action)
        /* 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))
+               if (!privacy_sign(compose->privacy_system, mimemsg, compose->account))
                        return -1;
 
        procmime_write_mimeinfo(mimemsg, fp);
@@ -3844,7 +3888,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);
                }
        }
@@ -4112,27 +4158,20 @@ static gchar *compose_get_header(Compose *compose)
        compose_add_headerfield_from_headerlist(compose, header, "Bcc", ", ");
 
        /* Subject */
-       str = (gpointer)gtk_entry_get_text(GTK_ENTRY(compose->subject_entry));
+       str = gtk_editable_get_chars(GTK_EDITABLE(compose->subject_entry), 0, -1);
        if (*str != '\0' && !IS_IN_CUSTOM_HEADER("Subject")) {
-               gchar *tmpstr;
-
-               tmpstr = g_strdup(str);
-               if (tmpstr == NULL) {
-                       g_string_free(header, TRUE);
-                       return NULL;
-               }
                g_strstrip(str);
                if (*str != '\0') {
                        compose_convert_header(buf, sizeof(buf), str,
                                               strlen("Subject: "), FALSE);
                        g_string_append_printf(header, "Subject: %s\n", buf);
                }
-               g_free(tmpstr);
        }
+       g_free(str);
 
        /* Message-ID */
        if (compose->account->gen_msgid) {
-               generate_msgid(compose->account->address, buf, sizeof(buf));
+               generate_msgid(buf, sizeof(buf));
                g_string_append_printf(header, "Message-ID: <%s>\n", buf);
                compose->msgid = g_strdup(buf);
        }
@@ -5154,15 +5193,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 = g_object_get_data(G_OBJECT(widget), "privacy_system");
        g_free(compose->privacy_system);
        compose->privacy_system = NULL;
@@ -5173,6 +5215,8 @@ 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);
        menu_set_sensitive(ifactory, "/Options/Encrypt", can_encrypt);
@@ -5257,18 +5301,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);
 
@@ -5279,26 +5323,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) {
+               g_signal_connect(G_OBJECT(system_none), "activate",
+                       G_CALLBACK(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_get_group(GTK_RADIO_MENU_ITEM(system_none));
+               widget = gtk_radio_menu_item_new_with_label(group,
+                       privacy_system_get_name(systemid));
                g_object_set_data_full(G_OBJECT(widget), "privacy_system",
                                       g_strdup(systemid), g_free);
+               g_signal_connect(G_OBJECT(widget), "activate",
+                       G_CALLBACK(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);
 }
@@ -5352,7 +5399,7 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
                compose_entry_append(compose, tmpl->bcc, COMPOSE_BCC);
 
        if (replace)
-               gtk_text_buffer_set_text(buffer, "\0", 1);
+               gtk_text_buffer_set_text(buffer, "", -1);
 
        mark = gtk_text_buffer_get_insert(buffer);
        gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
@@ -5955,7 +6002,7 @@ static void compose_input_cb(gpointer data, gint source,
                GtkTextView *text = GTK_TEXT_VIEW(compose->text);
                GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
 
-               gtk_text_buffer_set_text(buffer, "\0", 1);
+               gtk_text_buffer_set_text(buffer, "", -1);
                compose_insert_file(compose, compose->exteditor_file);
                compose_changed_cb(NULL, compose);
 
@@ -6230,7 +6277,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) 
@@ -6281,7 +6329,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) {
@@ -6323,7 +6371,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;
@@ -6459,7 +6507,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)
@@ -6902,19 +6950,20 @@ static void compose_advanced_action_cb(Compose *compose,
 
 static gchar *cliptext = NULL;
 
-static gboolean compose_grab_focus_before_cb(GtkWidget *widget, Compose *compose)
+static void compose_grab_focus_before_cb(GtkWidget *widget, Compose *compose)
 {
        gchar *str = NULL;
        GtkClipboard *clip = gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE));
-       if (cliptext)
+       if (cliptext) {
                g_free(cliptext);
+               cliptext = NULL;
+       }
+
        if (gtk_clipboard_wait_is_text_available(clip))
                cliptext = gtk_clipboard_wait_for_text(clip);
-       
-       return FALSE;
 }
 
-static gboolean compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
+static void compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
 {
        gchar *str = NULL;
        GtkClipboard *clip = gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE));
@@ -6930,8 +6979,6 @@ static gboolean compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
 
        if (GTK_IS_EDITABLE(widget) || GTK_IS_TEXT_VIEW(widget))
                compose->focused_editable = widget;
-       
-       return TRUE;
 }
 
 static void compose_changed_cb(GtkTextBuffer *textbuf, Compose *compose)
@@ -7357,6 +7404,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.