[evolution] Bug 781790 - Configure signature and start cursor position per account



commit aa94d04c12ff007e874f4f97476b9ab447bc8ead
Author: Milan Crha <mcrha redhat com>
Date:   Tue Jul 4 18:33:45 2017 +0200

    Bug 781790 - Configure signature and start cursor position per account

 po/POTFILES.in                                     |    1 +
 src/composer/e-msg-composer.c                      |   10 +
 src/e-util/e-content-editor.c                      |  116 ++++
 src/e-util/e-content-editor.h                      |   11 +
 src/mail/CMakeLists.txt                            |    2 +
 src/mail/e-mail-config-composing-page.c            |  632 ++++++++++++++++++++
 src/mail/e-mail-config-composing-page.h            |   71 +++
 src/mail/e-mail-config-defaults-page.c             |  336 -----------
 src/mail/e-mail-config-defaults-page.h             |    2 +-
 src/mail/e-mail-config-notebook.c                  |   22 +-
 src/mail/mail-config.ui                            |   10 +-
 src/modules/webkit-editor/e-webkit-editor.c        |  108 ++++-
 .../web-extension/e-composer-dom-functions.c       |   33 +-
 .../web-extension/e-composer-dom-functions.h       |    4 +-
 .../web-extension/e-editor-dom-functions.c         |   21 +-
 .../web-extension/e-editor-dom-functions.h         |    4 +-
 .../webkit-editor/web-extension/e-editor-page.c    |   17 +-
 .../webkit-editor/web-extension/e-editor-page.h    |    8 +-
 .../web-extension/e-editor-web-extension.c         |   27 +-
 19 files changed, 1052 insertions(+), 383 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 23058f7..7dd8e09 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -319,6 +319,7 @@ src/mail/e-mail-backend.c
 src/mail/e-mail-browser.c
 src/mail/e-mail-config-assistant.c
 src/mail/e-mail-config-auth-check.c
+src/mail/e-mail-config-composing-page.c
 src/mail/e-mail-config-confirm-page.c
 src/mail/e-mail-config-defaults-page.c
 src/mail/e-mail-config-identity-page.c
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index 9b7a0c1..62b7de1 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -1632,6 +1632,7 @@ msg_composer_mail_identity_changed_cb (EMsgComposer *composer)
        ESourceOpenPGP *pgp;
        ESourceSMIME *smime;
        EComposerHeaderTable *table;
+       EContentEditor *cnt_editor;
        GtkToggleAction *action;
        ESource *source;
        gboolean active;
@@ -1646,11 +1647,15 @@ msg_composer_mail_identity_changed_cb (EMsgComposer *composer)
        const gchar *active_signature_id;
        gchar *uid, *alias_name = NULL, *alias_address = NULL, *pgp_keyid, *smime_cert;
 
