[evolution] Bug 780275 - Problems with citation



commit 69aeaba553d7ada1afd934ab26957e76b56f79bd
Author: Tomas Popela <tpopela redhat com>
Date:   Fri Mar 31 09:41:58 2017 +0200

    Bug 780275 - Problems with citation
    
    There were several issues:
     * We have to have a special function for handling the problem described
       in the bug report due to quotation characters that are used in the
       plain text mode. In HTML mode everything is handled how it should be
       by WebKit and we only need to save the history. Several issues were
       fixed there.
     * I refactored the code so the history is saved outside the function
       that is fixing the previously mentioned issue as that function is
       only needed in the plain text mode (and that could leave the history
       not saved for the HTML mode).
     * A new code was added for correctly handling the situation where
       deleting a selection that starts in the quoted content (on the
       beginning of the block) and ends outside of the quoted content. This
       needs to be done only in plain text mode.
     * Several minor issues were fixed while doing undo and redo in the
       quoted content.
    
    To cover these issues I created new unit tests and extended the current
    ones.

 src/e-util/test-html-editor-units-bugs.c           |   79 ++++++
 src/e-util/test-html-editor-units.c                |   44 +++-
 .../web-extension/e-editor-dom-functions.c         |  265 ++++++++++++--------
 .../web-extension/e-editor-undo-redo-manager.c     |   74 +++++--
 4 files changed, 344 insertions(+), 118 deletions(-)
---
diff --git a/src/e-util/test-html-editor-units-bugs.c b/src/e-util/test-html-editor-units-bugs.c
index 588827c..ee80d6d 100644
--- a/src/e-util/test-html-editor-units-bugs.c
+++ b/src/e-util/test-html-editor-units-bugs.c
@@ -875,6 +875,83 @@ test_bug_779707 (TestFixture *fixture)
                g_test_fail ();
 }
 
+static void
+test_bug_780275_html (TestFixture *fixture)
+{
+       test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "mode:html\n"
+               "type:line 0\n"
+               "seq:nn\n"
+               "action:paste-quote\n"
+               "undo:save\n" /* 1 */
+               "seq:huuuD\n"
+               "undo:undo\n"
+               "undo:test:1\n"
+               "undo:redo\n"
+               "type:X\n"
+               "seq:ddenn\n"
+               "type:line 4\n"
+               "undo:drop\n"
+               "undo:save\n" /* 1 */
+               "seq:hSuusD\n"
+               "undo:undo\n"
+               "undo:test:1\n"
+               "undo:redo\n"
+               "",
+               HTML_PREFIX "<div>line 0</div>"
+               "<blockquote type=\"cite\">"
+               "<div>Xline 1</div>"
+               "<div>line 2</div>"
+               "</blockquote>"
+               "<div>line 4</div>"
+               HTML_SUFFIX,
+               "line 0\n"
+               "> Xline 1\n"
+               "> line 2\n"
+               "line 4"))
+               g_test_fail ();
+}
+
+static void
+test_bug_780275_plain (TestFixture *fixture)
+{
+       test_utils_set_clipboard_text ("line 1\nline 2\nline 3", FALSE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "mode:plain\n"
+               "type:line 0\n"
+               "seq:nn\n"
+               "action:paste-quote\n"
+               "undo:save\n" /* 1 */
+               "seq:huuuD\n"
+               "undo:undo\n"
+               "undo:test:1\n"
+               "undo:redo\n"
+               "type:X\n"
+               "seq:ddenn\n"
+               "type:line 4\n"
+               "undo:drop\n"
+               "undo:save\n" /* 1 */
+               "seq:hSuusD\n"
+               "undo:undo\n"
+               "undo:test:1\n"
+               "undo:redo\n",
+               HTML_PREFIX "<div style=\"width: 71ch;\">line 0</div>"
+               "<blockquote type=\"cite\">"
+               "<div style=\"width: 71ch;\">&gt; Xline 1</div>"
+               "<div style=\"width: 71ch;\">&gt; line 2</div>"
+               "</blockquote>"
+               "<div style=\"width: 71ch;\">line 4</div>"
+               HTML_SUFFIX,
+               "line 0\n"
+               "> Xline 1\n"
+               "> line 2\n"
+               "line 4"))
+               g_test_fail ();
+}
+
 void
 test_add_html_editor_bug_tests (void)
 {
@@ -897,4 +974,6 @@ test_add_html_editor_bug_tests (void)
        test_utils_add_test ("/bug/775042", test_bug_775042);
        test_utils_add_test ("/bug/775691", test_bug_775691);
        test_utils_add_test ("/bug/779707", test_bug_779707);
+       test_utils_add_test ("/bug/780275/html", test_bug_780275_html);
+       test_utils_add_test ("/bug/780275/plain", test_bug_780275_plain);
 }
diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c
index f607850..dcd4171 100644
--- a/src/e-util/test-html-editor-units.c
+++ b/src/e-util/test-html-editor-units.c
@@ -2588,8 +2588,13 @@ test_delete_quoted (TestFixture *fixture)
                E_CONTENT_EDITOR_INSERT_REPLACE_ALL | E_CONTENT_EDITOR_INSERT_TEXT_HTML);
 
        if (!test_utils_run_simple_test (fixture,
-               "seq:dddddSusDdd\n"
-               "type:b",
+               "seq:ddddd\n"
+               "undo:save\n" /* 1 */
+               "seq:SusDdd\n"
+               "type:b\n"
+               "undo:undo:2\n"
+               "undo:test\n"
+               "undo:redo:2",
                HTML_PREFIX "<div style=\"width: 71ch;\">On Thu, 2016-09-15 at 08:08 -0400, user wrote:</div>"
                "<blockquote type=\"cite\">"
                "<div style=\"width: 71ch;\">&gt; a</div>"
@@ -2636,6 +2641,40 @@ test_delete_after_quoted (TestFixture *fixture)
 }
 
 static void
+test_delete_quoted_selection (TestFixture *fixture)
+{
+       test_utils_set_clipboard_text ("line 1\n\nline 2\n", FALSE);
+
+       if (!test_utils_run_simple_test (fixture,
+               "mode:plain\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:d\n"
+               "type:X\n",
+               HTML_PREFIX "<div style=\"width: 71ch;\">line 0</div>"
+               "<blockquote type=\"cite\">"
+               "<div style=\"width: 71ch;\">&gt; line 1</div>"
+               "<div style=\"width: 71ch;\">&gt; <br></div>"
+               "<div style=\"width: 71ch;\">&gt; line 2</div>"
+               "<div style=\"width: 71ch;\">&gt; X</div>"
+               "</blockquote>"
+               HTML_SUFFIX,
+               "line 0\n"
+               "> line 1\n"
+               "> \n"
+               "> line 2\n"
+               "> X"))
+               g_test_fail ();
+}
+
+static void
 test_replace_dialog (TestFixture *fixture)
 {
        if (!test_utils_run_simple_test (fixture,
@@ -2844,6 +2883,7 @@ main (gint argc,
        test_utils_add_test ("/undo/link-paste/plain", test_undo_link_paste_plain);
        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 ("/replace/dialog", test_replace_dialog);
        test_utils_add_test ("/replace-all/dialog", test_replace_dialog_all);
 
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 26e152e..e97a9ab 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
@@ -9210,7 +9210,7 @@ save_history_for_delete_or_backspace (EEditorPage *editor_page,
        if (webkit_dom_range_get_collapsed (range, NULL)) {
                gboolean removing_from_anchor = FALSE;
                WebKitDOMRange *range_clone = NULL;
-               WebKitDOMNode *node, *next_block = NULL;
+               WebKitDOMNode *node;
 
                e_editor_page_block_selection_changed (editor_page);
 
@@ -9309,25 +9309,49 @@ save_history_for_delete_or_backspace (EEditorPage *editor_page,
 
                                                        fragment = 
webkit_dom_document_create_document_fragment (document);
                                                        if (delete_key) {
+                                                               WebKitDOMNode *clone;
+
+                                                               clone = webkit_dom_node_clone_node_with_error 
(actual_block, TRUE, NULL);
+                                                               if (e_editor_dom_get_citation_level 
(actual_block, FALSE) > 0)
+                                                                       webkit_dom_element_set_attribute (
+                                                                               WEBKIT_DOM_ELEMENT (clone),
+                                                                               "data-evo-quoted",
+                                                                               "",
+                                                                               NULL);
                                                                webkit_dom_node_append_child (
-                                                                       WEBKIT_DOM_NODE (fragment),
-                                                                       webkit_dom_node_clone_node_with_error 
(actual_block, TRUE, NULL),
-                                                                       NULL);
+                                                                       WEBKIT_DOM_NODE (fragment), clone, 
NULL);
+
+                                                               clone = webkit_dom_node_clone_node_with_error 
(tmp_block, TRUE, NULL);
+                                                               if (e_editor_dom_get_citation_level 
(tmp_block, FALSE) > 0)
+                                                                       webkit_dom_element_set_attribute (
+                                                                               WEBKIT_DOM_ELEMENT (clone),
+                                                                               "data-evo-quoted",
+                                                                               "",
+                                                                               NULL);
                                                                webkit_dom_node_append_child (
-                                                                       WEBKIT_DOM_NODE (fragment),
-                                                                       webkit_dom_node_clone_node_with_error 
(tmp_block, TRUE, NULL),
-                                                                       NULL);
-                                                               if (delete_key)
-                                                                       next_block = tmp_block;
+                                                                       WEBKIT_DOM_NODE (fragment), clone, 
NULL);
                                                        } else {
+                                                               WebKitDOMNode *clone;
+
+                                                               clone = webkit_dom_node_clone_node_with_error 
(tmp_block, TRUE, NULL);
+                                                               if (e_editor_dom_get_citation_level 
(tmp_block, FALSE) > 0)
+                                                                       webkit_dom_element_set_attribute (
+                                                                               WEBKIT_DOM_ELEMENT (clone),
+                                                                               "data-evo-quoted",
+                                                                               "",
+                                                                               NULL);
                                                                webkit_dom_node_append_child (
-                                                                       WEBKIT_DOM_NODE (fragment),
-                                                                       webkit_dom_node_clone_node_with_error 
(tmp_block, TRUE, NULL),
-                                                                       NULL);
+                                                                       WEBKIT_DOM_NODE (fragment), clone, 
NULL);
+
+                                                               clone = webkit_dom_node_clone_node_with_error 
(actual_block, TRUE, NULL);
+                                                               if (e_editor_dom_get_citation_level 
(tmp_block, FALSE) > 0)
+                                                                       webkit_dom_element_set_attribute (
+                                                                               WEBKIT_DOM_ELEMENT (clone),
+                                                                               "data-evo-quoted",
+                                                                               "",
+                                                                               NULL);
                                                                webkit_dom_node_append_child (
-                                                                       WEBKIT_DOM_NODE (fragment),
-                                                                       webkit_dom_node_clone_node_with_error 
(actual_block, TRUE, NULL),
-                                                                       NULL);
+                                                                       WEBKIT_DOM_NODE (fragment), clone, 
NULL);
                                                        }
                                                        g_object_set_data (
                                                                G_OBJECT (fragment),
@@ -9471,16 +9495,6 @@ save_history_for_delete_or_backspace (EEditorPage *editor_page,
                        }
                }
 
-               /* If concatenating two blocks with pressing Delete on the end
-                * of the previous one and the next node contain content that
-                * is wrapped on multiple lines, the last line will by separated
-                * by WebKit to the separate block. To avoid it let's remove
-                * all quoting and wrapping from the next paragraph. */
-               if (next_block) {
-                       e_editor_dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (next_block));
-                       e_editor_dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (next_block));
-               }
-
                e_editor_page_unblock_selection_changed (editor_page);
        } else {
                WebKitDOMElement *tmp_element;
@@ -9639,18 +9653,23 @@ e_editor_dom_fix_structure_after_delete_before_quoted_content (EEditorPage *edit
                next_block = webkit_dom_node_get_next_sibling (block);
 
                /* Next block is quoted content */
-               if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_block))
-                       goto restore;
+               if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_block)) {
+                       e_editor_dom_selection_restore (editor_page);
+                       return FALSE;
+               }
 
                /* Delete was pressed in block without any content */
