[evolution] Composer: Add an option to prefer PRE on paste of a plain text



commit 5ee60af2a2d0ca4ac1f38b2e707edaea0afe1c02
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jan 28 17:57:24 2021 +0100

    Composer: Add an option to prefer PRE on paste of a plain text
    
    Let the user choose whether paste of the plain text should be pasted
    as a normal paragraph or a preformatted paragraph.
    
    Related to https://gitlab.gnome.org/GNOME/evolution/-/issues/1269

 data/org.gnome.evolution.mail.gschema.xml.in |   5 +
 data/webkit/e-editor.js                      |   8 +-
 src/e-util/e-html-editor-actions.c           |   6 +-
 src/e-util/e-html-editor-private.h           |   2 +
 src/e-util/e-html-editor.c                   |  56 ++++++-
 src/e-util/e-util-enums.h                    |  14 +-
 src/e-util/test-html-editor-units-bugs.c     |   6 +
 src/e-util/test-html-editor-units.c          | 215 ++++++++++++++++++++++++++-
 src/modules/webkit-editor/e-webkit-editor.c  |  76 ++++++++--
 9 files changed, 360 insertions(+), 28 deletions(-)
---
diff --git a/data/org.gnome.evolution.mail.gschema.xml.in b/data/org.gnome.evolution.mail.gschema.xml.in
index 8dfaa9e109..dbb9b70435 100644
--- a/data/org.gnome.evolution.mail.gschema.xml.in
+++ b/data/org.gnome.evolution.mail.gschema.xml.in
@@ -244,6 +244,11 @@
       <_summary>Wrap quoted text in replies</_summary>
       <_description>If set to “true” quoted text in replies will be wrapped.</_description>
     </key>
+    <key name="composer-paste-plain-prefer-pre" type="b">
+      <default>false</default>
+      <_summary>Paste plain text as preformatted</_summary>
+      <_description>When set, paste a plain text into the composer body as Preformatted paragraph. When not 
set, paste it as Normal paragraph.</_description>
+    </key>
     <key name="composer-reply-credits-utc-to-localtime" type="b">
       <default>false</default>
       <_summary>Convert UTC time in reply credits to local time</_summary>
diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js
index 8cfaaf8a4a..aef0bdd7a3 100644
--- a/data/webkit/e-editor.js
+++ b/data/webkit/e-editor.js
@@ -5082,7 +5082,7 @@ EvoEditor.isEmptyParagraph = function(node)
 }
 
 // replaces current selection with the plain text or HTML, quoted or normal DIV
-EvoEditor.InsertContent = function(text, isHTML, quote)
+EvoEditor.InsertContent = function(text, isHTML, quote, preferPre)
 {
        EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_GROUP, "InsertContent");
        try {
@@ -5097,7 +5097,7 @@ EvoEditor.InsertContent = function(text, isHTML, quote)
                }
 
                var wasPlain = !isHTML;
-               var content = document.createElement(quote ? "BLOCKQUOTE" : wasPlain ? "PRE" : "DIV");
+               var content = document.createElement(quote ? "BLOCKQUOTE" : preferPre ? "PRE" : "DIV");
 
                if (quote) {
                        content.setAttribute("type", "cite");
@@ -5155,7 +5155,7 @@ EvoEditor.InsertContent = function(text, isHTML, quote)
 
                                for (ii = 0; ii < lines.length; ii++) {
                                        line = lines[ii];
-                                       divNode = document.createElement(wasPlain ? "PRE" : "DIV");
+                                       divNode = document.createElement(preferPre ? "PRE" : "DIV");
 
                                        content.appendChild(divNode);
 
@@ -5195,7 +5195,7 @@ EvoEditor.InsertContent = function(text, isHTML, quote)
                        if (!content.firstElementChild || (content.firstElementChild.tagName != "DIV" && 
content.firstElementChild.tagName != "P" &&
                            content.firstElementChild.tagName != "PRE")) {
                                // enclose quoted text into DIV
-                               var node = document.createElement("DIV");
+                               var node = document.createElement(preferPre ? "PRE" : "DIV");
 
                                while (content.firstChild) {
                                        node.appendChild(content.firstChild);
diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
index 98a4e93921..ab295f02da 100644
--- a/src/e-util/e-html-editor-actions.c
+++ b/src/e-util/e-html-editor-actions.c
@@ -684,7 +684,8 @@ clipboard_text_received_for_paste_as_text (GtkClipboard *clipboard,
                cnt_editor,
                text,
                E_CONTENT_EDITOR_INSERT_CONVERT |
-               E_CONTENT_EDITOR_INSERT_TEXT_PLAIN);
+               E_CONTENT_EDITOR_INSERT_TEXT_PLAIN |
+               (editor->priv->paste_plain_prefer_pre ? E_CONTENT_EDITOR_INSERT_CONVERT_PREFER_PRE : 0));
 }
 
 static void
@@ -723,7 +724,8 @@ paste_quote_text (EHTMLEditor *editor,
                cnt_editor,
                text,
                E_CONTENT_EDITOR_INSERT_QUOTE_CONTENT |
-               (is_html ? E_CONTENT_EDITOR_INSERT_TEXT_HTML : E_CONTENT_EDITOR_INSERT_TEXT_PLAIN));
+               (is_html ? E_CONTENT_EDITOR_INSERT_TEXT_HTML : E_CONTENT_EDITOR_INSERT_TEXT_PLAIN) |
+               ((!is_html && editor->priv->paste_plain_prefer_pre) ? 
E_CONTENT_EDITOR_INSERT_CONVERT_PREFER_PRE : 0));
 }
 
 static void
diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h
index 695ce0a72b..032b77cdb3 100644
--- a/src/e-util/e-html-editor-private.h
+++ b/src/e-util/e-html-editor-private.h
@@ -97,6 +97,8 @@ struct _EHTMLEditorPrivate {
        guint recent_spell_languages_merge_id;
 
        gint editor_layout_row;
+
+       gboolean paste_plain_prefer_pre;
 };
 
 void           editor_actions_init             (EHTMLEditor *editor);
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index 6ec7c7d7d3..574fa01a66 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -70,7 +70,8 @@
 
 enum {
        PROP_0,
-       PROP_FILENAME
+       PROP_FILENAME,
+       PROP_PASTE_PLAIN_PREFER_PRE
 };
 
 enum {
@@ -736,6 +737,27 @@ html_editor_realize (GtkWidget *widget)
        html_editor_spell_languages_changed (E_HTML_EDITOR (widget));
 }
 
+static void
+html_editor_set_paste_plain_prefer_pre (EHTMLEditor *editor,
+                                       gboolean value)
+{
+       g_return_if_fail (E_IS_HTML_EDITOR (editor));
+
+       if ((editor->priv->paste_plain_prefer_pre ? 1 : 0) != (value ? 1 : 0)) {
+               editor->priv->paste_plain_prefer_pre = value;
+
+               g_object_notify (G_OBJECT (editor), "paste-plain-prefer-pre");
+       }
+}
+
+static gboolean
+html_editor_get_paste_plain_prefer_pre (EHTMLEditor *editor)
+{
+       g_return_val_if_fail (E_IS_HTML_EDITOR (editor), FALSE);
+
+       return editor->priv->paste_plain_prefer_pre;
+}
+
 static void
 html_editor_set_property (GObject *object,
                           guint property_id,
@@ -749,6 +771,11 @@ html_editor_set_property (GObject *object,
                                g_value_get_string (value));
                        return;
 
+               case PROP_PASTE_PLAIN_PREFER_PRE:
+                       html_editor_set_paste_plain_prefer_pre (
+                               E_HTML_EDITOR (object),
+                               g_value_get_boolean (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -766,6 +793,12 @@ html_editor_get_property (GObject *object,
                                value, e_html_editor_get_filename (
                                E_HTML_EDITOR (object)));
                        return;
+
+               case PROP_PASTE_PLAIN_PREFER_PRE:
+                       g_value_set_boolean (
+                               value, html_editor_get_paste_plain_prefer_pre (
+                               E_HTML_EDITOR (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -776,6 +809,7 @@ html_editor_constructed (GObject *object)
 {
        EHTMLEditor *editor = E_HTML_EDITOR (object);
        EHTMLEditorPrivate *priv = editor->priv;
+       GSettings *settings;
        GdkRGBA transparent = { 0, 0, 0, 0 };
        GtkWidget *widget;
        GtkToolbar *toolbar;
@@ -922,6 +956,15 @@ html_editor_constructed (GObject *object)
        gtk_widget_show_all (GTK_WIDGET (tool_item));
 
        g_signal_connect_after (object, "realize", G_CALLBACK (html_editor_realize), NULL);
+
+       settings = e_util_ref_settings ("org.gnome.evolution.mail");
+
+       g_settings_bind (
+               settings, "composer-paste-plain-prefer-pre",
+               editor, "paste-plain-prefer-pre",
+               G_SETTINGS_BIND_GET);
+
+       g_object_unref (settings);
 }
 
 static void
@@ -1015,6 +1058,17 @@ e_html_editor_class_init (EHTMLEditorClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_STATIC_STRINGS));
 
+       g_object_class_install_property (
+               object_class,
+               PROP_PASTE_PLAIN_PREFER_PRE,
+               g_param_spec_boolean (
+                       "paste-plain-prefer-pre",
+                       NULL,
+                       NULL,
+                       FALSE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS));
+
        signals[UPDATE_ACTIONS] = g_signal_new (
                "update-actions",
                G_TYPE_FROM_CLASS (class),
diff --git a/src/e-util/e-util-enums.h b/src/e-util/e-util-enums.h
index 8d3fe55a47..f87e598cf2 100644
--- a/src/e-util/e-util-enums.h
+++ b/src/e-util/e-util-enums.h
@@ -150,16 +150,18 @@ typedef enum {
  * @E_CONTENT_EDITOR_INSERT_REPLACE_ALL:
  * @E_CONTENT_EDITOR_INSERT_TEXT_HTML:
  * @E_CONTENT_EDITOR_INSERT_TEXT_PLAIN:
+ * @E_CONTENT_EDITOR_INSERT_CONVERT_PREFER_PRE: Set when should convert plain text into <pre> instead of 
<div>. Since 3.40
  *
  * Since: 3.22
  **/
 typedef enum {
-       E_CONTENT_EDITOR_INSERT_NONE            = 0,
-       E_CONTENT_EDITOR_INSERT_CONVERT         = 1 << 0,
-       E_CONTENT_EDITOR_INSERT_QUOTE_CONTENT   = 1 << 1,
-       E_CONTENT_EDITOR_INSERT_REPLACE_ALL     = 1 << 2,
-       E_CONTENT_EDITOR_INSERT_TEXT_HTML       = 1 << 3,
-       E_CONTENT_EDITOR_INSERT_TEXT_PLAIN      = 1 << 4,
+       E_CONTENT_EDITOR_INSERT_NONE                    = 0,
+       E_CONTENT_EDITOR_INSERT_CONVERT                 = 1 << 0,
+       E_CONTENT_EDITOR_INSERT_QUOTE_CONTENT           = 1 << 1,
+       E_CONTENT_EDITOR_INSERT_REPLACE_ALL             = 1 << 2,
+       E_CONTENT_EDITOR_INSERT_TEXT_HTML               = 1 << 3,
+       E_CONTENT_EDITOR_INSERT_TEXT_PLAIN              = 1 << 4,
+       E_CONTENT_EDITOR_INSERT_CONVERT_PREFER_PRE      = 1 << 5
 } EContentEditorInsertContentFlags;
 
 /**
diff --git a/src/e-util/test-html-editor-units-bugs.c b/src/e-util/test-html-editor-units-bugs.c
index d38a1247bf..0ff8d9871b 100644
--- a/src/e-util/test-html-editor-units-bugs.c
+++ b/src/e-util/test-html-editor-units-bugs.c
@@ -746,6 +746,8 @@ test_bug_773164 (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("This is paragraph 1\n\nThis is paragraph 2\n\nThis is a longer 
paragraph 3", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:plain\n"
                "undo:save\n"
@@ -961,6 +963,8 @@ test_bug_780275_html (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:html\n"
                "type:line 0\n"
@@ -999,6 +1003,8 @@ test_bug_780275_plain (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:plain\n"
                "type:line 0\n"
diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c
index f5126d1a1d..d97ea2a5b8 100644
--- a/src/e-util/test-html-editor-units.c
+++ b/src/e-util/test-html-editor-units.c
@@ -4348,11 +4348,28 @@ test_paste_multiline_plain2html (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3\n", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", FALSE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:html\n"
                "type:text before \n"
                "action:paste\n"
                "type:text after\n",
+               HTML_PREFIX "<div>text before line 1</div><div>line 2</div><div>line 3</div><div>text 
after</div>" HTML_SUFFIX,
+               "text before line 1\nline 2\nline 3\ntext after\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "seq:C\n"
+               "type:a\n"
+               "seq:cD\n"
+               "type:text before \n"
+               "action:paste\n"
+               "type:text after\n",
                HTML_PREFIX "<div>text before line 1</div><pre>line 2</pre><pre>line 3</pre><pre>text 
after</pre>" HTML_SUFFIX,
                "text before line 1\nline 2\nline 3\ntext after\n"))
                g_test_fail ();
@@ -4363,12 +4380,32 @@ test_paste_multiline_plain2plain (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", FALSE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:plain\n"
                "type:text before \n"
                "action:paste\n"
                "type:\\ntext after\n",
                HTML_PREFIX "<div style=\"width: 71ch;\">text before line 1</div>"
+               "<div style=\"width: 71ch;\">line 2</div>"
+               "<div style=\"width: 71ch;\">line 3</div>"
+               "<div style=\"width: 71ch;\">text after</div>" HTML_SUFFIX,
+               "text before line 1\nline 2\nline 3\ntext after\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "seq:C\n"
+               "type:a\n"
+               "seq:cD\n"
+               "type:text before \n"
+               "action:paste\n"
+               "type:\\ntext after\n",
+               HTML_PREFIX "<div style=\"width: 71ch;\">text before line 1</div>"
                "<pre>line 2</pre>"
                "<pre>line 3</pre>"
                "<pre>text after</pre>" HTML_SUFFIX,
@@ -4511,6 +4548,8 @@ test_paste_quoted_multiline_plain2html (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3\n", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", FALSE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:html\n"
                "type:text before \n"
@@ -4518,6 +4557,32 @@ test_paste_quoted_multiline_plain2html (TestFixture *fixture)
                "type:\\n\n" /* stop quotting */
                "type:text after\n",
                HTML_PREFIX "<div>text before </div>"
+               "<blockquote type=\"cite\" " BLOCKQUOTE_STYLE "><div>line 1</div>"
+               "<div>line 2</div>"
+               "<div>line 3</div>"
+               "<div><br></div></blockquote>"
+               "<div>text after</div>" HTML_SUFFIX,
+               "text before \n"
+               "> line 1\n"
+               "> line 2\n"
+               "> line 3\n"
+               "> \n"
+               "text after\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "seq:C\n"
+               "type:a\n"
+               "seq:cD\n"
+               "type:text before \n"
+               "action:paste-quote\n"
+               "type:\\n\n" /* stop quotting */
+               "type:text after\n",
+               HTML_PREFIX "<div>text before </div>"
                "<blockquote type=\"cite\" " BLOCKQUOTE_STYLE "><pre>line 1</pre>"
                "<pre>line 2</pre>"
                "<pre>line 3</pre>"
@@ -4537,6 +4602,8 @@ test_paste_quoted_multiline_plain2plain (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", FALSE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:plain\n"
                "type:text before \n"
@@ -4544,6 +4611,30 @@ test_paste_quoted_multiline_plain2plain (TestFixture *fixture)
                "type:\\n\n" /* stop quotting */
                "type:text after\n",
                HTML_PREFIX "<div style=\"width: 71ch;\">text before </div>"
+               "<blockquote type=\"cite\"><div>" QUOTE_SPAN (QUOTE_CHR) "line 1</div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 2</div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 3</div></blockquote>"
+               "<div style=\"width: 71ch;\">text after</div>" HTML_SUFFIX,
+               "text before \n"
+               "> line 1\n"
+               "> line 2\n"
+               "> line 3\n"
+               "text after\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "seq:C\n"
+               "type:a\n"
+               "seq:cD\n"
+               "type:text before \n"
+               "action:paste-quote\n"
+               "type:\\n\n" /* stop quotting */
+               "type:text after\n",
+               HTML_PREFIX "<div style=\"width: 71ch;\">text before </div>"
                "<blockquote type=\"cite\"><pre>" QUOTE_SPAN (QUOTE_CHR) "line 1</pre>"
                "<pre>" QUOTE_SPAN (QUOTE_CHR) "line 2</pre>"
                "<pre>" QUOTE_SPAN (QUOTE_CHR) "line 3</pre></blockquote>"
@@ -6827,6 +6918,8 @@ test_delete_quoted_selection (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\n\nline 2\n", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", FALSE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:plain\n"
                "type:line 0\n"
@@ -6842,6 +6935,40 @@ test_delete_quoted_selection (TestFixture *fixture)
                "type:X\n",
                HTML_PREFIX "<div style=\"width: 71ch;\">line 0</div>"
                "<blockquote type=\"cite\">"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 1</div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "<br></div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 2</div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "X</div>"
+               "</blockquote>"
+               HTML_SUFFIX,
+               "line 0\n"
+               "> line 1\n"
+               "> \n"
+               "> line 2\n"
+               "> X\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "seq:C\n"
+               "type:a\n"
+               "seq:cD\n"
+               "type:line 0\n"
+               "seq:n\n"
+               "action:paste-quote\n"
+               "undo:save\n" /* 1 */
+               "seq:SuusD\n"
+               "undo:undo\n"
+               "undo:test\n"
+               "undo:redo\n"
+               "undo:undo\n"
+               "seq:r\n"
+               "type:X\n",
+               HTML_PREFIX "<div style=\"width: 71ch;\">line 0</div>"
+               "<blockquote type=\"cite\">"
                "<pre>" QUOTE_SPAN (QUOTE_CHR) "line 1</pre>"
                "<pre>" QUOTE_SPAN (QUOTE_CHR) "<br></pre>"
                "<pre>" QUOTE_SPAN (QUOTE_CHR) "line 2</pre>"
@@ -6857,10 +6984,12 @@ test_delete_quoted_selection (TestFixture *fixture)
 }
 
 static void
-test_delete_quoted_multiselect (TestFixture *fixture)
+test_delete_quoted_multiselect_pre (TestFixture *fixture)
 {
        test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
 
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", TRUE);
+
        if (!test_utils_run_simple_test (fixture,
                "mode:html\n"
                "action:paste-quote\n"
@@ -6935,6 +7064,87 @@ test_delete_quoted_multiselect (TestFixture *fixture)
                g_test_fail ();
 }
 
+static void
+test_delete_quoted_multiselect_div (TestFixture *fixture)
+{
+       test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
+
+       test_utils_fixture_change_setting_boolean (fixture, "org.gnome.evolution.mail", 
"composer-paste-plain-prefer-pre", FALSE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "mode:html\n"
+               "action:paste-quote\n"
+               "type:X\n"
+               "undo:save\n" /* 1 */
+               "seq:ChcrrSdsD\n",
+               HTML_PREFIX "<blockquote type=\"cite\" " BLOCKQUOTE_STYLE ">"
+               "<div>line 2</div>"
+               "<div>line 3X</div>"
+               "</blockquote>"
+               HTML_SUFFIX,
+               "> line 2\n"
+               "> line 3X\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       if (!test_utils_run_simple_test (fixture,
+               "undo:undo\n"
+               "undo:test\n"
+               "undo:redo\n"
+               "undo:drop:1\n"
+               "seq:Cec\n" /* Go to the end of the document (Ctrl+End) */
+               "type:\\nY\n",
+               HTML_PREFIX "<blockquote type=\"cite\" " BLOCKQUOTE_STYLE ">"
+               "<div>line 2</div>"
+               "<div>line 3X</div>"
+               "</blockquote>"
+               "<div>Y</div>"
+               HTML_SUFFIX,
+               "> line 2\n"
+               "> line 3X\n"
+               "Y\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       test_utils_insert_content (fixture, "<body></body>", E_CONTENT_EDITOR_INSERT_REPLACE_ALL | 
E_CONTENT_EDITOR_INSERT_TEXT_HTML);
+
+       if (!test_utils_run_simple_test (fixture,
+               "mode:plain\n"
+               "action:paste-quote\n"
+               "type:X\n"
+               "undo:save\n" /* 1 */
+               "seq:ChcrrSdsD\n",
+               HTML_PREFIX "<blockquote type=\"cite\">"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 2</div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 3X</div>"
+               "</blockquote>"
+               HTML_SUFFIX,
+               "> line 2\n"
+               "> line 3X\n")) {
+               g_test_fail ();
+               return;
+       }
+
+       if (!test_utils_run_simple_test (fixture,
+               "undo:undo\n"
+               "undo:test\n"
+               "undo:redo\n"
+               "seq:Cec\n" /* Go to the end of the document (Ctrl+End) */
+               "type:\\nY\n",
+               HTML_PREFIX "<blockquote type=\"cite\">"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 2</div>"
+               "<div>" QUOTE_SPAN (QUOTE_CHR) "line 3X</div>"
+               "</blockquote>"
+               "<div style=\"width: 71ch;\">Y</div>"
+               HTML_SUFFIX,
+               "> line 2\n"
+               "> line 3X\n"
+               "Y\n"))
+               g_test_fail ();
+}
+
 static void
 test_replace_dialog (TestFixture *fixture)
 {
@@ -7538,7 +7748,8 @@ main (gint argc,
        test_utils_add_test ("/delete/quoted", test_delete_quoted);
        test_utils_add_test ("/delete/after-quoted", test_delete_after_quoted);
        test_utils_add_test ("/delete/quoted-selection", test_delete_quoted_selection);
-       test_utils_add_test ("/delete/quoted-multiselect", test_delete_quoted_multiselect);
+       test_utils_add_test ("/delete/quoted-multiselect-pre", test_delete_quoted_multiselect_pre);
+       test_utils_add_test ("/delete/quoted-multiselect-div", test_delete_quoted_multiselect_div);
        test_utils_add_test ("/replace/dialog", test_replace_dialog);
        test_utils_add_test ("/replace/dialog-all", test_replace_dialog_all);
        test_utils_add_test ("/wrap/basic", test_wrap_basic);
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index 26cff463cf..894c3fd671 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -71,7 +71,8 @@ enum {
        PROP_MAGIC_SMILEYS,
        PROP_UNICODE_SMILEYS,
        PROP_WRAP_QUOTED_TEXT_IN_REPLIES,
-       PROP_MINIMUM_FONT_SIZE
+       PROP_MINIMUM_FONT_SIZE,
+       PROP_PASTE_PLAIN_PREFER_PRE
 };
 
 struct _EWebKitEditorPrivate {
@@ -88,6 +89,7 @@ struct _EWebKitEditorPrivate {
        gboolean can_paste;
        gboolean can_undo;
        gboolean can_redo;
+       gboolean paste_plain_prefer_pre;
 
        guint32 style_flags;
        guint32 temporary_style_flags; /* that's for collapsed selection, format changes only after something 
is typed */
@@ -1970,6 +1972,7 @@ webkit_editor_insert_content (EContentEditor *editor,
                               EContentEditorInsertContentFlags flags)
 {
        EWebKitEditor *wk_editor;
+       gboolean prefer_pre;
 
        wk_editor = E_WEBKIT_EDITOR (editor);
 
@@ -1987,11 +1990,13 @@ webkit_editor_insert_content (EContentEditor *editor,
                return;
        }
 
+       prefer_pre = (flags & E_CONTENT_EDITOR_INSERT_CONVERT_PREFER_PRE) != 0;
+
        if ((flags & E_CONTENT_EDITOR_INSERT_CONVERT) &&
            !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL)) {
                e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
-                       "EvoEditor.InsertContent(%s, %x, %x);",
-                       content, (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0, FALSE);
+                       "EvoEditor.InsertContent(%s, %x, %x, %x);",
+                       content, (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0, FALSE, prefer_pre);
        } else if ((flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL) &&
                   (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML)) {
                if ((strstr (content, "data-evo-draft") ||
@@ -2050,13 +2055,13 @@ webkit_editor_insert_content (EContentEditor *editor,
        } else if ((flags & E_CONTENT_EDITOR_INSERT_QUOTE_CONTENT) &&
                   !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL)) {
                e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
-                       "EvoEditor.InsertContent(%s, %x, %x);",
-                       content, (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0, TRUE);
+                       "EvoEditor.InsertContent(%s, %x, %x, %x);",
+                       content, (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0, TRUE, prefer_pre);
        } else if (!(flags & E_CONTENT_EDITOR_INSERT_CONVERT) &&
                   !(flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL)) {
                e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
-                       "EvoEditor.InsertContent(%s, %x, %x);",
-                       content, (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0, FALSE);
+                       "EvoEditor.InsertContent(%s, %x, %x, %x);",
+                       content, (flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0, FALSE, prefer_pre);
        } else {
                g_warning ("%s: Unsupported flags combination (0x%x)", G_STRFUNC, flags);
        }
@@ -4060,6 +4065,27 @@ webkit_editor_set_minimum_font_size (EWebKitEditor *wk_editor,
        }
 }
 
+static void
+webkit_editor_set_paste_plain_prefer_pre (EWebKitEditor *wk_editor,
+                                         gboolean value)
+{
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
+
+       if ((wk_editor->priv->paste_plain_prefer_pre ? 1 : 0) != (value ? 1 : 0)) {
+               wk_editor->priv->paste_plain_prefer_pre = value;
+
+               g_object_notify (G_OBJECT (wk_editor), "paste-plain-prefer-pre");
+       }
+}
+
+static gboolean
+webkit_editor_get_paste_plain_prefer_pre (EWebKitEditor *wk_editor)
+{
+       g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), FALSE);
+
+       return wk_editor->priv->paste_plain_prefer_pre;
+}
+
 static void
 e_webkit_editor_initialize_web_extensions_cb (WebKitWebContext *web_context,
                                              gpointer user_data)
@@ -4166,6 +4192,11 @@ webkit_editor_constructed (GObject *object)
                wk_editor, "wrap-quoted-text-in-replies",
                G_SETTINGS_BIND_GET);
 
+       g_settings_bind (
+               settings, "composer-paste-plain-prefer-pre",
+               wk_editor, "paste-plain-prefer-pre",
+               G_SETTINGS_BIND_GET);
+
        g_object_unref (settings);
 
        settings = e_util_ref_settings ("org.gnome.evolution.shell");
@@ -4510,6 +4541,12 @@ webkit_editor_set_property (GObject *object,
                                E_WEBKIT_EDITOR (object),
                                g_value_get_int (value));
                        return;
+
+               case PROP_PASTE_PLAIN_PREFER_PRE:
+                       webkit_editor_set_paste_plain_prefer_pre (
+                               E_WEBKIT_EDITOR (object),
+                               g_value_get_boolean (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -4744,6 +4781,11 @@ webkit_editor_get_property (GObject *object,
                        g_value_set_int (value,
                                webkit_editor_get_minimum_font_size (E_WEBKIT_EDITOR (object)));
                        return;
+
+               case PROP_PASTE_PLAIN_PREFER_PRE:
+                       g_value_set_boolean (value,
+                               webkit_editor_get_paste_plain_prefer_pre (E_WEBKIT_EDITOR (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -4955,10 +4997,6 @@ webkit_editor_paste_clipboard_targets_cb (GtkClipboard *clipboard,
        }
 
  fallback:
-       /* Order is important here to ensure common use cases are
-        * handled correctly.  See GNOME bug #603715 for details. */
-       /* Prefer plain text over HTML when in the plain text mode, but only
-        * when pasting content from outside the editor view. */
 
        if (!content || !*content) {
                g_free (content);
@@ -4975,7 +5013,8 @@ webkit_editor_paste_clipboard_targets_cb (GtkClipboard *clipboard,
                        E_CONTENT_EDITOR (wk_editor),
                        content,
                        E_CONTENT_EDITOR_INSERT_TEXT_PLAIN |
-                       E_CONTENT_EDITOR_INSERT_CONVERT);
+                       E_CONTENT_EDITOR_INSERT_CONVERT |
+                       (wk_editor->priv->paste_plain_prefer_pre ? E_CONTENT_EDITOR_INSERT_CONVERT_PREFER_PRE 
: 0));
 
        g_free (content);
 }
@@ -5543,7 +5582,6 @@ e_webkit_editor_class_init (EWebKitEditorClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS));
 
-
        g_object_class_install_property (
                object_class,
                PROP_WRAP_QUOTED_TEXT_IN_REPLIES,
@@ -5565,6 +5603,18 @@ e_webkit_editor_class_init (EWebKitEditorClass *class)
                        NULL,
                        G_MININT, G_MAXINT, 0,
                        G_PARAM_READWRITE));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_PASTE_PLAIN_PREFER_PRE,
+               g_param_spec_boolean (
+                       "paste-plain-prefer-pre",
+                       NULL,
+                       NULL,
+                       FALSE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
 }
 
 static void


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