+       cnt_editor = e_html_editor_get_content_editor (e_msg_composer_get_editor (composer));
        table = e_msg_composer_get_header_table (composer);
        uid = e_composer_header_table_dup_identity_uid (table, &alias_name, &alias_address);
 
        /* Silently return if no identity is selected. */
        if (!uid) {
+               e_content_editor_set_start_bottom (cnt_editor, E_THREE_STATE_INCONSISTENT);
+               e_content_editor_set_top_signature (cnt_editor, E_THREE_STATE_INCONSISTENT);
+
                g_free (alias_name);
                g_free (alias_address);
                return;
@@ -1662,6 +1667,11 @@ msg_composer_mail_identity_changed_cb (EMsgComposer *composer)
        extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
        mc = e_source_get_extension (source, extension_name);
 
+       e_content_editor_set_start_bottom (cnt_editor,
+               e_source_mail_composition_get_start_bottom (mc));
+       e_content_editor_set_top_signature (cnt_editor,
+               e_source_mail_composition_get_top_signature (mc));
+
        extension_name = E_SOURCE_EXTENSION_OPENPGP;
        pgp = e_source_get_extension (source, extension_name);
        pgp_keyid = e_source_openpgp_dup_key_id (pgp);
diff --git a/src/e-util/e-content-editor.c b/src/e-util/e-content-editor.c
index d70492d..ca5f416 100644
--- a/src/e-util/e-content-editor.c
+++ b/src/e-util/e-content-editor.c
@@ -392,6 +392,44 @@ e_content_editor_default_init (EContentEditorInterface *iface)
                        G_PARAM_STATIC_STRINGS));
 
        /**
+        * EContentEditor:start-bottom
+        *
+        * Holds where the cursor should be positioned after body of
+        * a reply or forward is loaded.
+        *
+        * Since: 3.26
+        */
+       g_object_interface_install_property (
+               iface,
+               g_param_spec_enum (
+                       "start-bottom",
+                       NULL,
+                       NULL,
+                       E_TYPE_THREE_STATE,
+                       E_THREE_STATE_INCONSISTENT,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS));
+
+       /**
+        * EContentEditor:top-signature
+        *
+        * Holds where the signature should be positioned after body of
+        * a reply or forward is loaded.
+        *
+        * Since: 3.26
+        */
+       g_object_interface_install_property (
+               iface,
+               g_param_spec_enum (
+                       "top-signature",
+                       NULL,
+                       NULL,
+                       E_TYPE_THREE_STATE,
+                       E_THREE_STATE_INCONSISTENT,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS));
+
+       /**
         * EContentEditor:spell-check-enabled
         *
         * Holds whether the spell checking is enabled.
@@ -1253,6 +1291,84 @@ e_content_editor_is_underline (EContentEditor *editor)
 }
 
 /**
+ * e_content_editor_set_start_bottom:
+ * @editor: an #EContentEditor
+ * @value: an #EThreeState value to set
+ *
+ * Changes start-bottom property, which is used to position
+ * cursor after setting message body in replies and forwards.
+ *
+ * Since: 3.26
+ **/
+void
+e_content_editor_set_start_bottom (EContentEditor *editor,
+                                  EThreeState value)
+{
+       g_return_if_fail (E_IS_CONTENT_EDITOR (editor));
+
+       g_object_set (G_OBJECT (editor), "start-bottom", value, NULL);
+}
+
+/**
+ * e_content_editor_get_start_bottom:
+ * @editor: an #EContentEditor
+ *
+ * Returns: the current value of start-bottom property.
+ *
+ * Since: 3.26
+ **/
+EThreeState
+e_content_editor_get_start_bottom (EContentEditor *editor)
+{
+       EThreeState value = E_THREE_STATE_INCONSISTENT;
+
+       g_return_val_if_fail (E_IS_CONTENT_EDITOR (editor), FALSE);
+
+       g_object_get (G_OBJECT (editor), "start-bottom", &value, NULL);
+
+       return value;
+}
+
+/**
+ * e_content_editor_set_top_signature:
+ * @editor: an #EContentEditor
+ * @value: an #EThreeState value to set
+ *
+ * Changes top-signature property, which is used to position
+ * signature after setting message body in replies and forwards.
+ *
+ * Since: 3.26
+ **/
+void
+e_content_editor_set_top_signature (EContentEditor *editor,
+                                   EThreeState value)
+{
+       g_return_if_fail (E_IS_CONTENT_EDITOR (editor));
+
+       g_object_set (G_OBJECT (editor), "top-signature", value, NULL);
+}
+
+/**
+ * e_content_editor_get_top_signature:
+ * @editor: an #EContentEditor
+ *
+ * Returns: the current value of top-signature property.
+ *
+ * Since: 3.26
+ **/
+EThreeState
+e_content_editor_get_top_signature (EContentEditor *editor)
+{
+       EThreeState value = E_THREE_STATE_INCONSISTENT;
+
+       g_return_val_if_fail (E_IS_CONTENT_EDITOR (editor), FALSE);
+
+       g_object_get (G_OBJECT (editor), "top-signature", &value, NULL);
+
+       return value;
+}
+
+/**
  * e_content_editor_setup_editor:
  * @content_editor: an #EContentEditor
  * @callback: an #EContentEditorInitializedCallback function
diff --git a/src/e-util/e-content-editor.h b/src/e-util/e-content-editor.h
index 8db2a6f..4497570 100644
--- a/src/e-util/e-content-editor.h
+++ b/src/e-util/e-content-editor.h
@@ -25,6 +25,7 @@
 #include <gtk/gtk.h>
 
 #include <camel/camel.h>
+#include <libedataserver/libedataserver.h>
 
 #include <e-util/e-emoticon.h>
 #include <e-util/e-spell-checker.h>
@@ -513,6 +514,16 @@ gboolean   e_content_editor_is_superscript
 void           e_content_editor_set_underline  (EContentEditor *editor,
                                                 gboolean underline);
 gboolean       e_content_editor_is_underline   (EContentEditor *editor);
+void           e_content_editor_set_start_bottom
+                                               (EContentEditor *editor,
+                                                EThreeState value);
+EThreeState    e_content_editor_get_start_bottom
+                                               (EContentEditor *editor);
+void           e_content_editor_set_top_signature
+                                               (EContentEditor *editor,
+                                                EThreeState value);
+EThreeState    e_content_editor_get_top_signature
+                                               (EContentEditor *editor);
 
 /* Methods */
 void           e_content_editor_initialize     (EContentEditor *content_editor,
diff --git a/src/mail/CMakeLists.txt b/src/mail/CMakeLists.txt
index a661b35..8520008 100644
--- a/src/mail/CMakeLists.txt
+++ b/src/mail/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SOURCES
        e-mail-config-activity-page.c
        e-mail-config-assistant.c
        e-mail-config-auth-check.c
+       e-mail-config-composing-page.c
        e-mail-config-confirm-page.c
        e-mail-config-defaults-page.c
        e-mail-config-identity-page.c
@@ -128,6 +129,7 @@ set(HEADERS
        e-mail-config-activity-page.h
        e-mail-config-assistant.h
        e-mail-config-auth-check.h
+       e-mail-config-composing-page.h
        e-mail-config-confirm-page.h
        e-mail-config-defaults-page.h
        e-mail-config-identity-page.h
diff --git a/src/mail/e-mail-config-composing-page.c b/src/mail/e-mail-config-composing-page.c
new file mode 100644
index 0000000..3fc89f1
--- /dev/null
+++ b/src/mail/e-mail-config-composing-page.c
@@ -0,0 +1,632 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/libedataserver.h>
+
+#include "e-mail-config-page.h"
+#include "e-mail-config-activity-page.h"
+
+#include "e-mail-config-composing-page.h"
+
+struct _EMailConfigComposingPagePrivate {
+       ESource *identity_source;
+};
+
+enum {
+       PROP_0,
+       PROP_IDENTITY_SOURCE
+};
+
+/* Forward Declarations */
+static void    e_mail_config_composing_page_interface_init
+                                       (EMailConfigPageInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EMailConfigComposingPage, e_mail_config_composing_page, 
E_TYPE_MAIL_CONFIG_ACTIVITY_PAGE,
+       G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)
+       G_IMPLEMENT_INTERFACE (E_TYPE_MAIL_CONFIG_PAGE, e_mail_config_composing_page_interface_init))
+
+static gboolean
+mail_config_composing_page_addrs_to_string (GBinding *binding,
+                                           const GValue *source_value,
+                                           GValue *target_value,
+                                           gpointer unused)
+{
+       gchar **strv;
+
+       strv = g_value_dup_boxed (source_value);
+
+       if (strv != NULL) {
+               gchar *string = g_strjoinv ("; ", strv);
+               g_value_set_string (target_value, string);
+               g_free (string);
+       } else {
+               g_value_set_string (target_value, "");
+       }
+
+       g_strfreev (strv);
+
+       return TRUE;
+}
+
+static gboolean
+mail_config_composing_page_string_to_addrs (GBinding *binding,
+                                           const GValue *source_value,
+                                           GValue *target_value,
+                                           gpointer unused)
+{
+       CamelInternetAddress *address;
+       const gchar *string;
+       gchar **strv;
+       gint n_addresses, ii;
+
+       string = g_value_get_string (source_value);
+
+       address = camel_internet_address_new ();
+       n_addresses = camel_address_decode (CAMEL_ADDRESS (address), string);
+
+       if (n_addresses < 0) {
+               g_object_unref (address);
+               return FALSE;
+
+       } else if (n_addresses == 0) {
+               g_value_set_boxed (target_value, NULL);
+               g_object_unref (address);
+               return TRUE;
+       }
+
+       strv = g_new0 (gchar *, n_addresses + 1);
+
+       for (ii = 0; ii < n_addresses; ii++) {
+               const gchar *name = NULL;
+               const gchar *addr = NULL;
+
+               camel_internet_address_get (address, ii, &name, &addr);
+               strv[ii] = camel_internet_address_format_address (name, addr);
+       }
+
+       g_value_take_boxed (target_value, strv);
+
+       return TRUE;
+}
+
+static void
+mail_config_composing_fill_reply_style_combox (GtkComboBoxText *combo)
+{
+       struct _values {
+               ESourceMailCompositionReplyStyle reply_style;
+               const gchar *display_name;
+       } values[] = {
+               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DEFAULT,
+                 NC_("ReplyForward", "Use global setting") },
+               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_ATTACH,
+                 NC_("ReplyForward", "Attachment") },
+               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_OUTLOOK,
+                 NC_("ReplyForward", "Inline (Outlook style)") },
+               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_QUOTED,
+                 NC_("ReplyForward", "Quoted") },
+               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DO_NOT_QUOTE,
+                 NC_("ReplyForward", "Do Not Quote") }
+       };
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+       gint ii;
+
+       g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo));
+
+       enum_class = g_type_class_ref (E_TYPE_SOURCE_MAIL_COMPOSITION_REPLY_STYLE);
+       g_return_if_fail (enum_class != NULL);
+
+       g_warn_if_fail (enum_class->n_values == G_N_ELEMENTS (values));
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               enum_value = g_enum_get_value (enum_class, values[ii].reply_style);
+               g_warn_if_fail (enum_value != NULL);
+
+               if (enum_value) {
+                       gtk_combo_box_text_append (combo,
+                               enum_value->value_name,
+                               g_dpgettext2 (GETTEXT_PACKAGE, "ReplyForward", values[ii].display_name));
+               }
+       }
+
+       g_type_class_unref (enum_class);
+}
+
+static gboolean
+mail_config_composing_page_reply_style_to_string (GBinding *binding,
+                                                const GValue *source_value,
+                                                GValue *target_value,
+                                                gpointer data)
+{
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+
+       enum_class = g_type_class_ref (E_TYPE_SOURCE_MAIL_COMPOSITION_REPLY_STYLE);
+       g_return_val_if_fail (enum_class != NULL, FALSE);
+
+       enum_value = g_enum_get_value (enum_class, g_value_get_enum (source_value));
+       g_return_val_if_fail (enum_value != NULL, FALSE);
+
+       g_value_set_string (target_value, enum_value->value_name);
+
+       g_type_class_unref (enum_class);
+
+       return TRUE;
+}
+
+static gboolean
+mail_config_composing_page_string_to_reply_style (GBinding *binding,
+                                                const GValue *source_value,
+                                                GValue *target_value,
+                                                gpointer data)
+{
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+       const gchar *value_name;
+
+       enum_class = g_type_class_ref (E_TYPE_SOURCE_MAIL_COMPOSITION_REPLY_STYLE);
+       g_return_val_if_fail (enum_class != NULL, FALSE);
+
+       value_name = g_value_get_string (source_value);
+       if (!value_name || !*value_name) {
+               enum_value = NULL;
+       } else {
+               enum_value = g_enum_get_value_by_name (enum_class, value_name);
+       }
+       if (!enum_value)
+               g_value_set_enum (target_value, E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DEFAULT);
+       else
+               g_value_set_enum (target_value, enum_value->value);
+
+       g_warn_if_fail (enum_value != NULL);
+
+       g_type_class_unref (enum_class);
+
+       return TRUE;
+}
+
+static void
+mail_config_composing_page_set_identity_source (EMailConfigComposingPage *page,
+                                               ESource *identity_source)
+{
+       g_return_if_fail (E_IS_SOURCE (identity_source));
+       g_return_if_fail (page->priv->identity_source == NULL);
+
+       page->priv->identity_source = g_object_ref (identity_source);
+}
+
+static void
+mail_config_composing_page_set_property (GObject *object,
+                                        guint property_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_IDENTITY_SOURCE:
+                       mail_config_composing_page_set_identity_source (
+                               E_MAIL_CONFIG_COMPOSING_PAGE (object),
+                               g_value_get_object (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_composing_page_get_property (GObject *object,
+                                        guint property_id,
+                                        GValue *value,
+                                        GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_IDENTITY_SOURCE:
+                       g_value_set_object (
+                               value,
+                               e_mail_config_composing_page_get_identity_source (
+                               E_MAIL_CONFIG_COMPOSING_PAGE (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_config_composing_page_dispose (GObject *object)
+{
+       EMailConfigComposingPage *page = E_MAIL_CONFIG_COMPOSING_PAGE (object);
+
+       g_clear_object (&page->priv->identity_source);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_mail_config_composing_page_parent_class)->dispose (object);
+}
+
+typedef struct _ThreeStateData {
+       GObject *composition_ext;
+       gchar *property_name;
+       gulong handler_id;
+} ThreeStateData;
+
+static void
+three_state_data_free (gpointer data,
+                      GClosure *closure)
+{
+       ThreeStateData *tsd = data;
+
+       if (tsd) {
+               g_clear_object (&tsd->composition_ext);
+               g_free (tsd->property_name);
+               g_free (tsd);
+       }
+}
+
+static void
+mail_config_composing_page_three_state_toggled_cb (GtkToggleButton *widget,
+                                                  gpointer user_data)
+{
+       ThreeStateData *tsd = user_data;
+       CamelThreeState set_to;
+
+       g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
+       g_return_if_fail (tsd != NULL);
+
+       g_signal_handler_block (widget, tsd->handler_id);
+
+       if (gtk_toggle_button_get_inconsistent (widget) &&
+           gtk_toggle_button_get_active (widget)) {
+               gtk_toggle_button_set_active (widget, FALSE);
+               gtk_toggle_button_set_inconsistent (widget, FALSE);
+               set_to = CAMEL_THREE_STATE_OFF;
+       } else if (!gtk_toggle_button_get_active (widget)) {
+               gtk_toggle_button_set_inconsistent (widget, TRUE);
+               gtk_toggle_button_set_active (widget, FALSE);
+               set_to = CAMEL_THREE_STATE_INCONSISTENT;
+       } else {
+               set_to = CAMEL_THREE_STATE_ON;
+       }
+
+       g_object_set (tsd->composition_ext, tsd->property_name, set_to, NULL);
+
+       g_signal_handler_unblock (widget, tsd->handler_id);
+}
+
+static void
+mail_config_composing_page_setup_three_state_value (ESourceMailComposition *composition_ext,
+                                                   const gchar *property_name,
+                                                   GtkWidget *check_button)
+{
+       ThreeStateData *tsd;
+       gboolean set_inconsistent = FALSE, set_active = FALSE;
+       EThreeState value = E_THREE_STATE_INCONSISTENT;
+
+       g_return_if_fail (E_IS_SOURCE_MAIL_COMPOSITION (composition_ext));
+       g_return_if_fail (property_name != NULL);
+       g_return_if_fail (GTK_IS_TOGGLE_BUTTON (check_button));
+
+       tsd = g_new0 (ThreeStateData, 1);
+       tsd->composition_ext = g_object_ref (composition_ext);
+       tsd->property_name = g_strdup (property_name);
+
+       g_object_get (tsd->composition_ext, tsd->property_name, &value, NULL);
+
+       switch (value) {
+               case CAMEL_THREE_STATE_ON:
+                       set_inconsistent = FALSE;
+                       set_active = TRUE;
+                       break;
+               case CAMEL_THREE_STATE_OFF:
+                       set_inconsistent = FALSE;
+                       set_active = FALSE;
+                       break;
+               case CAMEL_THREE_STATE_INCONSISTENT:
+                       set_inconsistent = TRUE;
+                       set_active = FALSE;
+                       break;
+       }
+
+       g_object_set (G_OBJECT (check_button),
+               "inconsistent", set_inconsistent,
+               "active", set_active,
+               NULL);
+
+       tsd->handler_id = g_signal_connect_data (check_button, "toggled",
+               G_CALLBACK (mail_config_composing_page_three_state_toggled_cb),
+               tsd, three_state_data_free, 0);
+}
+
+static void
+mail_config_composing_page_constructed (GObject *object)
+{
+       EMailConfigComposingPage *page;
+       ESource *source;
+       ESourceMailComposition *composition_ext;
+       ESourceMDN *mdn_ext;
+       GtkLabel *label;
+       GtkWidget *widget;
+       GtkWidget *container;
+       GtkWidget *main_box;
+       GtkSizeGroup *size_group;
+       GEnumClass *enum_class;
+       GEnumValue *enum_value;
+       EMdnResponsePolicy policy;
+       const gchar *text;
+       gchar *markup;
+
+       page = E_MAIL_CONFIG_COMPOSING_PAGE (object);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_mail_config_composing_page_parent_class)->constructed (object);
+
+       source = e_mail_config_composing_page_get_identity_source (page);
+
+       composition_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION);
+       mdn_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MDN);
+
+       main_box = e_mail_config_activity_page_get_internal_box (E_MAIL_CONFIG_ACTIVITY_PAGE (page));
+
+       gtk_box_set_spacing (GTK_BOX (main_box), 12);
+
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+       /*** Composing Messages ***/
+
+       widget = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+       gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+       gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       text = _("Composing Messages");
+       markup = g_markup_printf_escaped ("<b>%s</b>", text);
+       widget = gtk_label_new (markup);
+       gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
+       gtk_widget_show (widget);
+       g_free (markup);
+
+       text = _("Alway_s carbon-copy (cc) to:");
+       widget = gtk_label_new_with_mnemonic (text);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+       gtk_widget_show (widget);
+
+       label = GTK_LABEL (widget);
+
+       widget = gtk_entry_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
+       gtk_widget_show (widget);
+
+       e_binding_bind_property_full (
+               composition_ext, "cc",
+               widget, "text",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE,
+               mail_config_composing_page_addrs_to_string,
+               mail_config_composing_page_string_to_addrs,
+               NULL, (GDestroyNotify) NULL);
+
+       text = _("Always _blind carbon-copy (bcc) to:");
+       widget = gtk_label_new_with_mnemonic (text);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1);
+       gtk_widget_show (widget);
+
+       label = GTK_LABEL (widget);
+
+       widget = gtk_entry_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1);
+       gtk_widget_show (widget);
+
+       e_binding_bind_property_full (
+               composition_ext, "bcc",
+               widget, "text",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE,
+               mail_config_composing_page_addrs_to_string,
+               mail_config_composing_page_string_to_addrs,
+               NULL, (GDestroyNotify) NULL);
+
+       widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 1, 1);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       text = _("Re_ply style:");
+       widget = gtk_label_new_with_mnemonic (text);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       label = GTK_LABEL (widget);
+
+       widget = gtk_combo_box_text_new ();
+       gtk_widget_set_hexpand (widget, FALSE);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       mail_config_composing_fill_reply_style_combox (GTK_COMBO_BOX_TEXT (widget));
+
+       e_binding_bind_property_full (
+               composition_ext, "reply-style",
+               widget, "active-id",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE,
+               mail_config_composing_page_reply_style_to_string,
+               mail_config_composing_page_string_to_reply_style,
+               NULL, (GDestroyNotify) NULL);
+
+       widget = gtk_check_button_new_with_mnemonic (_("Start _typing at the bottom"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       mail_config_composing_page_setup_three_state_value (composition_ext, "start-bottom", widget);
+
+       widget = gtk_check_button_new_with_mnemonic (_("_Keep signature above the original message"));
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       mail_config_composing_page_setup_three_state_value (composition_ext, "top-signature", widget);
+
+       /*** Message Receipts ***/
+
+       widget = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
+       gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
+       gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
+       gtk_widget_show (widget);
+
+       container = widget;
+
+       text = _("Message Receipts");
+       markup = g_markup_printf_escaped ("<b>%s</b>", text);
+       widget = gtk_label_new (markup);
+       gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
+       gtk_widget_show (widget);
+       g_free (markup);
+
+       text = _("S_end message receipts:");
+       widget = gtk_label_new_with_mnemonic (text);
+       gtk_widget_set_margin_left (widget, 12);
+       gtk_size_group_add_widget (size_group, widget);
+       gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
+       gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
+       gtk_widget_show (widget);
+
+       label = GTK_LABEL (widget);
+
+       widget = gtk_combo_box_text_new ();
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_label_set_mnemonic_widget (label, widget);
+       gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
+       gtk_widget_show (widget);
+
+       /* XXX This is a pain in the butt, but we want to avoid hard-coding
+        *     string values from the EMdnResponsePolicy enum class in case
+        *     they change in the future. */
+       enum_class = g_type_class_ref (E_TYPE_MDN_RESPONSE_POLICY);
+       policy = E_MDN_RESPONSE_POLICY_NEVER;
+       enum_value = g_enum_get_value (enum_class, policy);
+       g_return_if_fail (enum_value != NULL);
+       gtk_combo_box_text_append (
+               GTK_COMBO_BOX_TEXT (widget),
+               enum_value->value_nick, _("Never"));
+       policy = E_MDN_RESPONSE_POLICY_ALWAYS;
+       enum_value = g_enum_get_value (enum_class, policy);
+       g_return_if_fail (enum_value != NULL);
+       gtk_combo_box_text_append (
+               GTK_COMBO_BOX_TEXT (widget),
+               enum_value->value_nick, _("Always"));
+       policy = E_MDN_RESPONSE_POLICY_ASK;
+       enum_value = g_enum_get_value (enum_class, policy);
+       g_return_if_fail (enum_value != NULL);
+       gtk_combo_box_text_append (
+               GTK_COMBO_BOX_TEXT (widget),
+               enum_value->value_nick, _("Ask for each message"));
+       g_type_class_unref (enum_class);
+
+       e_binding_bind_property_full (
+               mdn_ext, "response-policy",
+               widget, "active-id",
+               G_BINDING_BIDIRECTIONAL |
+               G_BINDING_SYNC_CREATE,
+               e_binding_transform_enum_value_to_nick,
+               e_binding_transform_enum_nick_to_value,
+               NULL, (GDestroyNotify) NULL);
+
+       g_object_unref (size_group);
+
+       e_mail_config_page_set_content (E_MAIL_CONFIG_PAGE (page), main_box);
+
+       e_extensible_load_extensions (E_EXTENSIBLE (page));
+}
+
+static void
+e_mail_config_composing_page_class_init (EMailConfigComposingPageClass *class)
+{
+       GObjectClass *object_class;
+
+       g_type_class_add_private (class, sizeof (EMailConfigComposingPagePrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = mail_config_composing_page_set_property;
+       object_class->get_property = mail_config_composing_page_get_property;
+       object_class->dispose = mail_config_composing_page_dispose;
+       object_class->constructed = mail_config_composing_page_constructed;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_IDENTITY_SOURCE,
+               g_param_spec_object (
+                       "identity-source",
+                       "Identity Source",
+                       "Mail identity source being edited",
+                       E_TYPE_SOURCE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_mail_config_composing_page_interface_init (EMailConfigPageInterface *iface)
+{
+       iface->title = _("Composing Messages");
+       iface->sort_order = E_MAIL_CONFIG_COMPOSING_PAGE_SORT_ORDER;
+}
+
+static void
+e_mail_config_composing_page_init (EMailConfigComposingPage *page)
+{
+       page->priv = G_TYPE_INSTANCE_GET_PRIVATE (page, E_TYPE_MAIL_CONFIG_COMPOSING_PAGE, 
EMailConfigComposingPagePrivate);
+}
+
+EMailConfigPage *
+e_mail_config_composing_page_new (ESource *identity_source)
+{
+       g_return_val_if_fail (E_IS_SOURCE (identity_source), NULL);
+
+       return g_object_new (E_TYPE_MAIL_CONFIG_COMPOSING_PAGE,
+               "identity-source", identity_source,
+               NULL);
+}
+
+ESource *
+e_mail_config_composing_page_get_identity_source (EMailConfigComposingPage *page)
+{
+       g_return_val_if_fail (E_IS_MAIL_CONFIG_COMPOSING_PAGE (page), NULL);
+
+       return page->priv->identity_source;
+}
diff --git a/src/mail/e-mail-config-composing-page.h b/src/mail/e-mail-config-composing-page.h
new file mode 100644
index 0000000..9be29e3
--- /dev/null
+++ b/src/mail/e-mail-config-composing-page.h
@@ -0,0 +1,71 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_COMPOSING_PAGE_H
+#define E_MAIL_CONFIG_COMPOSING_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libemail-engine/libemail-engine.h>
+
+#include <mail/e-mail-config-page.h>
+#include <mail/e-mail-config-activity-page.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_CONFIG_COMPOSING_PAGE \
+       (e_mail_config_composing_page_get_type ())
+#define E_MAIL_CONFIG_COMPOSING_PAGE(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_MAIL_CONFIG_COMPOSING_PAGE, EMailConfigComposingPage))
+#define E_MAIL_CONFIG_COMPOSING_PAGE_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_MAIL_CONFIG_COMPOSING_PAGE, EMailConfigComposingPageClass))
+#define E_IS_MAIL_CONFIG_COMPOSING_PAGE(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_MAIL_CONFIG_COMPOSING_PAGE))
+#define E_IS_MAIL_CONFIG_COMPOSING_PAGE_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_MAIL_CONFIG_COMPOSING_PAGE))
+#define E_MAIL_CONFIG_COMPOSING_PAGE_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_MAIL_CONFIG_COMPOSING_PAGE, EMailConfigComposingPageClass))
+
+#define E_MAIL_CONFIG_COMPOSING_PAGE_SORT_ORDER (550)
+
+G_BEGIN_DECLS
+
+typedef struct _EMailConfigComposingPage EMailConfigComposingPage;
+typedef struct _EMailConfigComposingPageClass EMailConfigComposingPageClass;
+typedef struct _EMailConfigComposingPagePrivate EMailConfigComposingPagePrivate;
+
+struct _EMailConfigComposingPage {
+       EMailConfigActivityPage parent;
+       EMailConfigComposingPagePrivate *priv;
+};
+
+struct _EMailConfigComposingPageClass {
+       EMailConfigActivityPageClass parent_class;
+};
+
+GType          e_mail_config_composing_page_get_type
+                                               (void) G_GNUC_CONST;
+EMailConfigPage *
+               e_mail_config_composing_page_new
+                                               (ESource *identity_source);
+ESource *      e_mail_config_composing_page_get_identity_source
+                                               (EMailConfigComposingPage *page);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_COMPOSING_PAGE_H */
diff --git a/src/mail/e-mail-config-defaults-page.c b/src/mail/e-mail-config-defaults-page.c
index 13285a7..c091150 100644
--- a/src/mail/e-mail-config-defaults-page.c
+++ b/src/mail/e-mail-config-defaults-page.c
@@ -128,70 +128,6 @@ mail_config_defaults_page_ref_store (EMailConfigDefaultsPage *page)
 }
 
 static gboolean
-mail_config_defaults_page_addrs_to_string (GBinding *binding,
-                                           const GValue *source_value,
-                                           GValue *target_value,
-                                           gpointer unused)
-{
-       gchar **strv;
-
-       strv = g_value_dup_boxed (source_value);
-
-       if (strv != NULL) {
-               gchar *string = g_strjoinv ("; ", strv);
-               g_value_set_string (target_value, string);
-               g_free (string);
-       } else {
-               g_value_set_string (target_value, "");
-       }
-
-       g_strfreev (strv);
-
-       return TRUE;
-}
-
-static gboolean
-mail_config_defaults_page_string_to_addrs (GBinding *binding,
-                                           const GValue *source_value,
-                                           GValue *target_value,
-                                           gpointer unused)
-{
-       CamelInternetAddress *address;
-       const gchar *string;
-       gchar **strv;
-       gint n_addresses, ii;
-
-       string = g_value_get_string (source_value);
-
-       address = camel_internet_address_new ();
-       n_addresses = camel_address_decode (CAMEL_ADDRESS (address), string);
-
-       if (n_addresses < 0) {
-               g_object_unref (address);
-               return FALSE;
-
-       } else if (n_addresses == 0) {
-               g_value_set_boxed (target_value, NULL);
-               g_object_unref (address);
-               return TRUE;
-       }
-
-       strv = g_new0 (gchar *, n_addresses + 1);
-
-       for (ii = 0; ii < n_addresses; ii++) {
-               const gchar *name = NULL;
-               const gchar *addr = NULL;
-
-               camel_internet_address_get (address, ii, &name, &addr);
-               strv[ii] = camel_internet_address_format_address (name, addr);
-       }
-
-       g_value_take_boxed (target_value, strv);
-
-       return TRUE;
-}
-
-static gboolean
 mail_config_defaults_page_folder_name_to_uri (GBinding *binding,
                                               const GValue *source_value,
                                               GValue *target_value,
@@ -486,102 +422,6 @@ mail_config_defaults_page_add_real_folder (EMailConfigDefaultsPage *page,
 }
 
 static void
-mail_config_defaults_fill_reply_style_combox (GtkComboBoxText *combo)
-{
-       struct _values {
-               ESourceMailCompositionReplyStyle reply_style;
-               const gchar *display_name;
-       } values[] = {
-               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DEFAULT,
-                 NC_("ReplyForward", "Use global setting") },
-               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_ATTACH,
-                 NC_("ReplyForward", "Attachment") },
-               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_OUTLOOK,
-                 NC_("ReplyForward", "Inline (Outlook style)") },
-               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_QUOTED,
-                 NC_("ReplyForward", "Quoted") },
-               { E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DO_NOT_QUOTE,
-                 NC_("ReplyForward", "Do Not Quote") }
-       };
-       GEnumClass *enum_class;
-       GEnumValue *enum_value;
-       gint ii;
-
-       g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (combo));
-
-       enum_class = g_type_class_ref (E_TYPE_SOURCE_MAIL_COMPOSITION_REPLY_STYLE);
-       g_return_if_fail (enum_class != NULL);
-
-       g_warn_if_fail (enum_class->n_values == G_N_ELEMENTS (values));
-
-       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
-               enum_value = g_enum_get_value (enum_class, values[ii].reply_style);
-               g_warn_if_fail (enum_value != NULL);
-
-               if (enum_value) {
-                       gtk_combo_box_text_append (combo,
-                               enum_value->value_name,
-                               g_dpgettext2 (GETTEXT_PACKAGE, "ReplyForward", values[ii].display_name));
-               }
-       }
-
-       g_type_class_unref (enum_class);
-}
-
-static gboolean
-mail_config_defaults_page_reply_style_to_string (GBinding *binding,
-                                                const GValue *source_value,
-                                                GValue *target_value,
-                                                gpointer data)
-{
-       GEnumClass *enum_class;
-       GEnumValue *enum_value;
-
-       enum_class = g_type_class_ref (E_TYPE_SOURCE_MAIL_COMPOSITION_REPLY_STYLE);
-       g_return_val_if_fail (enum_class != NULL, FALSE);
-
-       enum_value = g_enum_get_value (enum_class, g_value_get_enum (source_value));
-       g_return_val_if_fail (enum_value != NULL, FALSE);
-
-       g_value_set_string (target_value, enum_value->value_name);
-
-       g_type_class_unref (enum_class);
-
-       return TRUE;
-}
-
-static gboolean
-mail_config_defaults_page_string_to_reply_style (GBinding *binding,
-                                                const GValue *source_value,
-                                                GValue *target_value,
-                                                gpointer data)
-{
-       GEnumClass *enum_class;
-       GEnumValue *enum_value;
-       const gchar *value_name;
-
-       enum_class = g_type_class_ref (E_TYPE_SOURCE_MAIL_COMPOSITION_REPLY_STYLE);
-       g_return_val_if_fail (enum_class != NULL, FALSE);
-
-       value_name = g_value_get_string (source_value);
-       if (!value_name || !*value_name) {
-               enum_value = NULL;
-       } else {
-               enum_value = g_enum_get_value_by_name (enum_class, value_name);
-       }
-       if (!enum_value)
-               g_value_set_enum (target_value, E_SOURCE_MAIL_COMPOSITION_REPLY_STYLE_DEFAULT);
-       else
-               g_value_set_enum (target_value, enum_value->value);
-
-       g_warn_if_fail (enum_value != NULL);
-
-       g_type_class_unref (enum_class);
-
-       return TRUE;
-}
-
-static void
 mail_config_defaults_page_set_collection_source (EMailConfigDefaultsPage *page,
                                                 ESource *collection_source)
 {
@@ -771,16 +611,12 @@ mail_config_defaults_page_constructed (GObject *object)
        ESourceBackend *account_ext;
        ESourceMailComposition *composition_ext;
        ESourceMailSubmission *submission_ext;
-       ESourceMDN *mdn_ext;
        GtkLabel *label;
        GtkButton *button;
        GtkWidget *widget;
        GtkWidget *container;
        GtkWidget *hbox, *main_box;
        GtkSizeGroup *size_group;
-       GEnumClass *enum_class;
-       GEnumValue *enum_value;
-       EMdnResponsePolicy policy;
        CamelProvider *provider = NULL;
        CamelStore *store;
        const gchar *extension_name;
@@ -808,9 +644,6 @@ mail_config_defaults_page_constructed (GObject *object)
        extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
        submission_ext = e_source_get_extension (source, extension_name);
 
-       extension_name = E_SOURCE_EXTENSION_MDN;
-       mdn_ext = e_source_get_extension (source, extension_name);
-
        main_box = e_mail_config_activity_page_get_internal_box (E_MAIL_CONFIG_ACTIVITY_PAGE (page));
 
        gtk_box_set_spacing (GTK_BOX (main_box), 12);
@@ -1048,175 +881,6 @@ mail_config_defaults_page_constructed (GObject *object)
                gtk_widget_show (widget);
        }
 