-               if (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
-                       goto restore;
+               if (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker))) {
+                       e_editor_dom_selection_restore (editor_page);
+                       return FALSE;
+               }
 
                /* If there is just BR element go ahead */
                node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
-               if (node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node))
-                       goto restore;
-               else {
+               if (node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
+                       e_editor_dom_selection_restore (editor_page);
+                       return FALSE;
+               } else {
                        if (key_code != ~0) {
                                e_editor_dom_selection_restore (editor_page);
                                save_history_for_delete_or_backspace (
@@ -9663,6 +9682,12 @@ e_editor_dom_fix_structure_after_delete_before_quoted_content (EEditorPage *edit
 
                        if (delete_key) {
                                /* To the beginning of the next block. */
+                               while (next_block && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_block))
+                                       next_block = webkit_dom_node_get_first_child (next_block);
+
+                               if (element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted"))
+                                       next_block = webkit_dom_node_get_next_sibling (next_block);
+
                                e_editor_dom_move_caret_into_element (editor_page, WEBKIT_DOM_ELEMENT 
(next_block), TRUE);
                        } else {
                                WebKitDOMNode *prev_block;
@@ -9678,72 +9703,10 @@ e_editor_dom_fix_structure_after_delete_before_quoted_content (EEditorPage *edit
 
                        return TRUE;
                }
-       } else {
-               WebKitDOMNode *end_block, *parent;
-
-               /* Let the quote marks be selectable to nearly correctly remove the
-                * selection. Corrections after are done in body_keyup_event_cb. */
-               enable_quote_marks_select (document);
-
-               parent = webkit_dom_node_get_parent_node (
-                       WEBKIT_DOM_NODE (selection_start_marker));
-               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent) ||
-                   element_has_tag (WEBKIT_DOM_ELEMENT (parent), "b") ||
-                   element_has_tag (WEBKIT_DOM_ELEMENT (parent), "i") ||
-                   element_has_tag (WEBKIT_DOM_ELEMENT (parent), "u"))
-                       node = webkit_dom_node_get_previous_sibling (parent);
-               else
-                       node = webkit_dom_node_get_previous_sibling (
-                               WEBKIT_DOM_NODE (selection_start_marker));
-
-               if (!node || !WEBKIT_DOM_IS_ELEMENT (node))
-                       goto restore;
-
-               if (!element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted"))
-                       goto restore;
-
-               block = e_editor_dom_get_parent_block_node_from_child (
-                       WEBKIT_DOM_NODE (selection_start_marker));
-               end_block = e_editor_dom_get_parent_block_node_from_child (
-                       WEBKIT_DOM_NODE (selection_end_marker));
-
-               /* Situation where the start of the selection is in the beginning
-               + * of the block in quoted content and the end in the beginning of
-               + * content that is after the citation or the selection end is in
-               + * the end of the quoted content (showed by ^). We have to
-               + * mark the start block to correctly restore the structure
-               + * afterwards.
-               *
-               * > |xxx
-               * > xxx^
-               * |xxx
-               */
-               if (e_editor_dom_get_citation_level (end_block, FALSE) > 0) {
-                       WebKitDOMNode *parent;
-
-                       if (webkit_dom_node_get_next_sibling (end_block))
-                               goto restore;
-
-                       parent = webkit_dom_node_get_parent_node (end_block);
-                       while (parent && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent)) {
-                               WebKitDOMNode *next_parent = webkit_dom_node_get_parent_node (parent);
-
-                               if (webkit_dom_node_get_next_sibling (parent) &&
-                                   !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (next_parent))
-                                       goto restore;
-
-                               parent = next_parent;
-                       }
-               }
        }
 
- restore:
        e_editor_dom_selection_restore (editor_page);
 
-       if (key_code != ~0)
-               save_history_for_delete_or_backspace (
-                       editor_page, key_code == HTML_KEY_CODE_DELETE, control_key);
-
        return FALSE;
 }
 
@@ -10653,6 +10616,95 @@ e_editor_dom_key_press_event_process_backspace_key (EEditorPage *editor_page)
        return FALSE;
 }
 
+static gboolean
+deleting_block_starting_in_quoted_content (EEditorPage *editor_page,
+                                           glong key_code,
+                                           gboolean control_key)
+{
+       gint citation_level;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *element;
+       WebKitDOMHTMLElement *body;
+       WebKitDOMNode *node, *parent, *block, *sibling;
+       WebKitDOMRange *range = NULL;
+
+       e_editor_dom_selection_save (editor_page);
+
+       document = e_editor_page_get_document (editor_page);
+
+       element = webkit_dom_document_get_element_by_id (
+               document, "-x-evo-selection-start-marker");
+
+       /* Before the caret are just quote characters */
+       sibling = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+       if (!(sibling && WEBKIT_DOM_IS_ELEMENT (sibling) &&
+             element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-quoted"))) {
+               printf ("%s:%d\n", __PRETTY_FUNCTION__, __LINE__);
+               goto out;
+       }
+
+       if (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (sibling))) {
+               printf ("%s:%d\n", __PRETTY_FUNCTION__, __LINE__);
+               goto out;
+       }
+
+       element = webkit_dom_document_get_element_by_id (
+               document, "-x-evo-selection-end-marker");
+
+       citation_level = e_editor_dom_get_citation_level (WEBKIT_DOM_NODE (element), FALSE);
+
+       enable_quote_marks_select (document);
+       e_editor_dom_selection_restore (editor_page);
+
+       if (key_code != ~0)
+               save_history_for_delete_or_backspace (
+                       editor_page, key_code == HTML_KEY_CODE_DELETE, control_key);
+
+       e_editor_dom_exec_command (editor_page, E_CONTENT_EDITOR_COMMAND_DELETE, NULL);
+
+       range = e_editor_dom_get_current_range (editor_page);
+       node = webkit_dom_range_get_end_container (range, NULL);
+
+       block = e_editor_dom_get_parent_block_node_from_child (node);
+       parent = webkit_dom_node_get_parent_node (block);
+       body = webkit_dom_document_get_body (document);
+       while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (parent)))
+               parent = webkit_dom_node_get_parent_node (parent);
+
+       if (!citation_level) {
+               e_editor_dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (block));
+               e_editor_dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (block));
+
+               webkit_dom_node_insert_before (
+                       WEBKIT_DOM_NODE (body),
+                       block,
+                       webkit_dom_node_get_next_sibling (parent),
+                       NULL);
+       } else {
+               WebKitDOMNode *last_child = webkit_dom_node_get_last_child (block);
+
+               if (WEBKIT_DOM_IS_ELEMENT (last_child) &&
+                   element_has_class (WEBKIT_DOM_ELEMENT (last_child), "-x-evo-quoted")) {
+                       webkit_dom_node_append_child (
+                               block,
+                               WEBKIT_DOM_NODE (webkit_dom_document_create_element (document, "br", NULL)),
+                               NULL);
+               }
+
+       }
+
+       e_editor_dom_disable_quote_marks_select (editor_page);
+       e_editor_dom_move_caret_into_element (editor_page, WEBKIT_DOM_ELEMENT (block), TRUE);
+
+       g_clear_object (&range);
+
+       return TRUE;
+ out:
+       e_editor_dom_selection_restore (editor_page);
+
+       return FALSE;
+}
+
 gboolean
 e_editor_dom_key_press_event_process_delete_or_backspace_key (EEditorPage *editor_page,
                                                               glong key_code,
@@ -10660,8 +10712,7 @@ e_editor_dom_key_press_event_process_delete_or_backspace_key (EEditorPage *edito
                                                               gboolean delete)
 {
        WebKitDOMDocument *document;
-       gboolean html_mode;
-       gboolean local_delete;
+       gboolean html_mode, local_delete, collapsed;
 
        g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), FALSE);
 