-       /*** Composing Messages ***/
-
-       widget = gtk_grid_new ();
-       gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
-       gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
-       gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
-       gtk_widget_show (widget);
-
-       container = widget;
-
-       text = _("Composing Messages");
-       markup = g_markup_printf_escaped ("<b>%s</b>", text);
-       widget = gtk_label_new (markup);
-       gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
-       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 1);
-       gtk_widget_show (widget);
-       g_free (markup);
-
-       text = _("Alway_s carbon-copy (cc) to:");
-       widget = gtk_label_new_with_mnemonic (text);
-       gtk_widget_set_margin_left (widget, 12);
-       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
-       gtk_widget_show (widget);
-
-       label = GTK_LABEL (widget);
-
-       widget = gtk_entry_new ();
-       gtk_widget_set_hexpand (widget, TRUE);
-       gtk_widget_set_margin_left (widget, 12);
-       gtk_label_set_mnemonic_widget (label, widget);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 2, 1, 1);
-       gtk_widget_show (widget);
-
-       e_binding_bind_property_full (
-               composition_ext, "cc",
-               widget, "text",
-               G_BINDING_BIDIRECTIONAL |
-               G_BINDING_SYNC_CREATE,
-               mail_config_defaults_page_addrs_to_string,
-               mail_config_defaults_page_string_to_addrs,
-               NULL, (GDestroyNotify) NULL);
-
-       text = _("Always _blind carbon-copy (bcc) to:");
-       widget = gtk_label_new_with_mnemonic (text);
-       gtk_widget_set_margin_left (widget, 12);
-       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 3, 1, 1);
-       gtk_widget_show (widget);
-
-       label = GTK_LABEL (widget);
-
-       widget = gtk_entry_new ();
-       gtk_widget_set_hexpand (widget, TRUE);
-       gtk_widget_set_margin_left (widget, 12);
-       gtk_label_set_mnemonic_widget (label, widget);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 4, 1, 1);
-       gtk_widget_show (widget);
-
-       e_binding_bind_property_full (
-               composition_ext, "bcc",
-               widget, "text",
-               G_BINDING_BIDIRECTIONAL |
-               G_BINDING_SYNC_CREATE,
-               mail_config_defaults_page_addrs_to_string,
-               mail_config_defaults_page_string_to_addrs,
-               NULL, (GDestroyNotify) NULL);
-
-       widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 5, 1, 1);
-       gtk_widget_show (widget);
-
-       container = widget;
-
-       text = _("Re_ply style:");
-       widget = gtk_label_new_with_mnemonic (text);
-       gtk_widget_set_margin_left (widget, 12);
-       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-       gtk_widget_show (widget);
-
-       label = GTK_LABEL (widget);
-
-       widget = gtk_combo_box_text_new ();
-       gtk_widget_set_hexpand (widget, FALSE);
-       gtk_label_set_mnemonic_widget (label, widget);
-       gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-       gtk_widget_show (widget);
-
-       mail_config_defaults_fill_reply_style_combox (GTK_COMBO_BOX_TEXT (widget));
-
-       e_binding_bind_property_full (
-               composition_ext, "reply-style",
-               widget, "active-id",
-               G_BINDING_BIDIRECTIONAL |
-               G_BINDING_SYNC_CREATE,
-               mail_config_defaults_page_reply_style_to_string,
-               mail_config_defaults_page_string_to_reply_style,
-               NULL, (GDestroyNotify) NULL);
-
-       /*** Message Receipts ***/
-
-       widget = gtk_grid_new ();
-       gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
-       gtk_grid_set_column_spacing (GTK_GRID (widget), 6);
-       gtk_box_pack_start (GTK_BOX (main_box), widget, FALSE, FALSE, 0);
-       gtk_widget_show (widget);
-
-       container = widget;
-
-       text = _("Message Receipts");
-       markup = g_markup_printf_escaped ("<b>%s</b>", text);
-       widget = gtk_label_new (markup);
-       gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
-       gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 2, 1);
-       gtk_widget_show (widget);
-       g_free (markup);
-
-       text = _("S_end message receipts:");
-       widget = gtk_label_new_with_mnemonic (text);
-       gtk_widget_set_margin_left (widget, 12);
-       gtk_size_group_add_widget (size_group, widget);
-       gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
-       gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
-       gtk_widget_show (widget);
-
-       label = GTK_LABEL (widget);
-
-       widget = gtk_combo_box_text_new ();
-       gtk_widget_set_hexpand (widget, TRUE);
-       gtk_label_set_mnemonic_widget (label, widget);
-       gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
-       gtk_widget_show (widget);
-
-       /* XXX This is a pain in the butt, but we want to avoid hard-coding
-        *     string values from the EMdnResponsePolicy enum class in case
-        *     they change in the future. */
-       enum_class = g_type_class_ref (E_TYPE_MDN_RESPONSE_POLICY);
-       policy = E_MDN_RESPONSE_POLICY_NEVER;
-       enum_value = g_enum_get_value (enum_class, policy);
-       g_return_if_fail (enum_value != NULL);
-       gtk_combo_box_text_append (
-               GTK_COMBO_BOX_TEXT (widget),
-               enum_value->value_nick, _("Never"));
-       policy = E_MDN_RESPONSE_POLICY_ALWAYS;
-       enum_value = g_enum_get_value (enum_class, policy);
-       g_return_if_fail (enum_value != NULL);
-       gtk_combo_box_text_append (
-               GTK_COMBO_BOX_TEXT (widget),
-               enum_value->value_nick, _("Always"));
-       policy = E_MDN_RESPONSE_POLICY_ASK;
-       enum_value = g_enum_get_value (enum_class, policy);
-       g_return_if_fail (enum_value != NULL);
-       gtk_combo_box_text_append (
-               GTK_COMBO_BOX_TEXT (widget),
-               enum_value->value_nick, _("Ask for each message"));
-       g_type_class_unref (enum_class);
-
-       e_binding_bind_property_full (
-               mdn_ext, "response-policy",
-               widget, "active-id",
-               G_BINDING_BIDIRECTIONAL |
-               G_BINDING_SYNC_CREATE,
-               e_binding_transform_enum_value_to_nick,
-               e_binding_transform_enum_nick_to_value,
-               NULL, (GDestroyNotify) NULL);
-
        g_object_unref (size_group);
 
        e_mail_config_page_set_content (E_MAIL_CONFIG_PAGE (page), main_box);
diff --git a/src/mail/e-mail-config-defaults-page.h b/src/mail/e-mail-config-defaults-page.h
index e5b5c79..026d13e 100644
--- a/src/mail/e-mail-config-defaults-page.h
+++ b/src/mail/e-mail-config-defaults-page.h
@@ -30,7 +30,7 @@
 #define E_MAIL_CONFIG_DEFAULTS_PAGE(obj) \
        (G_TYPE_CHECK_INSTANCE_CAST \
        ((obj), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPage))
-#define E_MAIL_CONFIG_DEFAULT_PAGE_CLASS(cls) \
+#define E_MAIL_CONFIG_DEFAULTS_PAGE_CLASS(cls) \
        (G_TYPE_CHECK_CLASS_CAST \
        ((cls), E_TYPE_MAIL_CONFIG_DEFAULTS_PAGE, EMailConfigDefaultsPageClass))
 #define E_IS_MAIL_CONFIG_DEFAULTS_PAGE(obj) \
diff --git a/src/mail/e-mail-config-notebook.c b/src/mail/e-mail-config-notebook.c
index 7630bfa..47f4537 100644
--- a/src/mail/e-mail-config-notebook.c
+++ b/src/mail/e-mail-config-notebook.c
@@ -15,16 +15,19 @@
  *
  */
 