@@ -10688,16 +10739,31 @@ e_editor_dom_key_press_event_process_delete_or_backspace_key (EEditorPage *edito
            delete_last_character_from_previous_line_in_quoted_block (editor_page, key_code, control_key))
                goto out;
 
-       if (e_editor_dom_fix_structure_after_delete_before_quoted_content (editor_page, key_code, 
control_key, FALSE))
+       if (!html_mode && e_editor_dom_fix_structure_after_delete_before_quoted_content (editor_page, 
key_code, control_key, delete))
+               goto out;
+
+       collapsed = e_editor_dom_selection_is_collapsed (editor_page);
+
+       if (!html_mode && !collapsed && deleting_block_starting_in_quoted_content (editor_page, key_code, 
control_key))
                goto out;
 
+       if (!collapsed) {
+               /* Let the quote marks be selectable to nearly correctly remove the
+                * selection. Corrections after are done in body_keyup_event_cb. */
+               enable_quote_marks_select (document);
+       }
+
+       if (key_code != ~0)
+               save_history_for_delete_or_backspace (
+                       editor_page, key_code == HTML_KEY_CODE_DELETE, control_key);
+
        if (local_delete) {
                WebKitDOMElement *selection_start_marker;
                WebKitDOMNode *sibling, *block, *next_block;
 
                /* This needs to be performed just in plain text mode
                 * and when the selection is collapsed. */
-               if (html_mode || !e_editor_dom_selection_is_collapsed (editor_page))
+               if (html_mode)
                        return FALSE;
 
                e_editor_dom_selection_save (editor_page);
@@ -10739,8 +10805,7 @@ e_editor_dom_key_press_event_process_delete_or_backspace_key (EEditorPage *edito
                WebKitDOMElement *selection_start_marker;
                WebKitDOMNode *node, *block, *prev_block, *last_child, *child;
 
-               if (html_mode || !e_editor_dom_selection_is_collapsed (editor_page) ||
-                   e_editor_dom_selection_is_citation (editor_page))
+               if (html_mode || e_editor_dom_selection_is_citation (editor_page))
                        return FALSE;
 
                e_editor_dom_selection_save (editor_page);
diff --git a/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c 
b/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
index a030ef7..293f886 100644
--- a/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
+++ b/src/modules/webkit-editor/web-extension/e-editor-undo-redo-manager.c
@@ -371,12 +371,15 @@ undo_delete (EEditorPage *editor_page,
 
                node = webkit_dom_range_get_end_container (range, NULL);
                block = e_editor_dom_get_parent_block_node_from_child (node);
+               if (webkit_dom_document_fragment_query_selector (event->data.fragment, ".-x-evo-quoted", 
NULL) ||
+                   webkit_dom_document_fragment_query_selector (event->data.fragment, "[data-evo-quoted]", 
NULL)) {
+                       WebKitDOMNodeList *list;
+                       gint ii;
 
-               if (webkit_dom_document_fragment_query_selector (event->data.fragment, ".-x-evo-quoted", 
NULL)) {
                        while ((node = webkit_dom_node_get_first_child (fragment))) {
-                               if (WEBKIT_DOM_IS_ELEMENT (node) &&
-                                   webkit_dom_element_query_selector (WEBKIT_DOM_ELEMENT (node), 
".-x-evo-quoted", NULL))
-
+                               if (WEBKIT_DOM_IS_ELEMENT (node) && (
+                                   webkit_dom_element_query_selector (WEBKIT_DOM_ELEMENT (node), 
".-x-evo-quoted", NULL) ||
+                                   webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (node), 
"data-evo-quoted"))) {
                                        if (e_editor_dom_get_citation_level (block, FALSE) > 0) {
                                                webkit_dom_node_insert_before (
                                                        webkit_dom_node_get_parent_node (block),
@@ -420,6 +423,14 @@ undo_delete (EEditorPage *editor_page,
                                                        NULL);
                                }
                        }
+
+                       list = webkit_dom_document_query_selector_all (
+                               document, "[data-evo-quoted]", NULL);
+                       for (ii = webkit_dom_node_list_get_length (list); ii--;)
+                               webkit_dom_element_remove_attribute (
+                                       WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (list, ii)),
+                                       "data-evo-quoted");
+                       g_clear_object (&list);
                } else {
                        while ((node = webkit_dom_node_get_first_child (fragment))) {
                                webkit_dom_node_insert_before (
@@ -504,7 +515,8 @@ undo_delete (EEditorPage *editor_page,
 
        /* Multi block delete */
        if (WEBKIT_DOM_IS_ELEMENT (first_child) && !single_block) {
-               gboolean delete;
+               gboolean delete, reinserting_blockquote = FALSE;
+               gboolean could_append = FALSE;
                WebKitDOMElement *signature;
                WebKitDOMNode *node, *current_block, *last_child;
                WebKitDOMNode *next_block, *insert_before;
@@ -570,6 +582,7 @@ undo_delete (EEditorPage *editor_page,
 
                current_block = e_editor_dom_get_parent_block_node_from_child (WEBKIT_DOM_NODE (element));
 
+               could_append = !WEBKIT_DOM_IS_TEXT (webkit_dom_node_get_last_child (last_child));
                while (node) {
                        WebKitDOMNode *next_sibling, *parent_node;
 
@@ -619,21 +632,46 @@ undo_delete (EEditorPage *editor_page,
                        } else if (!next_sibling && !webkit_dom_node_is_same_node (parent_node, 
current_block))
                                next_sibling = webkit_dom_node_get_next_sibling (parent_node);
 
-                       if (delete)
+                       if (delete) {
                                remove_node (node);
-                       else
+                       } else if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
+                               WebKitDOMNode *last_node = webkit_dom_node_get_last_child (last_child);
+                               if (!last_node) {
+                                       webkit_dom_node_append_child (last_child, node, NULL);
+                               } else if (WEBKIT_DOM_IS_ELEMENT (last_node) &&
+                                          (element_has_class (WEBKIT_DOM_ELEMENT (last_node), 
"-x-evo-quoted") || could_append)) {
+                                       webkit_dom_node_append_child (last_child, node, NULL);
+                               } else {
+                                       remove_node (node);
+                               }
+                       } else {
                                webkit_dom_node_append_child (last_child, node, NULL);
+                       }
+
                        node = next_sibling;
                }
 
-               /* Get the first block in deleted content. */
-               while (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (first_child))
-                       first_child = webkit_dom_node_get_first_child (first_child);
+               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (first_child) &&
+                   !WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (webkit_dom_node_get_parent_node (current_block))) {
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_parent_node (current_block),
+                               first_child,
+                               current_block,
+                               NULL);
+                       reinserting_blockquote = TRUE;
+                       e_editor_dom_wrap_and_quote_element (
+                               editor_page, WEBKIT_DOM_ELEMENT (webkit_dom_node_get_first_child 
(first_child)));
 
-               /* All the nodes that are in the first block of the deleted content
-                * belongs to the current block right after the caret position. */
-               while ((node = webkit_dom_node_get_first_child (first_child)))
-                       webkit_dom_node_append_child (current_block, node, NULL);
+               } else {
+                       /* Get the first block in deleted content. */
+                       while (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (first_child))
+                               first_child = webkit_dom_node_get_first_child (first_child);
+
+                       /* All the nodes that are in the first block of the deleted content
+                        * belongs to the current block right after the caret position. */
+                       while ((node = webkit_dom_node_get_first_child (first_child)))
+                               webkit_dom_node_append_child (current_block, node, NULL);
+               }
 
                next_block = webkit_dom_node_get_next_sibling (current_block);
                insert_before = next_block;
@@ -659,7 +697,8 @@ undo_delete (EEditorPage *editor_page,
 
                /* Remove the first block from deleted content as its content was already
                 * moved to the right place. */
-               remove_node (first_child);
+               if (!reinserting_blockquote)
+                       remove_node (first_child);
 
                /* Insert the deleted content. */
                if (insert_before)
@@ -675,7 +714,10 @@ undo_delete (EEditorPage *editor_page,
                                WEBKIT_DOM_NODE (fragment),
                                NULL);
 
-               e_editor_dom_wrap_and_quote_element (editor_page, WEBKIT_DOM_ELEMENT (current_block));
+               if (reinserting_blockquote)
+                       remove_node_if_empty (current_block);
+               else
+                       e_editor_dom_wrap_and_quote_element (editor_page, WEBKIT_DOM_ELEMENT (current_block));
 
                if (WEBKIT_DOM_IS_ELEMENT (last_child))
                        e_editor_dom_wrap_and_quote_element (editor_page, WEBKIT_DOM_ELEMENT (last_child));


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