-#include "e-mail-config-notebook.h"
+#include "evolution-config.h"
 
 #include <libebackend/libebackend.h>
 
-#include <mail/e-mail-config-defaults-page.h>
-#include <mail/e-mail-config-identity-page.h>
-#include <mail/e-mail-config-provider-page.h>
-#include <mail/e-mail-config-receiving-page.h>
-#include <mail/e-mail-config-security-page.h>
-#include <mail/e-mail-config-sending-page.h>
+#include "e-mail-config-composing-page.h"
+#include "e-mail-config-defaults-page.h"
+#include "e-mail-config-identity-page.h"
+#include "e-mail-config-provider-page.h"
+#include "e-mail-config-receiving-page.h"
+#include "e-mail-config-security-page.h"
+#include "e-mail-config-sending-page.h"
+
+#include "e-mail-config-notebook.h"
 
 #define E_MAIL_CONFIG_NOTEBOOK_GET_PRIVATE(obj) \
        (G_TYPE_INSTANCE_GET_PRIVATE \
@@ -475,6 +478,11 @@ mail_config_notebook_constructed (GObject *object)
                notebook->priv->transport_source);
        e_mail_config_notebook_add_page (notebook, page);
 
+       /*** Composing Messages Page ***/
+
+       page = e_mail_config_composing_page_new (notebook->priv->identity_source);
+       e_mail_config_notebook_add_page (notebook, page);
+
        /*** Security Page ***/
 
        page = e_mail_config_security_page_new (
diff --git a/src/mail/mail-config.ui b/src/mail/mail-config.ui
index 977d7ac..22e975c 100644
--- a/src/mail/mail-config.ui
+++ b/src/mail/mail-config.ui
@@ -519,7 +519,7 @@
                     </child>
                     <child>
                       <object class="GtkCheckButton" id="chkReplyStartBottom">
-                        <property name="label" translatable="yes">Start _typing at the bottom on 
replying</property>
+                        <property name="label" translatable="yes">Start _typing at the bottom</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
@@ -535,8 +535,8 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkCheckButton" id="chkSignatureInNewOnly">
-                        <property name="label" translatable="yes">Include si_gnature in new messages 
only</property>
+                      <object class="GtkCheckButton" id="chkTopSignature">
+                        <property name="label" translatable="yes">_Keep signature above the original 
message</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
@@ -552,8 +552,8 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkCheckButton" id="chkTopSignature">
-                        <property name="label" translatable="yes">_Keep signature above the original message 
on replying</property>
+                      <object class="GtkCheckButton" id="chkSignatureInNewOnly">
+                        <property name="label" translatable="yes">Include si_gnature in new messages 
only</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index 8a6c35c..4b165da 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -48,6 +48,8 @@ enum {
        PROP_HTML_MODE,
        PROP_SPELL_CHECK_ENABLED,
        PROP_SPELL_CHECKER,
+       PROP_START_BOTTOM,
+       PROP_TOP_SIGNATURE,
 
        PROP_ALIGNMENT,
        PROP_BACKGROUND_COLOR,
@@ -138,6 +140,9 @@ struct _EWebKitEditorPrivate {
        gulong drag_data_received_handler_id;
 
        gchar *last_hover_uri;
+
+       EThreeState start_bottom;
+       EThreeState top_signature;
 };
 
 static const GdkRGBA black = { 0, 0, 0, 1 };
@@ -163,6 +168,18 @@ G_DEFINE_TYPE_WITH_CODE (
                E_TYPE_CONTENT_EDITOR,
                e_webkit_editor_content_editor_init));
 
+static gint16
+e_webkit_editor_three_state_to_int16 (EThreeState value)
+{
+       if (value == E_THREE_STATE_ON)
+               return 1;
+
+       if (value == E_THREE_STATE_OFF)
+               return 0;
+
+       return -1;
+}
+
 EWebKitEditor *
 e_webkit_editor_new (void)
 {
@@ -1719,7 +1736,9 @@ set_convert_in_situ (EWebKitEditor *wk_editor,
        e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
                wk_editor->priv->web_extension,
                "SetConvertInSitu",
-               g_variant_new ("(tb)", current_page_id (wk_editor), value),
+               g_variant_new ("(tbnn)", current_page_id (wk_editor), value,
+                       e_webkit_editor_three_state_to_int16 (e_content_editor_get_start_bottom 
(E_CONTENT_EDITOR (wk_editor))),
+                       e_webkit_editor_three_state_to_int16 (e_content_editor_get_top_signature 
(E_CONTENT_EDITOR (wk_editor)))),
                NULL);
 }
 
@@ -1816,7 +1835,9 @@ webkit_editor_insert_content (EContentEditor *editor,
                e_util_invoke_g_dbus_proxy_call_with_error_check (
                        wk_editor->priv->web_extension,
                        "DOMConvertContent",
-                       g_variant_new ("(ts)", current_page_id (wk_editor), content),
+                       g_variant_new ("(tsnn)", current_page_id (wk_editor), content,
+                               e_webkit_editor_three_state_to_int16 (e_content_editor_get_start_bottom 
(editor)),
+                               e_webkit_editor_three_state_to_int16 (e_content_editor_get_top_signature 
(editor))),
                        wk_editor->priv->cancellable);
        } else if ((flags & E_CONTENT_EDITOR_INSERT_CONVERT) &&
                    !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL) &&
@@ -2256,6 +2277,50 @@ webkit_editor_set_spell_checking_languages (EContentEditor *editor,
 }
 
 static void
+webkit_editor_set_start_bottom (EWebKitEditor *wk_editor,
+                               EThreeState value)
+{
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
+
+       if (wk_editor->priv->start_bottom == value)
+               return;
+
+       wk_editor->priv->start_bottom = value;
+
+       g_object_notify (G_OBJECT (wk_editor), "start-bottom");
+}
+
+static EThreeState
+webkit_editor_get_start_bottom (EWebKitEditor *wk_editor)
+{
+       g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), E_THREE_STATE_INCONSISTENT);
+
+       return wk_editor->priv->start_bottom;
+}
+
+static void
+webkit_editor_set_top_signature (EWebKitEditor *wk_editor,
+                                EThreeState value)
+{
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
+
+       if (wk_editor->priv->top_signature == value)
+               return;
+
+       wk_editor->priv->top_signature = value;
+
+       g_object_notify (G_OBJECT (wk_editor), "top-signature");
+}
+
+static EThreeState
+webkit_editor_get_top_signature (EWebKitEditor *wk_editor)
+{
+       g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), E_THREE_STATE_INCONSISTENT);
+
+       return wk_editor->priv->top_signature;
+}
+
+static void
 webkit_editor_set_spell_check_enabled (EWebKitEditor *wk_editor,
                                        gboolean enable)
 {
@@ -2370,14 +2435,16 @@ webkit_editor_insert_signature (EContentEditor *editor,
                wk_editor->priv->web_extension,
                "DOMInsertSignature",
                g_variant_new (
-                       "(tsbsbbb)",
+                       "(tsbsbbbnn)",
                        current_page_id (wk_editor),
                        content ? content : "",
                        is_html,
                        signature_id,
                        *set_signature_from_message,
                        *check_if_signature_is_changed,
-                       *ignore_next_signature_change),
+                       *ignore_next_signature_change,
+                       e_webkit_editor_three_state_to_int16 (e_content_editor_get_start_bottom (editor)),
+                       e_webkit_editor_three_state_to_int16 (e_content_editor_get_top_signature (editor))),
                NULL);
 
        if (result) {
@@ -5409,6 +5476,18 @@ webkit_editor_set_property (GObject *object,
                                "DOMSelectionSetUnderline");
                        return;
 
+               case PROP_START_BOTTOM:
+                       webkit_editor_set_start_bottom (
+                               E_WEBKIT_EDITOR (object),
+                               g_value_get_enum (value));
+                       return;
+
+               case PROP_TOP_SIGNATURE:
+                       webkit_editor_set_top_signature (
+                               E_WEBKIT_EDITOR (object),
+                               g_value_get_enum (value));
+                       return;
+
                case PROP_SPELL_CHECK_ENABLED:
                        webkit_editor_set_spell_check_enabled (
                                E_WEBKIT_EDITOR (object),
@@ -5585,6 +5664,20 @@ webkit_editor_get_property (GObject *object,
                                        E_CONTENT_EDITOR_STYLE_IS_UNDERLINE));
                        return;
 
+               case PROP_START_BOTTOM:
+                       g_value_set_enum (
+                               value,
+                               webkit_editor_get_start_bottom (
+                                       E_WEBKIT_EDITOR (object)));
+                       return;
+
+               case PROP_TOP_SIGNATURE:
+                       g_value_set_enum (
+                               value,
+                               webkit_editor_get_top_signature (
+                                       E_WEBKIT_EDITOR (object)));
+                       return;
+
                case PROP_SPELL_CHECK_ENABLED:
                        g_value_set_boolean (
                                value,
@@ -6281,6 +6374,10 @@ e_webkit_editor_class_init (EWebKitEditorClass *class)
        g_object_class_override_property (
                object_class, PROP_UNDERLINE, "underline");
        g_object_class_override_property (
+               object_class, PROP_START_BOTTOM, "start-bottom");
+       g_object_class_override_property (
+               object_class, PROP_TOP_SIGNATURE, "top-signature");
+       g_object_class_override_property (
                object_class, PROP_SPELL_CHECK_ENABLED, "spell-check-enabled");
        g_object_class_override_property (
                object_class, PROP_SPELL_CHECKER, "spell-checker");
@@ -6399,6 +6496,9 @@ e_webkit_editor_init (EWebKitEditor *wk_editor)
        wk_editor->priv->block_format = E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH;
        wk_editor->priv->alignment = E_CONTENT_EDITOR_ALIGNMENT_LEFT;
 
+       wk_editor->priv->start_bottom = E_THREE_STATE_INCONSISTENT;
+       wk_editor->priv->top_signature = E_THREE_STATE_INCONSISTENT;
+
        wk_editor->priv->web_extension_selection_changed_cb_id = 0;
        wk_editor->priv->web_extension_content_changed_cb_id = 0;
        wk_editor->priv->web_extension_undo_redo_state_changed_cb_id = 0;
diff --git a/src/modules/webkit-editor/web-extension/e-composer-dom-functions.c 
b/src/modules/webkit-editor/web-extension/e-composer-dom-functions.c
index 1544081..21dfc52 100644
--- a/src/modules/webkit-editor/web-extension/e-composer-dom-functions.c
+++ b/src/modules/webkit-editor/web-extension/e-composer-dom-functions.c
@@ -88,23 +88,20 @@ start_typing_at_bottom (void)
 }
 
 static void
-move_caret_after_signature_inserted (EEditorPage *editor_page)
+move_caret_after_signature_inserted (EEditorPage *editor_page,
+                                    gboolean start_bottom,
+                                    gboolean top_signature)
 {
        WebKitDOMDocument *document;
        WebKitDOMElement *element, *signature;
        WebKitDOMHTMLElement *body;
        WebKitDOMNodeList *paragraphs = NULL;
-       gboolean top_signature;
-       gboolean start_bottom;
        gboolean has_paragraphs_in_body = TRUE;
 
        g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
 
        document = e_editor_page_get_document (editor_page);
 
-       top_signature = e_editor_page_get_allow_top_signature (editor_page) && use_top_signature ();
-       start_bottom = start_typing_at_bottom ();
-
        body = webkit_dom_document_get_body (document);
        e_editor_page_block_selection_changed (editor_page);
 
@@ -262,7 +259,9 @@ e_composer_dom_insert_signature (EEditorPage *editor_page,
                                  const gchar *id,
                                  gboolean *set_signature_from_message,
                                  gboolean *check_if_signature_is_changed,
-                                 gboolean *ignore_next_signature_change)
+                                gboolean *ignore_next_signature_change,
+                                gint16 in_start_at_bottom,
+                                gint16 in_top_signature)
 {
        WebKitDOMDocument *document;
        WebKitDOMElement *signature_to_insert;
@@ -286,7 +285,14 @@ e_composer_dom_insert_signature (EEditorPage *editor_page,
 
        /* "Edit as New Message" sets is_message_from_edit_as_new.
         * Always put the signature at the bottom for that case. */
-       top_signature = e_editor_page_get_allow_top_signature (editor_page) && use_top_signature ();
+       if (e_editor_page_get_allow_top_signature (editor_page)) {
+               if (in_top_signature == 0 || in_top_signature == 1)
+                       top_signature = in_top_signature == 1;
+               else
+                       top_signature = use_top_signature ();
+       } else {
+               top_signature = FALSE;
+       }
 
        html_mode = e_editor_page_get_html_mode (editor_page);
 
@@ -472,9 +478,16 @@ insert:
                                NULL);
                }
        } else {
+               gboolean start_at_bottom;
+
                signature_wrapper = webkit_dom_document_create_element (document, "div", NULL);
                webkit_dom_element_set_class_name (signature_wrapper, "-x-evo-signature-wrapper");
 
+               if (in_start_at_bottom == 0 || in_start_at_bottom == 1)
+                       start_at_bottom = in_start_at_bottom == 1;
+               else
+                       start_at_bottom = start_typing_at_bottom ();
+
                webkit_dom_node_append_child (
                        WEBKIT_DOM_NODE (signature_wrapper),
                        WEBKIT_DOM_NODE (signature_to_insert),
@@ -485,7 +498,7 @@ insert:
 
                        child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
 
-                       if (start_typing_at_bottom ()) {
+                       if (start_at_bottom) {
                                webkit_dom_node_insert_before (
                                        WEBKIT_DOM_NODE (body),
                                        WEBKIT_DOM_NODE (signature_wrapper),
@@ -507,7 +520,7 @@ insert:
                                NULL);
                }
 
-               move_caret_after_signature_inserted (editor_page);
+               move_caret_after_signature_inserted (editor_page, start_at_bottom, top_signature);
        }
        g_clear_object (&signatures);
 
diff --git a/src/modules/webkit-editor/web-extension/e-composer-dom-functions.h 
b/src/modules/webkit-editor/web-extension/e-composer-dom-functions.h
index a204346..6f6d170 100644
--- a/src/modules/webkit-editor/web-extension/e-composer-dom-functions.h
+++ b/src/modules/webkit-editor/web-extension/e-composer-dom-functions.h
@@ -31,7 +31,9 @@ gchar *               e_composer_dom_insert_signature (EEditorPage *editor_page,
                                                 const gchar *id,
                                                 gboolean *set_signature_from_message,
                                                 gboolean *check_if_signature_is_changed,
-                                                gboolean *ignore_next_signature_change);
+                                                gboolean *ignore_next_signature_change,
+                                                gint16 start_at_bottom,
+                                                gint16 top_signature);
 gchar *                e_composer_dom_get_active_signature_uid
                                                (EEditorPage *editor_page);
 gchar *                e_composer_dom_get_raw_body_content_without_signature
diff --git a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c 
b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
index 6c2c8fb..002f1db 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.c
@@ -6001,7 +6001,9 @@ register_html_events_handlers (EEditorPage *editor_page,
 
 void
 e_editor_dom_convert_content (EEditorPage *editor_page,
-                              const gchar *preferred_text)
+                             const gchar *preferred_text,
+                             gint16 in_start_at_bottom,
+                             gint16 in_top_signature)
 {
        WebKitDOMDocument *document;
        WebKitDOMElement *paragraph, *content_wrapper, *top_signature;
@@ -6018,9 +6020,13 @@ e_editor_dom_convert_content (EEditorPage *editor_page,
        g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
 
        document = e_editor_page_get_document (editor_page);
-       settings = e_util_ref_settings ("org.gnome.evolution.mail");
-       start_bottom = g_settings_get_boolean (settings, "composer-reply-start-bottom");
-       g_object_unref (settings);
+       if (in_start_at_bottom == 0 || in_start_at_bottom == 1) {
+               start_bottom = in_start_at_bottom == 1;
+       } else {
+               settings = e_util_ref_settings ("org.gnome.evolution.mail");
+               start_bottom = g_settings_get_boolean (settings, "composer-reply-start-bottom");
+               g_object_unref (settings);
+       }
 
        dom_window = webkit_dom_document_get_default_view (document);
        body = webkit_dom_document_get_body (document);
@@ -8734,6 +8740,7 @@ void
 e_editor_dom_process_content_after_load (EEditorPage *editor_page)
 {
        gboolean html_mode;
+       gint16 start_at_bottom = -1, top_signature = -1;
        WebKitDOMDocument *document;
        WebKitDOMHTMLElement *body;
        WebKitDOMDOMWindow *dom_window = NULL;
@@ -8755,14 +8762,14 @@ e_editor_dom_process_content_after_load (EEditorPage *editor_page)
                webkit_dom_element_set_attribute (
                        WEBKIT_DOM_ELEMENT (body), "data-evo-plain-text", "", NULL);
 
-       if (e_editor_page_get_convert_in_situ (editor_page)) {
-               e_editor_dom_convert_content (editor_page, NULL);
+       if (e_editor_page_get_convert_in_situ (editor_page, &start_at_bottom, &top_signature)) {
+               e_editor_dom_convert_content (editor_page, NULL, start_at_bottom, top_signature);
                /* The BODY could be replaced during the conversion */
                body = webkit_dom_document_get_body (document);
                /* Make the quote marks non-selectable. */
                e_editor_dom_disable_quote_marks_select (editor_page);
                dom_set_links_active (document, FALSE);
-               e_editor_page_set_convert_in_situ (editor_page, FALSE);
+               e_editor_page_set_convert_in_situ (editor_page, FALSE, -1, -1);
 
                /* The composer body could be empty in some case (loading an empty string
                 * or empty HTML). In that case create the initial paragraph. */
diff --git a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h 
b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
index 3ac56b1..5c92335 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
+++ b/src/modules/webkit-editor/web-extension/e-editor-dom-functions.h
@@ -109,7 +109,9 @@ void                e_editor_dom_set_monospace_font_family_on_body
                                                (WebKitDOMElement *body,
                                                 gboolean html_mode);
 void           e_editor_dom_convert_content    (EEditorPage *editor_page,
-                                                const gchar *preferred_text);
+                                                const gchar *preferred_text,
+                                                gint16 in_start_at_bottom,
+                                                gint16 in_top_signature);
 void           e_editor_dom_convert_and_insert_html_into_selection
                                                (EEditorPage *editor_page,
                                                 const gchar *html,
diff --git a/src/modules/webkit-editor/web-extension/e-editor-page.c 
b/src/modules/webkit-editor/web-extension/e-editor-page.c
index ddacdf1..09b0235 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-page.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-page.c
@@ -55,6 +55,8 @@ struct _EEditorPagePrivate {
        gboolean smiley_written;
        gint word_wrap_length;
 
+       gint16 convert_in_situ_start_at_bottom;
+       gint16 convert_in_situ_top_signature;
        gboolean convert_in_situ;
        gboolean body_input_event_removed;
        gboolean dont_save_history_in_body_input;
@@ -682,20 +684,31 @@ e_editor_page_set_body_input_event_removed (EEditorPage *editor_page,
 }
 
 gboolean
-e_editor_page_get_convert_in_situ (EEditorPage *editor_page)
+e_editor_page_get_convert_in_situ (EEditorPage *editor_page,
+                                  gint16 *out_start_at_bottom,
+                                  gint16 *out_top_signature)
 {
        g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), FALSE);
 
+       if (out_start_at_bottom)
+               *out_start_at_bottom = editor_page->priv->convert_in_situ_start_at_bottom;
+       if (out_top_signature)
+               *out_top_signature = editor_page->priv->convert_in_situ_top_signature;
+
        return editor_page->priv->convert_in_situ;
 }
 
 void
 e_editor_page_set_convert_in_situ (EEditorPage *editor_page,
-                                   gboolean value)
+                                  gboolean value,
+                                  gint16 start_at_bottom,
+                                  gint16 top_signature)
 {
        g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
 
        editor_page->priv->convert_in_situ = value;
+       editor_page->priv->convert_in_situ_start_at_bottom = start_at_bottom;
+       editor_page->priv->convert_in_situ_top_signature = top_signature;
 }
 
 GHashTable *
diff --git a/src/modules/webkit-editor/web-extension/e-editor-page.h 
b/src/modules/webkit-editor/web-extension/e-editor-page.h
index 909e130..020a18b 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-page.h
+++ b/src/modules/webkit-editor/web-extension/e-editor-page.h
@@ -148,10 +148,14 @@ void              e_editor_page_set_body_input_event_removed
                                                (EEditorPage *editor_page,
                                                 gboolean value);
 gboolean       e_editor_page_get_convert_in_situ
-                                               (EEditorPage *editor_page);
+                                               (EEditorPage *editor_page,
+                                                gint16 *out_start_at_bottom,
+                                                gint16 *out_top_signature);
 void           e_editor_page_set_convert_in_situ
                                                (EEditorPage *editor_page,
-                                                gboolean value);
+                                                gboolean value,
+                                                gint16 start_at_bottom,
+                                                gint16 top_signature);
 GHashTable *   e_editor_page_get_inline_images
                                                (EEditorPage *editor_page);
 void           e_editor_page_add_new_inline_image_into_list
diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c 
b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
index af5d7db..d333b95 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c
@@ -409,6 +409,8 @@ static const gchar *introspection_xml =
 "    <method name='SetConvertInSitu'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='b' name='value' direction='in'/>"
+"      <arg type='n' name='start_at_bottom' direction='in'/>"
+"      <arg type='n' name='top_signature' direction='in'/>"
 "    </method>"
 "    <method name='DOMForceSpellCheck'>"
 "      <arg type='t' name='page_id' direction='in'/>"
@@ -466,6 +468,8 @@ static const gchar *introspection_xml =
 "    <method name='DOMConvertContent'>"
 "      <arg type='t' name='page_id' direction='in'/>"
 "      <arg type='s' name='preffered_text' direction='in'/>"
+"      <arg type='n' name='start_at_bottom' direction='in'/>"
+"      <arg type='n' name='top_signature' direction='in'/>"
 "    </method>"
 "    <method name='DOMAddNewInlineImageIntoList'>"
 "      <arg type='t' name='page_id' direction='in'/>"
@@ -579,6 +583,8 @@ static const gchar *introspection_xml =
 "      <arg type='b' name='set_signature_from_message' direction='in'/>"
 "      <arg type='b' name='check_if_signature_is_changed' direction='in'/>"
 "      <arg type='b' name='ignore_next_signature_change' direction='in'/>"
+"      <arg type='n' name='start_at_bottom' direction='in'/>"
+"      <arg type='n' name='top_signature' direction='in'/>"
 "      <arg type='s' name='new_signature_id' direction='out'/>"
 "      <arg type='b' name='out_set_signature_from_message' direction='out'/>"
 "      <arg type='b' name='out_check_if_signature_is_changed' direction='out'/>"
@@ -1727,14 +1733,15 @@ handle_method_call (GDBusConnection *connection,
                g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "SetConvertInSitu") == 0) {
                gboolean value = FALSE;
+               gint16 start_at_bottom = -1, top_signature = -1;
 
-               g_variant_get (parameters, "(tb)", &page_id, &value);
+               g_variant_get (parameters, "(tbnn)", &page_id, &value, &start_at_bottom, &top_signature);
 
                editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
                if (!editor_page)
                        goto error;
 
-               e_editor_page_set_convert_in_situ (editor_page, value);
+               e_editor_page_set_convert_in_situ (editor_page, value, start_at_bottom, top_signature);
 
                g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "DOMForceSpellCheck") == 0) {
@@ -1822,14 +1829,15 @@ handle_method_call (GDBusConnection *connection,
                g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "DOMConvertContent") == 0) {
                const gchar *preferred_text;
+               gint64 start_at_bottom = -1, top_signature = -1;
 
-               g_variant_get (parameters, "(t&s)", &page_id, &preferred_text);
+               g_variant_get (parameters, "(t&snn)", &page_id, &preferred_text, &start_at_bottom, 
&top_signature);
 
                editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
                if (!editor_page)
                        goto error;
 
-               e_editor_dom_convert_content (editor_page, preferred_text);
+               e_editor_dom_convert_content (editor_page, preferred_text, start_at_bottom, top_signature);
                g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "DOMAddNewInlineImageIntoList") == 0) {
                const gchar *cid_uri, *src, *filename;
@@ -2117,19 +2125,22 @@ handle_method_call (GDBusConnection *connection,
        } else if (g_strcmp0 (method_name, "DOMInsertSignature") == 0) {
                gboolean is_html, set_signature_from_message;
                gboolean check_if_signature_is_changed, ignore_next_signature_change;
+               gint16 start_at_bottom = -1, top_signature = -1;
                const gchar *content, *signature_id;
                gchar *new_signature_id = NULL;
 
                g_variant_get (
                        parameters,
-                       "(t&sb&sbbb)",
+                       "(t&sb&sbbbnn)",
                        &page_id,
                        &content,
                        &is_html,
                        &signature_id,
                        &set_signature_from_message,
                        &check_if_signature_is_changed,
-                       &ignore_next_signature_change);
+                       &ignore_next_signature_change,
+                       &start_at_bottom,
+                       &top_signature);
 
                editor_page = get_editor_page_or_return_dbus_error (invocation, extension, page_id);
                if (!editor_page)
@@ -2142,7 +2153,9 @@ handle_method_call (GDBusConnection *connection,
                        signature_id,
                        &set_signature_from_message,
                        &check_if_signature_is_changed,
-                       &ignore_next_signature_change);
+                       &ignore_next_signature_change,
+                       start_at_bottom,
+                       top_signature);
 
                g_dbus_method_invocation_return_value (
                        invocation,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]