[evolution/wip/webkit2] EHTMLEditorView - Improve the undo/redo in composer



commit ed658ea80cb9768994640c4bc391d2840b33c69f
Author: Tomas Popela <tpopela redhat com>
Date:   Tue Mar 1 20:00:39 2016 +0100

    EHTMLEditorView - Improve the undo/redo in composer

 .../e-html-editor-selection-dom-functions.c        |   12 +-
 .../composer/e-html-editor-undo-redo-manager.c     |  498 +++++--
 .../composer/e-html-editor-view-dom-functions.c    | 1543 +++++++++++++-------
 .../composer/e-html-editor-view-dom-functions.h    |   31 +-
 .../composer/e-html-editor-web-extension.c         |   15 +
 .../composer/e-html-editor-web-extension.h         |    5 +
 6 files changed, 1452 insertions(+), 652 deletions(-)
---
diff --git a/web-extensions/composer/e-html-editor-selection-dom-functions.c 
b/web-extensions/composer/e-html-editor-selection-dom-functions.c
index fea1d67..096e9b6 100644
--- a/web-extensions/composer/e-html-editor-selection-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-selection-dom-functions.c
@@ -2904,7 +2904,7 @@ dom_put_node_into_paragraph (WebKitDOMDocument *document,
 }
 
 static gint
-get_citation_level (WebKitDOMNode *node)
+selection_get_citation_level (WebKitDOMNode *node)
 {
        WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
        gint level = 0;
@@ -3023,7 +3023,7 @@ dom_selection_wrap (WebKitDOMDocument *document,
                after_selection_end = webkit_dom_node_contains (
                        block, WEBKIT_DOM_NODE (selection_end_marker));
 
-               citation_level = get_citation_level (block);
+               citation_level = selection_get_citation_level (block);
                quote = citation_level ? citation_level * 2 : 0;
 
                wrapped_paragraph = dom_wrap_paragraph_length (
@@ -3069,7 +3069,7 @@ dom_wrap_paragraphs_in_document (WebKitDOMDocument *document,
                gint word_wrap_length, quote, citation_level;
                WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);
 
-               citation_level = get_citation_level (node);
+               citation_level = selection_get_citation_level (node);
                quote = citation_level ? citation_level * 2 : 0;
                word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
 
@@ -3101,7 +3101,7 @@ dom_wrap_paragraph (WebKitDOMDocument *document,
        g_return_val_if_fail (WEBKIT_DOM_IS_ELEMENT (paragraph), NULL);
 
        indentation_level = get_indentation_level (paragraph);
-       citation_level = get_citation_level (WEBKIT_DOM_NODE (paragraph));
+       citation_level = selection_get_citation_level (WEBKIT_DOM_NODE (paragraph));
 
        if (node_is_list_or_item (WEBKIT_DOM_NODE (paragraph))) {
                gint list_level = get_list_level (WEBKIT_DOM_NODE (paragraph));
@@ -4999,7 +4999,7 @@ process_block_to_block (WebKitDOMDocument *document,
                if (!next_block && !after_selection_end) {
                        gint citation_level;
 
-                       citation_level = get_citation_level (WEBKIT_DOM_NODE (element));
+                       citation_level = selection_get_citation_level (WEBKIT_DOM_NODE (element));
 
                        if (citation_level > 0) {
                                next_block = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
@@ -5017,7 +5017,7 @@ process_block_to_block (WebKitDOMDocument *document,
                        if (format == E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_BLOCKQUOTE)
                                citation_level = 1;
                        else
-                               citation_level = get_citation_level (WEBKIT_DOM_NODE (element));
+                               citation_level = selection_get_citation_level (WEBKIT_DOM_NODE (element));
 
                        if (citation_level > 0) {
                                gint quote, word_wrap_length;
diff --git a/web-extensions/composer/e-html-editor-undo-redo-manager.c 
b/web-extensions/composer/e-html-editor-undo-redo-manager.c
index d118fd6..dd8dc88 100644
--- a/web-extensions/composer/e-html-editor-undo-redo-manager.c
+++ b/web-extensions/composer/e-html-editor-undo-redo-manager.c
@@ -327,6 +327,70 @@ event_selection_was_collapsed (EHTMLEditorHistoryEvent *ev)
        return (ev->before.start.x == ev->before.end.x) && (ev->before.start.y == ev->before.end.y);
 }
 
+static WebKitDOMNode *
+split_node_into_two (WebKitDOMNode *item,
+                     gint level)
+{
+       gint current_level = 1;
+       WebKitDOMDocument *document;
+       WebKitDOMDocumentFragment *fragment;
+       WebKitDOMNode *parent, *prev_parent = NULL, *tmp = NULL;
+
+       document = webkit_dom_node_get_owner_document (item);
+       fragment = webkit_dom_document_create_document_fragment (document);
+
+       tmp = item;
+       parent = webkit_dom_node_get_parent_node (item);
+       while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+               WebKitDOMNode *clone, *first_child, *insert_before = NULL, *sibling;
+
+               first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+               clone = webkit_dom_node_clone_node (parent, FALSE);
+               webkit_dom_node_insert_before (
+                       WEBKIT_DOM_NODE (fragment), clone, first_child, NULL);
+
+               if (first_child)
+                       insert_before = webkit_dom_node_get_first_child (first_child);
+
+               while (first_child && (sibling = webkit_dom_node_get_next_sibling (first_child)))
+                       webkit_dom_node_insert_before (first_child, sibling, insert_before, NULL);
+
+               while ((sibling = webkit_dom_node_get_next_sibling (tmp)))
+                       webkit_dom_node_append_child (clone, sibling, NULL);
+
+               webkit_dom_node_insert_before (
+                       clone, tmp, webkit_dom_node_get_first_child (clone), NULL);
+
+               prev_parent = parent;
+               tmp = webkit_dom_node_get_next_sibling (parent);
+               parent = webkit_dom_node_get_parent_node (parent);
+               if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+                       first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+                       insert_before = webkit_dom_node_get_first_child (first_child);
+                       while (first_child && (sibling = webkit_dom_node_get_next_sibling (first_child))) {
+                               webkit_dom_node_insert_before (
+                                       first_child, sibling, insert_before, NULL);
+                       }
+               }
+
+               if (current_level >= level && level >= 0)
+                       break;
+
+               current_level++;
+       }
+
+       if (prev_parent) {
+               tmp = webkit_dom_node_insert_before (
+                       parent,
+                       webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+                       webkit_dom_node_get_next_sibling (prev_parent),
+                       NULL);
+               remove_node_if_empty (prev_parent);
+       }
+
+       return tmp;
+}
+
 static void
 undo_delete (WebKitDOMDocument *document,
              EHTMLEditorWebExtension *extension,
@@ -344,7 +408,7 @@ undo_delete (WebKitDOMDocument *document,
        dom_selection = webkit_dom_dom_window_get_selection (dom_window);
        g_object_unref (dom_window);
 
-       fragment = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (event->data.fragment),  TRUE);
+       fragment = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (event->data.fragment), TRUE);
        first_child = webkit_dom_node_get_first_child (fragment);
 
        content = webkit_dom_node_get_text_content (fragment);
@@ -363,60 +427,172 @@ undo_delete (WebKitDOMDocument *document,
                        single_block = WEBKIT_DOM_IS_TEXT (first_child);
        }
 
-       /* Redoing Return key press */
-       if (empty) {
-               WebKitDOMNode *node, *tmp_node;
+       /* Delete or BackSpace pressed in the beginning of a block or on its end. */
+       if (event->type == HISTORY_DELETE && !single_block &&
+           g_object_get_data (G_OBJECT (event->data.fragment), "-x-evo-fragment")) {
+               WebKitDOMNode *node, *block;
 
-               range = get_range_for_point (document, event->before.start);
+               range = get_range_for_point (document, event->after.start);
                webkit_dom_dom_selection_remove_all_ranges (dom_selection);
                webkit_dom_dom_selection_add_range (dom_selection, range);
-               g_object_unref (dom_selection);
 
-               node = webkit_dom_range_get_start_container (range, NULL);
-               g_object_unref (range);
-               if (!node)
-                       return;
-
-               tmp_node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (event->data.fragment));
-               if (WEBKIT_DOM_IS_HTML_LI_ELEMENT (tmp_node) &&
-                   WEBKIT_DOM_IS_HTML_BR_ELEMENT (webkit_dom_node_get_last_child (tmp_node)))
-                       if (return_pressed_in_empty_list_item (document, extension, FALSE))
-                               return;
+               node = webkit_dom_range_get_end_container (range, NULL);
+               block = get_parent_block_node_from_child (node);
+
+               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 (get_citation_level (block, FALSE) > 0) {
+                                               webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (block),
+                                                       node,
+                                                       block,
+                                                       NULL);
+                                       } else {
+                                               WebKitDOMNode *next_block;
+
+                                               next_block = webkit_dom_node_get_next_sibling (block);
+                                               while (next_block && dom_node_is_citation_node (next_block))
+                                                       next_block = webkit_dom_node_get_first_child 
(next_block);
+
+                                               webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (next_block),
+                                                       node,
+                                                       next_block,
+                                                       NULL);
+                                       }
+                               else {
+                                       if (get_citation_level (block, FALSE) > 0) {
+                                               WebKitDOMNode *next_node;
+
+                                               next_node = split_node_into_two (block, -1);
+                                               webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (next_node),
+                                                       node,
+                                                       next_node,
+                                                       NULL);
+                                       } else
+                                               webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (block),
+                                                       node,
+                                                       block,
+                                                       NULL);
+                               }
+                       }
+               } else {
+                       while ((node = webkit_dom_node_get_first_child (fragment))) {
+                               webkit_dom_node_insert_before (
+                                       webkit_dom_node_get_parent_node (block),
+                                       node,
+                                       block,
+                                       NULL);
+                       }
+               }
 
-               if (WEBKIT_DOM_IS_HTML_LI_ELEMENT (webkit_dom_node_get_parent_node (node)))
-                       element = webkit_dom_node_get_parent_element (node);
-               else
-                       element = get_parent_block_element (node);
+               remove_node (block);
 
-               webkit_dom_node_insert_before (
-                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
-                       fragment,
-                       webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element)),
-                       NULL);
+               restore_selection_to_history_event_state (document, event->before);
 
-               dom_selection_restore (document);
                dom_force_spell_check_in_viewport (document, extension);
 
                return;
        }
 
+       /* Redoing Return key press */
+       if (event->type == HISTORY_INPUT && (empty ||
+           g_object_get_data (G_OBJECT (event->data.fragment), "-x-evo-return-key"))) {
+               if (key_press_event_process_return_key (document, extension)) {
+                       body_key_up_event_process_return_key (document, extension);
+                       dom_force_spell_check_in_viewport (document, extension);
+                       return;
+               } else {
+                       WebKitDOMElement *element;
+                       WebKitDOMNode *next_sibling;
+
+                       range = get_range_for_point (document, event->before.start);
+                       webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+                       webkit_dom_dom_selection_add_range (dom_selection, range);
+                       g_object_unref (dom_selection);
+
+                       dom_selection_save (document);
+
+                       element = webkit_dom_document_get_element_by_id (
+                               document, "-x-evo-selection-end-marker");
+
+                       next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+                       if (next_sibling && !(WEBKIT_DOM_IS_HTML_BR_ELEMENT (next_sibling))) {
+                               split_node_into_two (WEBKIT_DOM_NODE (element), 1);
+                       } else {
+                               WebKitDOMNode *block;
+
+                               block = get_parent_block_node_from_child (
+                                       WEBKIT_DOM_NODE (element));
+                               dom_remove_selection_markers (document);
+                               webkit_dom_node_insert_before (
+                                       webkit_dom_node_get_parent_node (block),
+                                       fragment,
+                                       webkit_dom_node_get_next_sibling (block),
+                                       NULL);
+                       }
+                       dom_selection_restore (document);
+
+                       return;
+               }
+       }
+
+       if (!single_block) {
+               if (WEBKIT_DOM_IS_ELEMENT (first_child) &&
+                   !(WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (first_child) ||
+                     WEBKIT_DOM_IS_HTML_PRE_ELEMENT (first_child) ||
+                     (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (first_child) &&
+                      element_has_class (WEBKIT_DOM_ELEMENT (first_child), "-x-evo-paragraph"))))
+                       single_block = TRUE;
+       }
+
        /* Multi block delete */
        if (WEBKIT_DOM_IS_ELEMENT (first_child) && !single_block) {
                gboolean delete;
                WebKitDOMElement *signature;
-               WebKitDOMNode *node, *parent, *last_child;
-               WebKitDOMNode *parent_deleted_content;
-               WebKitDOMNode *parent_current_block;
-               WebKitDOMNode *insert_before;
+               WebKitDOMNode *node, *current_block, *last_child;
+               WebKitDOMNode *next_block, *insert_before;
+               WebKitDOMNode *parent_deleted_content, *parent_current_block;
 
-               range = get_range_for_point (document, event->before.start);
+               range = get_range_for_point (document, event->after.start);
                webkit_dom_dom_selection_remove_all_ranges (dom_selection);
                webkit_dom_dom_selection_add_range (dom_selection, range);
                g_object_unref (range);
                dom_selection_save (document);
 
-               element = webkit_dom_document_get_element_by_id (
-                       document, "-x-evo-selection-start-marker");
+               if ((element = webkit_dom_document_get_element_by_id (document, 
"-x-evo-selection-end-marker"))) {
+                       WebKitDOMNode *next_sibling;
+
+                       if ((next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element))) &&
+                            WEBKIT_DOM_IS_CHARACTER_DATA (next_sibling) &&
+                            webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (next_sibling)) 
== 1) {
+                               gchar *data;
+
+                               data = webkit_dom_character_data_get_data (WEBKIT_DOM_CHARACTER_DATA 
(next_sibling));
+                               if (data && *data == ' ') {
+                                       WebKitDOMElement *hidden_space;
+
+                                       hidden_space = webkit_dom_document_create_element (document, "span", 
NULL);
+                                       webkit_dom_element_set_attribute (
+                                               hidden_space, "data-hidden-space", "", NULL);
+                                       remove_node (next_sibling);
+                                       webkit_dom_node_insert_before (
+                                               webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                                               WEBKIT_DOM_NODE (hidden_space),
+                                               webkit_dom_node_get_previous_sibling (
+                                                       WEBKIT_DOM_NODE (element)),
+                                               NULL);
+                               }
+                               g_free (data);
+                       }
+               }
+
+               element = webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker");
 
                /* Get the last block in deleted content. */
                last_child = webkit_dom_node_get_last_child (fragment);
@@ -429,7 +605,7 @@ undo_delete (WebKitDOMDocument *document,
 
                /* FIXME Ugly hack */
                /* If the selection ended in signature, the structure will be broken
-                * thus we saved the while signature into deleted fragment and we will
+                * thus we saved the whole signature into deleted fragment and we will
                 * restore the whole signature, but we need to remove the rest of the
                 * signature that's left after delete to avoid duplications. */
                signature = webkit_dom_document_query_selector (document, ".-x-evo-signature-wrapper", NULL);
@@ -442,10 +618,13 @@ undo_delete (WebKitDOMDocument *document,
                                element_has_class (WEBKIT_DOM_ELEMENT (tmp_node), "-x-evo-signature-wrapper");
                }
 
+               current_block = get_parent_block_node_from_child (WEBKIT_DOM_NODE (element));
+
                while (node) {
-                       WebKitDOMNode *next_sibling;
+                       WebKitDOMNode *next_sibling, *parent_node;
 
                        next_sibling = webkit_dom_node_get_next_sibling (node);
+                       parent_node = webkit_dom_node_get_parent_node (node);
                        if (!next_sibling && WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
                                /* Check if the whole element was deleted. If so replace it and
                                 * skip the code down there. */
@@ -462,8 +641,10 @@ undo_delete (WebKitDOMDocument *document,
 
                                        tmp_element = webkit_dom_document_get_element_by_id (
                                                document, "-x-evo-tmp-block");
-                                       if (tmp_element)
+                                       if (tmp_element) {
                                                webkit_dom_element_remove_attribute (tmp_element, "id");
+                                               wrap_and_quote_element (document, extension, tmp_element);
+                                       }
 
                                        /* Remove empty blockquotes, if presented. */
                                        tmp_element = webkit_dom_document_query_selector (
@@ -483,7 +664,9 @@ undo_delete (WebKitDOMDocument *document,
 
                                        return;
                                }
-                       }
+                       } 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)
                                remove_node (node);
                        else
@@ -497,18 +680,18 @@ undo_delete (WebKitDOMDocument *document,
 
                /* All the nodes that are in the first block of the deleted content
                 * belongs to the current block right after the caret position. */
-               parent = get_parent_block_node_from_child (WEBKIT_DOM_NODE (element));
                while ((node = webkit_dom_node_get_first_child (first_child)))
-                       webkit_dom_node_append_child (WEBKIT_DOM_NODE (parent), node, NULL);
+                       webkit_dom_node_append_child (current_block, node, NULL);
 
                parent_deleted_content = webkit_dom_node_get_parent_node (first_child);
-               parent_current_block = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (parent));
-               insert_before = webkit_dom_node_get_next_sibling (parent);
+               parent_current_block = webkit_dom_node_get_parent_node (current_block);
+               insert_before = webkit_dom_node_get_next_sibling (current_block);
 
                /* Remove the first block from deleted content as its content was already
                 * moved to the right place. */
                remove_node (first_child);
 
+               next_block = webkit_dom_node_get_next_sibling (current_block);
                /* Move the deleted content back to the body. Start from the next sibling
                 * of the first block (if presented) where the delete occurred. */
                while (parent_deleted_content) {
@@ -528,18 +711,29 @@ undo_delete (WebKitDOMDocument *document,
                        remove_node (parent_deleted_content);
                        parent_deleted_content = tmp;
                        insert_before = webkit_dom_node_get_next_sibling (parent_current_block);
+
+                       if (!insert_before && next_block && WEBKIT_DOM_IS_HTML_BODY_ELEMENT (
+                           webkit_dom_node_get_parent_node (parent_current_block)))
+                               insert_before = split_node_into_two (next_block, -1);
+
                        /* Be sure that we don't go above body. */
                        if (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent_current_block))
                                parent_current_block = webkit_dom_node_get_parent_node (parent_current_block);
                }
 
+               wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (current_block));
+
+               if (WEBKIT_DOM_IS_ELEMENT (last_child))
+                       wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_child));
+
                dom_merge_siblings_if_necessarry (document, event->data.fragment);
 
                dom_selection_restore (document);
                dom_force_spell_check_in_viewport (document, extension);
        } else {
-               gboolean empty_text = FALSE;
-               WebKitDOMNode *nd;
+               gboolean empty_text = FALSE, was_link = FALSE;
+               WebKitDOMNode *prev_sibling, *next_sibling, *nd;
+               WebKitDOMNode *parent;
 
                element = webkit_dom_document_create_element (document, "span", NULL);
 
@@ -574,28 +768,85 @@ undo_delete (WebKitDOMDocument *document,
                        g_free (text);
                }
 
+               parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
                if (!nd || empty_text) {
-                       WebKitDOMNode *parent;
-
-                       parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
-                       if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent)) {
+                       if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent))
                                webkit_dom_node_insert_before (
                                        webkit_dom_node_get_parent_node (parent),
                                        WEBKIT_DOM_NODE (element),
                                        parent,
                                        NULL);
-                       }
                }
 
                /* Insert the deleted content back to the body. */
-               webkit_dom_node_insert_before (
-                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
-                       fragment,
-                       WEBKIT_DOM_NODE (element),
-                       NULL);
+               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent)) {
+                       if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (first_child)) {
+                               WebKitDOMNode *child;
+
+                               while ((child = webkit_dom_node_get_first_child (first_child)))
+                                       webkit_dom_node_append_child (parent, child, NULL);
+
+                               remove_node (first_child);
+
+                               was_link = TRUE;
+                               webkit_dom_node_insert_before (
+                                       webkit_dom_node_get_parent_node (parent),
+                                       fragment,
+                                       webkit_dom_node_get_next_sibling (parent),
+                                       NULL);
+                       } else {
+                               if (g_object_get_data (G_OBJECT (event->data.fragment), 
"-x-evo-removing-from-anchor") ||
+                                   !event_selection_was_collapsed (event)) {
+                                       webkit_dom_node_insert_before (
+                                               webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                                               fragment,
+                                               WEBKIT_DOM_NODE (element),
+                                               NULL);
+                               } else {
+                                       webkit_dom_node_insert_before (
+                                               webkit_dom_node_get_parent_node (parent),
+                                               fragment,
+                                               webkit_dom_node_get_next_sibling (parent),
+                                               NULL);
+                               }
+                       }
+               } else {
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                               fragment,
+                               WEBKIT_DOM_NODE (element),
+                               NULL);
+               }
+
+               webkit_dom_node_normalize (parent);
+               prev_sibling = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+               next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+               if (prev_sibling && next_sibling) {
+                       WebKitDOMNode *clone_prev, *clone_next;
+
+                       clone_prev = webkit_dom_node_clone_node (prev_sibling, FALSE);
+                       clone_next = webkit_dom_node_clone_node (next_sibling, FALSE);
+
+                       if (webkit_dom_node_is_equal_node (clone_prev, clone_next)) {
+                               WebKitDOMNode *child;
+
+                               while ((child = webkit_dom_node_get_first_child (next_sibling)))
+                                       webkit_dom_node_append_child (prev_sibling, child, NULL);
+
+                               remove_node (next_sibling);
+                       }
+               }
 
                remove_node (WEBKIT_DOM_NODE (element));
 
+               if (event->type == HISTORY_DELETE && !e_html_editor_web_extension_get_html_mode (extension) &&
+                   !webkit_dom_document_fragment_query_selector (event->data.fragment, ".-x-evo-quoted", 
NULL)) {
+                       WebKitDOMNode *current_block;
+
+                       current_block = get_parent_block_node_from_child (parent);
+                       wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (current_block));
+               }
+
                /* If the selection markers are presented restore the selection,
                 * otherwise the selection was not collapsed so select the deleted
                 * content as it was before the delete occurred. */
@@ -607,7 +858,7 @@ undo_delete (WebKitDOMDocument *document,
                if (event->type != HISTORY_INPUT) {
                        if (e_html_editor_web_extension_get_magic_smileys_enabled (extension))
                                dom_check_magic_smileys (document, extension);
-                       if (e_html_editor_web_extension_get_magic_links_enabled (extension))
+                       if (!was_link && e_html_editor_web_extension_get_magic_links_enabled (extension))
                                dom_check_magic_links (document, extension, FALSE);
                }
                dom_force_spell_check_for_current_paragraph (document, extension);
@@ -621,55 +872,97 @@ redo_delete (WebKitDOMDocument *document,
              EHTMLEditorWebExtension *extension,
              EHTMLEditorHistoryEvent *event)
 {
+       EHTMLEditorUndoRedoManager *manager;
+       gboolean delete_key, control_key;
+       glong length = 1;
+       gint ii;
        WebKitDOMDocumentFragment *fragment = event->data.fragment;
-       WebKitDOMNode *first_child;
-
-       first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+       WebKitDOMNode *node;
 
+       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
        restore_selection_to_history_event_state (document, event->before);
 
-       if (webkit_dom_document_fragment_query_selector (fragment, "span#-x-evo-selection-start-marker", 
NULL)) {
-               gboolean delete = FALSE, control_key = FALSE;
-               glong length = 1;
-               gint ii;
-               WebKitDOMDOMWindow *dom_window;
-               WebKitDOMDOMSelection *dom_selection;
+       delete_key = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment), 
"-x-evo-delete-key"));
+       control_key = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment), 
"-x-evo-control-key"));
 
-               dom_window = webkit_dom_document_get_default_view (document);
-               g_object_unref (dom_window);
-               dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+       if (!delete_key && key_press_event_process_backspace_key (document, extension))
+               goto out;
+
+       if (key_press_event_process_delete_or_backspace_key (document, extension, ~0, 0, delete_key))
+               goto out;
 
-               control_key = event_selection_was_collapsed (event);
-               if (control_key) {
-                       gchar *text_content;
+       if (control_key) {
+               gchar *text_content;
+
+               text_content = webkit_dom_node_get_text_content (WEBKIT_DOM_NODE (fragment));
+               length = g_utf8_strlen (text_content, -1);
+               control_key = length > 1;
+
+               g_free (text_content);
+       }
 
-                       text_content = webkit_dom_node_get_text_content (WEBKIT_DOM_NODE (fragment));
-                       length = g_utf8_strlen (text_content, -1);
-                       control_key = length > 1;
+       /* 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 (delete_key && GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment), 
"-x-evo-fragment"))) {
+               WebKitDOMNode *current_block, *next_block, *node;
+               WebKitDOMRange *range;
 
-                       g_free (text_content);
+               range = dom_get_current_range (document);
+               node = webkit_dom_range_get_end_container (range, NULL);
+               g_object_unref (range);
+               current_block = get_parent_block_node_from_child (node);
+               if (get_citation_level (current_block, FALSE) > 0 &&
+                   (next_block = webkit_dom_node_get_next_sibling (current_block))) {
+                       dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (next_block));
+                       dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (next_block));
                }
+       }
 
-               /* Check if the event was delete or backspace press. */
-               delete = WEBKIT_DOM_IS_ELEMENT (first_child);
-               delete = delete && element_has_id (WEBKIT_DOM_ELEMENT (first_child), 
"-x-evo-selection-start-marker");
-               for (ii = 0; ii < length; ii++) {
+       for (ii = 0; ii < length; ii++) {
+               dom_exec_command (
+                       document, extension,
+                       delete_key ? E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE :
+                                    E_HTML_EDITOR_VIEW_COMMAND_DELETE,
+                       NULL);
+       }
+
+       /* Really don't know why, but when the selection marker nodes were in
+        * anchors then we need to do an extra delete command otherwise we will
+        * end with two blocks split in half. */
+       node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+       while ((node = webkit_dom_node_get_first_child (node))) {
+               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
                        dom_exec_command (
                                document, extension,
-                               delete ? E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE :
-                                        E_HTML_EDITOR_VIEW_COMMAND_DELETE,
+                               E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE,
                                NULL);
+                       break;
                }
+       }
 
-               g_object_unref (dom_selection);
-       } else {
-               if (!dom_delete_character_from_quoted_line_start (document, extension, ~0, 0))
-                       if (!dom_fix_structure_after_delete_before_quoted_content (document, extension, ~0, 
0))
-                               dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, 
NULL);
-
-               dom_disable_quote_marks_select (document);
+       node = webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment));
+       while ((node = webkit_dom_node_get_last_child (node))) {
+               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
+                       dom_exec_command (
+                               document, extension,
+                               E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE,
+                               NULL);
+                       break;
+               }
        }
 
+       e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, TRUE);
+       e_html_editor_undo_redo_manager_set_operation_in_progress (manager, FALSE);
+       body_input_event_process (document, extension, NULL);
+       e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+       e_html_editor_undo_redo_manager_set_operation_in_progress (manager, TRUE);
+       e_html_editor_web_extension_set_renew_history_after_coordinates (extension, FALSE);
+       body_key_up_event_process_backspace_or_delete (document, extension, delete_key);
+       e_html_editor_web_extension_set_renew_history_after_coordinates (extension, TRUE);
+ out:
        restore_selection_to_history_event_state (document, event->after);
 
        dom_force_spell_check_for_current_paragraph (document, extension);
@@ -1598,7 +1891,6 @@ undo_redo_citation_split (WebKitDOMDocument *document,
                in_situ = TRUE;
 
        if (undo) {
-               gint citation_level = 1, length, word_wrap_length;
                WebKitDOMElement *selection_start, *parent;
                WebKitDOMNode *citation_before, *citation_after, *child, *last_child, *tmp;
 
@@ -1612,6 +1904,15 @@ undo_redo_citation_split (WebKitDOMDocument *document,
 
                parent = get_parent_block_element (WEBKIT_DOM_NODE (selection_start));
 
+               if (event->data.fragment &&
+                   !webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (event->data.fragment))) {
+                       remove_node (WEBKIT_DOM_NODE (parent));
+                       dom_merge_siblings_if_necessarry (document, NULL);
+                       restore_selection_to_history_event_state (document, event->before);
+
+                       return;
+               }
+
                citation_before = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (parent));
                if (!dom_node_is_citation_node (citation_before)) {
                        dom_selection_restore (document);
@@ -1626,16 +1927,20 @@ undo_redo_citation_split (WebKitDOMDocument *document,
 
                /* Get first block in next citation. */
                child = webkit_dom_node_get_first_child (citation_after);
-               while (child && dom_node_is_citation_node (child)) {
-                       citation_level++;
+               while (child && dom_node_is_citation_node (child))
                        child = webkit_dom_node_get_first_child (child);
-               }
 
                /* Get last block in previous citation. */
                last_child = webkit_dom_node_get_last_child (citation_before);
                while (last_child && dom_node_is_citation_node (last_child))
                        last_child = webkit_dom_node_get_last_child (last_child);
 
+               /* Before appending any content to the block, check that the
+                * last node is not BR, if it is, remove it. */
+               tmp = webkit_dom_node_get_last_child (last_child);
+               if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (tmp))
+                       remove_node (tmp);
+
                if (in_situ) {
                        webkit_dom_node_append_child (
                                webkit_dom_node_get_parent_node (last_child),
@@ -1654,14 +1959,7 @@ undo_redo_citation_split (WebKitDOMDocument *document,
                        while ((tmp = webkit_dom_node_get_first_child (child)))
                                webkit_dom_node_append_child (last_child, tmp, NULL);
 
-                       word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
-                       length = word_wrap_length - 2 * citation_level;
-
-                       /* We need to re-wrap and re-quote the block. */
-                       last_child = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
-                               document, extension, WEBKIT_DOM_ELEMENT (last_child), length));
-                       dom_quote_plain_text_element_after_wrapping (
-                               document, WEBKIT_DOM_ELEMENT (last_child), citation_level);
+                       wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_child));
 
                        remove_node (child);
                }
@@ -1679,6 +1977,8 @@ undo_redo_citation_split (WebKitDOMDocument *document,
                if (event->data.fragment != NULL && !in_situ)
                        undo_delete (document, extension, event);
 
+               dom_merge_siblings_if_necessarry (document, NULL);
+
                restore_selection_to_history_event_state (document, event->before);
 
                dom_force_spell_check_in_viewport (document, extension);
@@ -1923,7 +2223,7 @@ e_html_editor_undo_redo_manager_insert_history_event (EHTMLEditorUndoRedoManager
        manager->priv->history_size++;
        manager->priv->can_undo = TRUE;
 
-       d (print_history (view));
+       d (print_history (manager));
 
        g_object_notify (G_OBJECT (manager), "can-undo");
 }
diff --git a/web-extensions/composer/e-html-editor-view-dom-functions.c 
b/web-extensions/composer/e-html-editor-view-dom-functions.c
index 345e954..70ef36a 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.c
@@ -433,7 +433,7 @@ dom_node_is_citation_node (WebKitDOMNode *node)
        }
 }
 
-static gint
+gint
 get_citation_level (WebKitDOMNode *node,
                     gboolean set_plaintext_quoted)
 {
@@ -577,12 +577,50 @@ get_parent_block_node_from_child (WebKitDOMNode *node)
 }
 
 WebKitDOMElement *
+wrap_and_quote_element (WebKitDOMDocument *document,
+                       EHTMLEditorWebExtension *extension,
+                       WebKitDOMElement *element)
+{
+       gint citation_level;
+       WebKitDOMElement *tmp_element = element;
+
+       g_return_val_if_fail (WEBKIT_DOM_IS_ELEMENT (element), element);
+
+       if (e_html_editor_web_extension_get_html_mode (extension))
+               return element;
+
+       citation_level = get_citation_level (WEBKIT_DOM_NODE (element), FALSE);
+
+       dom_remove_quoting_from_element (element);
+       dom_remove_wrapping_from_element (element);
+
+       if (element_has_class (element, "-x-evo-paragraph")) {
+               gint word_wrap_length, length;
+
+               word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
+               length = word_wrap_length - 2 * citation_level;
+               tmp_element = dom_wrap_paragraph_length (
+                       document, extension, element, length);
+       }
+
+       if (citation_level > 0) {
+
+               webkit_dom_node_normalize (WEBKIT_DOM_NODE (tmp_element));
+               dom_quote_plain_text_element_after_wrapping (
+                       document, tmp_element, citation_level);
+       }
+
+       return tmp_element;
+}
+
+WebKitDOMElement *
 dom_insert_new_line_into_citation (WebKitDOMDocument *document,
                                    EHTMLEditorWebExtension *extension,
                                    const gchar *html_to_insert)
 {
        gboolean html_mode = FALSE, ret_val, avoid_editor_call;
        WebKitDOMElement *element, *paragraph = NULL;
+       WebKitDOMNode *last_block;
 
        html_mode = e_html_editor_web_extension_get_html_mode (extension);
 
@@ -674,37 +712,43 @@ dom_insert_new_line_into_citation (WebKitDOMDocument *document,
                        return NULL;
        }
 
+       last_block = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+       while (last_block && dom_node_is_citation_node (last_block))
+               last_block = webkit_dom_node_get_last_child (last_block);
+
+       if (last_block) {
+               WebKitDOMNode *last_child;
+
+               if ((last_child = webkit_dom_node_get_last_child (last_block))) {
+                       if (WEBKIT_DOM_IS_ELEMENT (last_child) &&
+                           element_has_class (WEBKIT_DOM_ELEMENT (last_child), "-x-evo-quoted"))
+                               webkit_dom_node_append_child (
+                                       last_block,
+                                       WEBKIT_DOM_NODE (
+                                               webkit_dom_document_create_element (
+                                                       document, "br", NULL)),
+                                       NULL);
+               }
+       }
+
        if (!html_mode) {
-               WebKitDOMNode *next_sibling;
+               WebKitDOMNode *sibling;
 
-               next_sibling = webkit_dom_node_get_next_sibling (
-                       WEBKIT_DOM_NODE (element));
+               sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
 
-               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling)) {
-                       gint citation_level, length;
-                       gint word_wrap_length;
+               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (sibling)) {
                        WebKitDOMNode *node;
 
-                       node = webkit_dom_node_get_first_child (next_sibling);
+                       node = webkit_dom_node_get_first_child (sibling);
                        while (node && dom_node_is_citation_node (node))
                                node = webkit_dom_node_get_first_child (node);
 
-                       citation_level = get_citation_level (node, FALSE);
-                       word_wrap_length =
-                               e_html_editor_web_extension_get_word_wrap_length (extension);
-                       length = word_wrap_length - 2 * citation_level;
+                       /* Rewrap and requote nodes that were created by split. */
+                       if (WEBKIT_DOM_IS_ELEMENT (node))
+                               wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (node));
 
-                       /* Rewrap and requote first block after the newly inserted line */
-                       if (node && WEBKIT_DOM_IS_ELEMENT (node)) {
-                               dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (node));
-                               dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (node));
-
-                               if (element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-paragraph"))
-                                       node = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
-                                               document, extension, WEBKIT_DOM_ELEMENT (node), length));
-                               dom_quote_plain_text_element_after_wrapping (
-                                       document, WEBKIT_DOM_ELEMENT (node), citation_level);
-                       }
+                       if (WEBKIT_DOM_IS_ELEMENT (last_block))
+                               wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_block));
 
                        dom_force_spell_check_in_viewport (document, extension);
                }
@@ -2147,6 +2191,10 @@ save_history_for_input (WebKitDOMDocument *document,
                remove_node (WEBKIT_DOM_NODE (element_start));
                remove_node (WEBKIT_DOM_NODE (element_end));
 
+               g_object_set_data (
+                       G_OBJECT (fragment), "-x-evo-return-key", GINT_TO_POINTER (1));
+
+
                webkit_dom_dom_selection_modify (dom_selection, "move", "right", "character");
        } else {
                webkit_dom_node_append_child (
@@ -2226,19 +2274,17 @@ body_scroll_event_cb (WebKitDOMElement *element,
        e_html_editor_web_extension_set_spell_check_on_scroll_event_source_id (extension, id);
 }
 
-static void
-body_input_event_cb (WebKitDOMElement *element,
-                     WebKitDOMEvent *event,
-                     EHTMLEditorWebExtension *extension)
+void
+body_input_event_process (WebKitDOMDocument *document,
+                         EHTMLEditorWebExtension *extension,
+                         WebKitDOMEvent *event)
 {
        EHTMLEditorUndoRedoManager *manager;
        gboolean do_spell_check = FALSE;
        gboolean html_mode;
-       WebKitDOMDocument *document;
        WebKitDOMNode *node;
        WebKitDOMRange *range;
 
-       document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
        range = dom_get_current_range (document);
 
        manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
@@ -2496,8 +2542,6 @@ body_input_event_cb (WebKitDOMElement *element,
 
                        /* Wrap and quote the line */
                        if (!remove_quoting && text_length >= word_wrap_length) {
-                               EHTMLEditorHistoryEvent *ev;
-
                                dom_remove_quoting_from_element (block);
 
                                block = dom_wrap_paragraph_length (document, extension, block, length);
@@ -2513,16 +2557,6 @@ body_input_event_cb (WebKitDOMElement *element,
                                                NULL,
                                                NULL);
 
-                               /* The content was wrapped and the coordinates
-                                * of caret could be changed, so renew them. */
-                               ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
-                               dom_selection_get_coordinates (
-                                       document,
-                                       &ev->after.start.x,
-                                       &ev->after.start.y,
-                                       &ev->after.end.x,
-                                       &ev->after.end.y);
-
                                dom_selection_restore (document);
                                do_spell_check = TRUE;
                                goto out;
@@ -2537,6 +2571,18 @@ body_input_event_cb (WebKitDOMElement *element,
        g_object_unref (range);
 }
 
+static void
+body_input_event_cb (WebKitDOMElement *element,
+                     WebKitDOMEvent *event,
+                     EHTMLEditorWebExtension *extension)
+{
+       WebKitDOMDocument *document;
+
+       document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+
+       body_input_event_process (document, extension, event);
+}
+
 void
 dom_remove_input_event_listener_from_body (WebKitDOMDocument *document,
                                            EHTMLEditorWebExtension *extension)
@@ -2721,238 +2767,216 @@ dom_merge_siblings_if_necessarry (WebKitDOMDocument *document,
        }
 }
 
-static void
-body_keyup_event_cb (WebKitDOMElement *element,
-                     WebKitDOMUIEvent *event,
-                     EHTMLEditorWebExtension *extension)
+/* This will fix the structure after the situations where some text
+ * inside the quoted content is selected and afterwards deleted with
+ * BackSpace or Delete. */
+void
+body_key_up_event_process_backspace_or_delete (WebKitDOMDocument *document,
+                                              EHTMLEditorWebExtension *extension,
+                                               gboolean delete)
 {
-       glong key_code;
-       WebKitDOMDocument *document;
-
-       document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
-       if (!e_html_editor_web_extension_is_composition_in_progress (extension))
-               dom_register_input_event_listener_on_body (document, extension);
+       gint level;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker;
+       WebKitDOMElement *tmp_element;
+       WebKitDOMNode *parent, *node;
 
-       if (!dom_selection_is_collapsed (document))
+       if (e_html_editor_web_extension_get_html_mode (extension))
                return;
 
-       key_code = webkit_dom_ui_event_get_key_code (event);
-       if (key_code == HTML_KEY_CODE_BACKSPACE || key_code == HTML_KEY_CODE_DELETE) {
-               /* This will fix the structure after the situations where some text
-                * inside the quoted content is selected and afterwards deleted with
-                * BackSpace or Delete. */
-               gint level;
-               WebKitDOMElement *selection_start_marker, *selection_end_marker;
-               WebKitDOMElement *tmp_element;
-               WebKitDOMNode *parent, *node;
-
-               if (e_html_editor_web_extension_get_html_mode (extension))
-                       return;
-
-               dom_disable_quote_marks_select (document);
-               /* Remove empty blocks if presented. */
-               remove_empty_blocks (document);
-
-               dom_selection_save (document);
-               selection_start_marker = webkit_dom_document_get_element_by_id (
-                       document, "-x-evo-selection-start-marker");
-               selection_end_marker = webkit_dom_document_get_element_by_id (
-                       document, "-x-evo-selection-end-marker");
-
-               /* If we deleted a selection the caret will be inside the quote marks, fix it. */
-               parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
-               if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quote-character")) {
-                       webkit_dom_node_insert_before (
-                               webkit_dom_node_get_parent_node (
-                                       webkit_dom_node_get_parent_node (parent)),
-                               WEBKIT_DOM_NODE (selection_end_marker),
-                               webkit_dom_node_get_next_sibling (
-                                       webkit_dom_node_get_parent_node (parent)),
-                               NULL);
-                       webkit_dom_node_insert_before (
-                               webkit_dom_node_get_parent_node (
-                                       webkit_dom_node_get_parent_node (parent)),
-                               WEBKIT_DOM_NODE (selection_start_marker),
-                               webkit_dom_node_get_next_sibling (
-                                       webkit_dom_node_get_parent_node (parent)),
-                               NULL);
-               }
-
-               /* Under some circumstances we will end with block inside the citation
-                * that has the quote marks removed and we have to reinsert them back. */
-               level = get_citation_level (WEBKIT_DOM_NODE (selection_start_marker), FALSE);
-               node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
-               if (level > 0 && node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
-                       WebKitDOMNode *prev_sibling;
-
-                       prev_sibling = webkit_dom_node_get_previous_sibling (
-                               WEBKIT_DOM_NODE (selection_start_marker));
-                       if (!prev_sibling ||
-                           (WEBKIT_DOM_IS_HTML_BR_ELEMENT (prev_sibling) &&
-                           !webkit_dom_node_get_previous_sibling (prev_sibling))) {
-                               WebKitDOMElement *block;
-
-                               block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
-                                       WEBKIT_DOM_NODE (selection_start_marker)));
-                               if (webkit_dom_element_has_attribute (block, "data-no-quote")) {
-                                       webkit_dom_element_remove_attribute (block, "data-no-quote");
-                               } else {
-                                       dom_remove_quoting_from_element (block);
-                                       if (element_has_class (block, "-x-evo-paragraph")) {
-                                               gint length, word_wrap_length;
-
-                                               word_wrap_length = 
e_html_editor_web_extension_get_word_wrap_length (extension);
-                                               length =  word_wrap_length - 2 * (level - 1);
-                                               block = dom_wrap_paragraph_length (
-                                                       document, extension, block, length);
-                                               webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
-                                       }
-                                       dom_quote_plain_text_element_after_wrapping (
-                                               document, block, level);
-                               }
-                       }
-               } else if (level > 0 && node && WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
-                       EHTMLEditorUndoRedoManager *manager;
-                       EHTMLEditorHistoryEvent *event;
-                       WebKitDOMDocumentFragment *fragment;
-                       WebKitDOMNode *block;
+       dom_disable_quote_marks_select (document);
+       /* Remove empty blocks if presented. */
+       remove_empty_blocks (document);
 
-                       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
-                       block = get_parent_block_node_from_child (
-                               WEBKIT_DOM_NODE (selection_start_marker));
+       dom_selection_save (document);
+       selection_start_marker = webkit_dom_document_get_element_by_id (
+               document, "-x-evo-selection-start-marker");
+       selection_end_marker = webkit_dom_document_get_element_by_id (
+               document, "-x-evo-selection-end-marker");
 
-                       dom_remove_selection_markers (document);
+       /* If we deleted a selection the caret will be inside the quote marks, fix it. */
+       parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
+       if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quote-character")) {
+               webkit_dom_node_insert_before (
+                       webkit_dom_node_get_parent_node (
+                               webkit_dom_node_get_parent_node (parent)),
+                       WEBKIT_DOM_NODE (selection_end_marker),
+                       webkit_dom_node_get_next_sibling (
+                               webkit_dom_node_get_parent_node (parent)),
+                       NULL);
+               webkit_dom_node_insert_before (
+                       webkit_dom_node_get_parent_node (
+                               webkit_dom_node_get_parent_node (parent)),
+                       WEBKIT_DOM_NODE (selection_start_marker),
+                       webkit_dom_node_get_next_sibling (
+                               webkit_dom_node_get_parent_node (parent)),
+                       NULL);
+       }
 
-                       event = g_new0 (EHTMLEditorHistoryEvent, 1);
-                       event->type = HISTORY_AND;
+       /* Under some circumstances we will end with block inside the citation
+        * that has the quote marks removed and we have to reinsert them back. */
+       level = get_citation_level (WEBKIT_DOM_NODE (selection_start_marker), FALSE);
+       node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
+       if (level > 0 && node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
+               WebKitDOMElement *block;
 
-                       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+               block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
+                       WEBKIT_DOM_NODE (selection_start_marker)));
 
-                       event = g_new0 (EHTMLEditorHistoryEvent, 1);
-                       event->type = HISTORY_CITATION_SPLIT;
+               dom_remove_quoting_from_element (block);
+               if (element_has_class (block, "-x-evo-paragraph")) {
+                       gint length, word_wrap_length;
 
-                       dom_selection_get_coordinates (
-                               document,
-                               &event->before.start.x,
-                               &event->before.start.y,
-                               &event->before.end.x,
-                               &event->before.end.y);
+                       word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
+                       length =  word_wrap_length - 2 * level;
+                       block = dom_wrap_paragraph_length (
+                               document, extension, block, length);
+                       webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
+               }
+               dom_quote_plain_text_element_after_wrapping (
+                       document, block, level);
+       } else if (level > 0 && !node) {
+               WebKitDOMNode *prev_sibling;
 
-                       fragment = webkit_dom_document_create_document_fragment (document);
+               prev_sibling = webkit_dom_node_get_previous_sibling (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+               if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
+                   element_has_class (WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-quoted") &&
+                   !webkit_dom_node_get_previous_sibling (prev_sibling))
+                       webkit_dom_node_append_child (
+                               parent,
+                               WEBKIT_DOM_NODE (webkit_dom_document_create_element (document, "br", NULL)),
+                               NULL);
+       }
 
-                       /* Save the current block as it will be removed few lines after this. */
+       /* Situation where the start of the selection was 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 was in
+        * the end of the quoted content (showed by ^). The correct structure
+        * in these cases is to have empty block after the citation.
+        *
+        * > |xxx
+        * > xxx^
+        * |xxx
+        * */
+       tmp_element = webkit_dom_document_get_element_by_id (document, "-x-evo-tmp-block");
+       if (tmp_element) {
+               dom_remove_wrapping_from_element (tmp_element);
+               dom_remove_quoting_from_element (tmp_element);
+
+               /* Append the BR element if the block is empty, but the
+                * selection is there to be able to move to the block
+                * with caret later. */
+               if (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) &&
+                   !webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
                        webkit_dom_node_append_child (
-                               WEBKIT_DOM_NODE (fragment),
-                               webkit_dom_node_clone_node (block, TRUE),
+                               WEBKIT_DOM_NODE (tmp_element),
+                               WEBKIT_DOM_NODE (webkit_dom_document_create_element (
+                                       document, "br", NULL)),
                                NULL);
 
-                       event->data.fragment = fragment;
+               webkit_dom_element_remove_attribute (tmp_element, "id");
 
-                       /* Remove current block (and all of its parents if they
-                        * are empty) as it will be replaced by a new block that
-                        * will be in the body and not in the blockquote. */
-                       dom_remove_node_and_parents_if_empty (block);
+               parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp_element));
+               while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (parent)))
+                       parent = webkit_dom_node_get_parent_node (parent);
 
-                       dom_insert_new_line_into_citation (document, extension, "");
+               webkit_dom_node_insert_before (
+                       webkit_dom_node_get_parent_node (parent),
+                       WEBKIT_DOM_NODE (tmp_element),
+                       webkit_dom_node_get_next_sibling (parent),
+                       NULL);
+       }
 
-                       dom_selection_get_coordinates (
-                               document,
-                               &event->after.start.x,
-                               &event->after.start.y,
-                               &event->after.end.x,
-                               &event->after.end.y);
+       dom_merge_siblings_if_necessarry (document, NULL);
 
-                       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+       dom_selection_restore (document);
+       dom_force_spell_check_for_current_paragraph (document, extension);
+}
 
-                       return;
-               }
-
-               /* Situation where the start of the selection was 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 was in
-                * the end of the quoted content (showed by ^). The correct structure
-                * in these cases is to have empty block after the citation.
-                *
-                * > |xxx
-                * > xxx^
-                * |xxx
-                */
-               tmp_element = webkit_dom_document_get_element_by_id (document, "-x-evo-tmp-block");
-               if (tmp_element) {
-                       dom_remove_wrapping_from_element (tmp_element);
-                       dom_remove_quoting_from_element (tmp_element);
-
-                       /* Append the BR element if the block is empty, but the
-                        * selection is there to be able to move to the block
-                        * with caret later. */
-                       if (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) &&
-                           !webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
-                               webkit_dom_node_append_child (
-                                       WEBKIT_DOM_NODE (tmp_element),
-                                       WEBKIT_DOM_NODE (webkit_dom_document_create_element (
-                                               document, "br", NULL)),
-                                       NULL);
+void
+body_key_up_event_process_return_key (WebKitDOMDocument *document,
+                                     EHTMLEditorWebExtension *extension)
+{
+       WebKitDOMElement *selection_start_marker, *selection_end_marker;
+       WebKitDOMNode *parent;
 
-                       webkit_dom_element_remove_attribute (tmp_element, "id");
+       /* If the return is pressed in an unordered list in plain text mode
+        * the caret is moved to the "*" character before the newly inserted
+        * item. It looks like it is not enough that the item has BR element
+        * inside, but we have to again use the zero width space character
+        * to fix the situation. */
+       if (e_html_editor_web_extension_get_html_mode (extension))
+               return;
 
-                       parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp_element));
-                       while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node 
(parent)))
-                               parent = webkit_dom_node_get_parent_node (parent);
+       /* FIXME WK2 this is called twice */
+       /* dom_selection_save (document); */
 
-                       webkit_dom_node_insert_before (
-                               webkit_dom_node_get_parent_node (parent),
-                               WEBKIT_DOM_NODE (tmp_element),
-                               webkit_dom_node_get_next_sibling (parent),
-                               NULL);
-               }
+       dom_selection_save (document);
 
-               dom_merge_siblings_if_necessarry (document, NULL);
-               dom_selection_restore (document);
-       } else if (key_code == HTML_KEY_CODE_CONTROL)
-               dom_set_links_active (document, FALSE);
-       else if (key_code == HTML_KEY_CODE_RETURN) {
-               WebKitDOMDocument *document;
-               WebKitDOMElement *selection_start_marker, *selection_end_marker;
-               WebKitDOMNode *parent;
+       selection_start_marker = webkit_dom_document_get_element_by_id (
+               document, "-x-evo-selection-start-marker");
+       selection_end_marker = webkit_dom_document_get_element_by_id (
+               document, "-x-evo-selection-end-marker");
 
-               /* If the return is pressed in an unordered list in plain text mode
-                * the caret is moved to the "*" character before the the newly inserted
-                * item. It looks like it is not enough that the item has BR element
-                * inside, but we have to again use the zero width space character
-                * to fix the situation. */
-               if (e_html_editor_web_extension_get_html_mode (extension))
-                       return;
+       parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
+       if (!WEBKIT_DOM_IS_HTML_LI_ELEMENT (parent) ||
+           !WEBKIT_DOM_IS_HTML_U_LIST_ELEMENT (webkit_dom_node_get_parent_node (parent))) {
+               dom_selection_restore (document);
+               return;
+       }
 
-               /* FIXME WK2 - the below is called twice, the second time two lines below */
-               /*dom_selection_save (document);*/
+       if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)) &&
+           (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) ||
+            WEBKIT_DOM_IS_HTML_BR_ELEMENT (webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE 
(selection_end_marker)))))
+               webkit_dom_html_element_insert_adjacent_text (
+                       WEBKIT_DOM_HTML_ELEMENT (parent),
+                       "afterbegin",
+                       UNICODE_ZERO_WIDTH_SPACE,
+                       NULL);
 
-               document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+       dom_selection_restore (document);
+}
 
-               dom_selection_save (document);
+static void
+body_keyup_event_cb (WebKitDOMElement *element,
+                     WebKitDOMUIEvent *event,
+                     EHTMLEditorWebExtension *extension)
+{
+       WebKitDOMDocument *document;
+       glong key_code;
 
-               selection_start_marker = webkit_dom_document_get_element_by_id (
-                       document, "-x-evo-selection-start-marker");
-               selection_end_marker = webkit_dom_document_get_element_by_id (
-                       document, "-x-evo-selection-end-marker");
+       document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+       if (!e_html_editor_web_extension_is_composition_in_progress (extension))
+               dom_register_input_event_listener_on_body (document, extension);
 
-               parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
-               if (!WEBKIT_DOM_IS_HTML_LI_ELEMENT (parent) ||
-                   !WEBKIT_DOM_IS_HTML_U_LIST_ELEMENT (webkit_dom_node_get_parent_node (parent))) {
-                       dom_selection_restore (document);
-                       return;
-               }
+       if (!dom_selection_is_collapsed (document))
+               return;
 
-               if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)) &&
-                   (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) ||
-                    WEBKIT_DOM_IS_HTML_BR_ELEMENT (webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE 
(selection_end_marker)))))
-                       webkit_dom_html_element_insert_adjacent_text (
-                               WEBKIT_DOM_HTML_ELEMENT (parent),
-                               "afterbegin",
-                               UNICODE_ZERO_WIDTH_SPACE,
-                               NULL);
+       key_code = webkit_dom_ui_event_get_key_code (event);
+       if (key_code == HTML_KEY_CODE_BACKSPACE || key_code == HTML_KEY_CODE_DELETE) {
+               body_key_up_event_process_backspace_or_delete (document, extension, key_code == 
HTML_KEY_CODE_DELETE);
+
+               /* The content was wrapped and the coordinates
+                * of caret could be changed, so renew them. But
+                * only do that when we are not redoing a history
+                * event, otherwise it would modify the history. */
+               if (e_html_editor_web_extension_get_renew_history_after_coordinates (extension)) {
+                       EHTMLEditorHistoryEvent *ev = NULL;
+                       EHTMLEditorUndoRedoManager *manager;
 
-               dom_selection_restore (document);
-       }
+                       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+                       ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+                       dom_selection_get_coordinates (
+                               document,
+                               &ev->after.start.x,
+                               &ev->after.start.y,
+                               &ev->after.end.x,
+                               &ev->after.end.y);
+               }
+       } else if (key_code == HTML_KEY_CODE_CONTROL)
+               dom_set_links_active (document, FALSE);
+       else if (key_code == HTML_KEY_CODE_RETURN)
+               body_key_up_event_process_return_key (document, extension);
 }
 
 static void
@@ -2981,6 +3005,79 @@ fix_structure_after_pasting_multiline_content (WebKitDOMNode *node)
        }
 }
 
+static gboolean
+delete_hidden_space (WebKitDOMDocument *document,
+                    EHTMLEditorWebExtension *extension)
+{
+       gint citation_level;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker, *block;
+
+       selection_start_marker = webkit_dom_document_query_selector (
+               document, "span#-x-evo-selection-start-marker", NULL);
+       selection_end_marker = webkit_dom_document_query_selector (
+               document, "span#-x-evo-selection-end-marker", NULL);
+
+       if (!selection_start_marker || !selection_end_marker)
+               return FALSE;
+
+       block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
+               WEBKIT_DOM_NODE (selection_start_marker)));
+
+       citation_level = get_citation_level (
+               WEBKIT_DOM_NODE (selection_start_marker), FALSE);
+
+       if (selection_start_marker && citation_level > 0) {
+               EHTMLEditorUndoRedoManager *manager;
+               EHTMLEditorHistoryEvent *ev = NULL;
+               WebKitDOMNode *node;
+               WebKitDOMDocumentFragment *fragment;
+
+               manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+
+               node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker));
+               if (!(WEBKIT_DOM_IS_ELEMENT (node) &&
+                     element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted")))
+                       return FALSE;
+
+               node = webkit_dom_node_get_previous_sibling (node);
+               if (!(WEBKIT_DOM_IS_ELEMENT (node) &&
+                     element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-wrap-br")))
+                       return FALSE;
+
+               node = webkit_dom_node_get_previous_sibling (node);
+               if (!(WEBKIT_DOM_IS_ELEMENT (node) &&
+                     webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (node), "data-hidden-space")))
+                       return FALSE;
+
+               ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+               ev->type = HISTORY_DELETE;
+
+               dom_selection_get_coordinates (
+                       document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, 
&ev->before.end.y);
+
+               remove_node (node);
+
+               wrap_and_quote_element (document, extension, block);
+
+               fragment = webkit_dom_document_create_document_fragment (document);
+               webkit_dom_node_append_child (
+                       WEBKIT_DOM_NODE (fragment),
+                       WEBKIT_DOM_NODE (
+                               webkit_dom_document_create_text_node (document, " ")),
+                       NULL);
+               ev->data.fragment = fragment;
+
+               dom_selection_get_coordinates (
+                       document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
+
+               e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 gboolean
 dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
                                    EHTMLEditorWebExtension *extension)
@@ -2988,7 +3085,8 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
        EHTMLEditorHistoryEvent *ev = NULL;
        gboolean html_mode;
        gint citation_level, success = FALSE;
-       WebKitDOMElement *selection_start_marker, *selection_end_marker, *block;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker;
+       WebKitDOMNode *block;
        EHTMLEditorUndoRedoManager *manager;
 
        manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
@@ -3002,8 +3100,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
        if (!selection_start_marker || !selection_end_marker)
                return FALSE;
 
-       block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
-               WEBKIT_DOM_NODE (selection_start_marker)));
+       block = get_parent_block_node_from_child (WEBKIT_DOM_NODE (selection_start_marker));
 
        citation_level = get_citation_level (
                WEBKIT_DOM_NODE (selection_start_marker), FALSE);
@@ -3014,7 +3111,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
 
                        WebKitDOMNode *prev_sibling;
 
-                       webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
+                       webkit_dom_node_normalize (block);
 
                        prev_sibling = webkit_dom_node_get_previous_sibling (
                                WEBKIT_DOM_NODE (selection_start_marker));
@@ -3040,8 +3137,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
 
                if (html_mode)
                        success = WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (
-                               webkit_dom_node_get_parent_element (
-                                       WEBKIT_DOM_NODE (block)));
+                               webkit_dom_node_get_parent_element (block));
        }
 
        if (!success)
@@ -3052,15 +3148,15 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
                ev->type = HISTORY_UNQUOTE;
 
                dom_selection_get_coordinates (document, &ev->before.start.x, &ev->before.start.y, 
&ev->before.end.x, &ev->before.end.y);
-               ev->data.dom.from = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (block), TRUE);
+               ev->data.dom.from = webkit_dom_node_clone_node (block, TRUE);
        }
 
        if (citation_level == 1) {
                gchar *inner_html;
-               WebKitDOMElement *paragraph;
+               WebKitDOMElement *paragraph, *element;
 
-               inner_html = webkit_dom_element_get_inner_html (block);
-               webkit_dom_element_set_id (block, "-x-evo-to-remove");
+               inner_html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT (block));
+               webkit_dom_element_set_id (WEBKIT_DOM_ELEMENT (block), "-x-evo-to-remove");
 
                paragraph = dom_insert_new_line_into_citation (document, extension, inner_html);
                g_free (inner_html);
@@ -3087,11 +3183,10 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
                }
 
                if (block)
-                       remove_node (WEBKIT_DOM_NODE (block));
-               block = webkit_dom_document_get_element_by_id (
-                       document, "-x-evo-to-remove");
-               if (block)
-                       remove_node (WEBKIT_DOM_NODE (block));
+                       remove_node (block);
+
+               while ((element = webkit_dom_document_get_element_by_id (document, "-x-evo-to-remove")))
+                       remove_node (WEBKIT_DOM_NODE (element));
 
                if (paragraph)
                        remove_node_if_empty (
@@ -3100,47 +3195,41 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
        }
 
        if (citation_level > 1) {
-               gint length, word_wrap_length;
                WebKitDOMNode *parent;
 
-               word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
-               length =  word_wrap_length - 2 * (citation_level - 1);
-
                if (html_mode) {
                        webkit_dom_node_insert_before (
-                               WEBKIT_DOM_NODE (block),
+                               block,
                                WEBKIT_DOM_NODE (selection_start_marker),
-                               webkit_dom_node_get_first_child (
-                                       WEBKIT_DOM_NODE (block)),
+                               webkit_dom_node_get_first_child (block),
                                NULL);
                        webkit_dom_node_insert_before (
-                               WEBKIT_DOM_NODE (block),
+                               block,
                                WEBKIT_DOM_NODE (selection_end_marker),
-                               webkit_dom_node_get_first_child (
-                                       WEBKIT_DOM_NODE (block)),
+                               webkit_dom_node_get_first_child (block),
                                NULL);
 
                }
 
-               dom_remove_quoting_from_element (block);
-               dom_remove_wrapping_from_element (block);
+               dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (block));
+               dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (block));
 
-               parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (block));
+               parent = webkit_dom_node_get_parent_node (block);
 
-               if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (block))) {
+               if (!webkit_dom_node_get_previous_sibling (block)) {
                        /* Currect block is in the beginning of citation, just move it
                         * before the citation where already is */
                        webkit_dom_node_insert_before (
                                webkit_dom_node_get_parent_node (parent),
-                               WEBKIT_DOM_NODE (block),
+                               block,
                                parent,
                                NULL);
-               } else if (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (block))) {
+               } else if (!webkit_dom_node_get_next_sibling (block)) {
                        /* Currect block is at the end of the citation, just move it
                         * after the citation where already is */
                        webkit_dom_node_insert_before (
                                webkit_dom_node_get_parent_node (parent),
-                               WEBKIT_DOM_NODE (block),
+                               block,
                                webkit_dom_node_get_next_sibling (parent),
                                NULL);
                } else {
@@ -3153,7 +3242,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
 
                        /* Move nodes that are after the currect block into the
                         * new blockquote */
-                       child = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (block));
+                       child = webkit_dom_node_get_next_sibling (block);
                        while (child) {
                                WebKitDOMNode *next = webkit_dom_node_get_next_sibling (child);
                                webkit_dom_node_append_child (clone, child, NULL);
@@ -3168,16 +3257,12 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
 
                        webkit_dom_node_insert_before (
                                webkit_dom_node_get_parent_node (parent),
-                               WEBKIT_DOM_NODE (block),
+                               block,
                                clone,
                                NULL);
                }
 
-               if (!html_mode) {
-                       block = dom_wrap_paragraph_length (document, extension, block, length);
-                       webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
-                       dom_quote_plain_text_element_after_wrapping (document, block, citation_level - 1);
-               }
+               wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (block));
        }
 
        if (ev) {
@@ -7517,9 +7602,9 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
                                       gboolean delete_key,
                                       gboolean control_key)
 {
-       EHTMLEditorHistoryEvent *ev;
+       EHTMLEditorHistoryEvent *ev = NULL;
        EHTMLEditorUndoRedoManager *manager;
-       WebKitDOMDocumentFragment *fragment;
+       WebKitDOMDocumentFragment *fragment = NULL;
        WebKitDOMDOMWindow *dom_window;
        WebKitDOMDOMSelection *dom_selection;
        WebKitDOMRange *range;
@@ -7550,7 +7635,9 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
        range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
 
        if (webkit_dom_range_get_collapsed (range, NULL)) {
+               gboolean removing_from_anchor = FALSE;
                WebKitDOMRange *range_clone;
+               WebKitDOMNode *node, *next_block = NULL;
 
                e_html_editor_web_extension_block_selection_changed_callback (extension);
 
@@ -7576,47 +7663,135 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
                                        NULL);
                        g_object_unref (tmp_range);
                } else {
-                       if (delete_key) {
-                               WebKitDOMNode *container, *next_sibling;
+                       typedef WebKitDOMNode * (*GetSibling)(WebKitDOMNode *node);
+                       WebKitDOMNode *container, *sibling;
+                       WebKitDOMElement *selection_marker;
+
+                       GetSibling get_sibling = delete_key ?
+                               webkit_dom_node_get_next_sibling :
+                               webkit_dom_node_get_previous_sibling;
+
+                       container = webkit_dom_range_get_end_container (range_clone, NULL);
+                       sibling = get_sibling (container);
+
+                       selection_marker = webkit_dom_document_get_element_by_id (
+                               document,
+                               delete_key ?
+                                       "-x-evo-selection-end-marker" :
+                                       "-x-evo-selection-start-marker");
 
-                               container = webkit_dom_range_get_end_container (range_clone, NULL);
-                               next_sibling = webkit_dom_node_get_next_sibling (container);
+                       if (selection_marker) {
+                               WebKitDOMNode *tmp_sibling;
 
-                               if (dom_is_selection_position_node (next_sibling)) {
-                                       WebKitDOMNode *next_node;
+                               tmp_sibling = get_sibling (WEBKIT_DOM_NODE (selection_marker));
+                               if (!tmp_sibling || (WEBKIT_DOM_IS_HTML_BR_ELEMENT (tmp_sibling) &&
+                                   !element_has_class (WEBKIT_DOM_ELEMENT (tmp_sibling), "-x-evo-wrap-br")))
+                                       sibling = WEBKIT_DOM_NODE (selection_marker);
+                       }
 
-                                       next_node = webkit_dom_node_get_next_sibling (
-                                               webkit_dom_node_get_next_sibling (next_sibling));
-                                       if (next_node) {
+                       if (dom_is_selection_position_node (sibling)) {
+                               if ((node = get_sibling (sibling)))
+                                       node = get_sibling (node);
+                               if (node) {
+                                       if (WEBKIT_DOM_IS_ELEMENT (node) &&
+                                           webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (node), 
"data-hidden-space")) {
+                                               fragment = webkit_dom_document_create_document_fragment 
(document);
+                                               webkit_dom_node_append_child (
+                                                       WEBKIT_DOM_NODE (fragment),
+                                                       WEBKIT_DOM_NODE (
+                                                               webkit_dom_document_create_text_node 
(document, " ")),
+                                                       NULL);
+                                       } else if (delete_key) {
                                                webkit_dom_range_set_start (
-                                                       range_clone, next_node, 0, NULL);
+                                                       range_clone, node, 0, NULL);
                                                webkit_dom_range_set_end (
-                                                       range_clone, next_node, 1, NULL);
+                                                       range_clone, node, 1, NULL);
                                        }
                                } else {
-                                       glong offset;
+                                       WebKitDOMRange *tmp_range, *actual_range;
+
+                                       actual_range = webkit_dom_dom_selection_get_range_at (dom_selection, 
0, NULL);
+
+                                       webkit_dom_dom_selection_modify (
+                                               dom_selection, "move", delete_key ? "right" : "left", 
"character");
+
+                                       tmp_range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, 
NULL);
+                                       if (webkit_dom_range_compare_boundary_points (tmp_range, 2, 
actual_range, NULL) != 0) {
+                                               WebKitDOMNode *actual_block;
+                                               WebKitDOMNode *tmp_block;
+
+                                               actual_block = get_parent_block_node_from_child (container);
+
+                                               tmp_block = delete_key ?
+                                                       webkit_dom_range_get_end_container (tmp_range, NULL) :
+                                                       webkit_dom_range_get_start_container (tmp_range, 
NULL);
+                                               tmp_block = get_parent_block_node_from_child (tmp_block);
+
+                                               webkit_dom_dom_selection_modify (
+                                                       dom_selection, "move", delete_key ? "left" : "right", 
"character");
+
+                                               if (tmp_block) {
+                                                       fragment = 
webkit_dom_document_create_document_fragment (document);
+                                                       if (delete_key) {
+                                                               webkit_dom_node_append_child (
+                                                                       WEBKIT_DOM_NODE (fragment),
+                                                                       webkit_dom_node_clone_node 
(actual_block, TRUE),
+                                                                       NULL);
+                                                               webkit_dom_node_append_child (
+                                                                       WEBKIT_DOM_NODE (fragment),
+                                                                       webkit_dom_node_clone_node 
(tmp_block, TRUE),
+                                                                       NULL);
+                                                               if (delete_key)
+                                                                       next_block = tmp_block;
+                                                       } else {
+                                                               webkit_dom_node_append_child (
+                                                                       WEBKIT_DOM_NODE (fragment),
+                                                                       webkit_dom_node_clone_node 
(tmp_block, TRUE),
+                                                                       NULL);
+                                                               webkit_dom_node_append_child (
+                                                                       WEBKIT_DOM_NODE (fragment),
+                                                                       webkit_dom_node_clone_node 
(actual_block, TRUE),
+                                                                       NULL);
+                                                       }
+                                                       g_object_set_data (
+                                                               G_OBJECT (fragment),
+                                                               "-x-evo-fragment",
+                                                               GINT_TO_POINTER (1));
+                                               }
+                                       }
+                                       g_object_unref (tmp_range);
+                                       g_object_unref (actual_range);
+                               }
+                       } else {
+                               glong offset;
 
-                                       offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+                               offset = webkit_dom_range_get_start_offset (range_clone, NULL);
 
+                               if (delete_key)
                                        webkit_dom_range_set_end (
                                                range_clone, container, offset + 1, NULL);
-                               }
-                       } else {
-                               webkit_dom_range_set_start (
-                                       range_clone,
-                                       webkit_dom_range_get_start_container (range_clone, NULL),
-                                       webkit_dom_range_get_start_offset (range_clone, NULL) - 1,
-                                       NULL);
+                               else
+                                       webkit_dom_range_set_start (
+                                               range_clone, container, offset - 1, NULL);
+
+                               removing_from_anchor = WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (
+                                       webkit_dom_node_get_parent_node (container));
                        }
                }
 
-               fragment = webkit_dom_range_clone_contents (range_clone, NULL);
-               if (!webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment))) {
+
+               if (!fragment)
+                       fragment = webkit_dom_range_clone_contents (range_clone, NULL);
+               if (removing_from_anchor)
+                       g_object_set_data (G_OBJECT (fragment), "-x-evo-removing-from-anchor", 
GINT_TO_POINTER (1));
+               node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+               if (!node) {
                        g_free (ev);
                        e_html_editor_web_extension_unblock_selection_changed_callback (extension);
                        g_object_unref (range);
                        g_object_unref (range_clone);
                        g_object_unref (dom_selection);
+                       g_warning ("History event was not saved for %s key", delete_key ? "Delete" : 
"Backspace");
                        return;
                }
 
@@ -7631,8 +7806,15 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
                                webkit_dom_dom_selection_remove_all_ranges (dom_selection);
                                webkit_dom_dom_selection_add_range (dom_selection, range_clone);
                        } else {
+                               gboolean selection_saved = FALSE;
                                WebKitDOMRange *tmp_range;
 
+                               if (webkit_dom_document_get_element_by_id (document, 
"-x-evo-selection-start-marker"))
+                                       selection_saved = TRUE;
+
+                               if (selection_saved)
+                                       dom_selection_restore (document);
+
                                tmp_range = webkit_dom_range_clone_range (range_clone, NULL);
                                /* Prepare the selection to the right position after
                                 * delete and save it. */
@@ -7647,8 +7829,19 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
                                webkit_dom_dom_selection_remove_all_ranges (dom_selection);
                                webkit_dom_dom_selection_add_range (dom_selection, tmp_range);
                                g_object_unref (tmp_range);
+
+                               if (selection_saved)
+                                       dom_selection_save (document);
                        }
                } else {
+                       gboolean selection_saved = FALSE;
+
+                       if (webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker"))
+                               selection_saved = TRUE;
+
+                       if (selection_saved)
+                               dom_selection_restore (document);
+
                        if (delete_key) {
                                dom_selection_get_coordinates (
                                        document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, 
&ev->after.end.y);
@@ -7661,34 +7854,51 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
                                ev->after.end.x = ev->after.start.x;
                                ev->after.end.y = ev->after.start.y;
                        }
+
+                       if (selection_saved)
+                               dom_selection_save (document);
                }
 
                g_object_unref (range_clone);
 
                if (delete_key) {
-                       webkit_dom_node_insert_before (
-                               WEBKIT_DOM_NODE (fragment),
-                               WEBKIT_DOM_NODE (
-                                       dom_create_selection_marker (document, FALSE)),
-                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
-                               NULL);
-                       webkit_dom_node_insert_before (
-                               WEBKIT_DOM_NODE (fragment),
-                               WEBKIT_DOM_NODE (
-                                       dom_create_selection_marker (document, TRUE)),
-                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
-                               NULL);
+                       if (!WEBKIT_DOM_IS_ELEMENT (node)) {
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (fragment),
+                                       WEBKIT_DOM_NODE (
+                                               dom_create_selection_marker (document, FALSE)),
+                                       webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+                                       NULL);
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (fragment),
+                                       WEBKIT_DOM_NODE (
+                                               dom_create_selection_marker (document, TRUE)),
+                                       webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+                                       NULL);
+                       }
                } else {
-                       webkit_dom_node_append_child (
-                               WEBKIT_DOM_NODE (fragment),
-                               WEBKIT_DOM_NODE (
-                                       dom_create_selection_marker (document, TRUE)),
-                               NULL);
-                       webkit_dom_node_append_child (
-                               WEBKIT_DOM_NODE (fragment),
-                               WEBKIT_DOM_NODE (
-                                       dom_create_selection_marker (document, FALSE)),
-                               NULL);
+                       if (!WEBKIT_DOM_IS_ELEMENT (node)) {
+                               webkit_dom_node_append_child (
+                                       WEBKIT_DOM_NODE (fragment),
+                                       WEBKIT_DOM_NODE (
+                                               dom_create_selection_marker (document, TRUE)),
+                                       NULL);
+                               webkit_dom_node_append_child (
+                                       WEBKIT_DOM_NODE (fragment),
+                                       WEBKIT_DOM_NODE (
+                                               dom_create_selection_marker (document, FALSE)),
+                                       NULL);
+                       }
+               }
+
+               /* 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) {
+                       dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (next_block));
+                       dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (next_block));
                }
 
                e_html_editor_web_extension_unblock_selection_changed_callback (extension);
@@ -7810,6 +8020,9 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
        g_object_unref (range);
        g_object_unref (dom_selection);
 
+       g_object_set_data (G_OBJECT (fragment), "-x-evo-delete-key", GINT_TO_POINTER (delete_key));
+       g_object_set_data (G_OBJECT (fragment), "-x-evo-control-key", GINT_TO_POINTER (control_key));
+
        ev->data.fragment = fragment;
 
        manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
@@ -7820,7 +8033,8 @@ gboolean
 dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *document,
                                                      EHTMLEditorWebExtension *extension,
                                                      guint key_val,
-                                                     guint state)
+                                                     guint state,
+                                                     gboolean delete_key)
 {
        gboolean collapsed = FALSE;
        WebKitDOMElement *selection_start_marker, *selection_end_marker;
@@ -7839,15 +8053,15 @@ dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *documen
                return FALSE;
 
        if (collapsed) {
-               WebKitDOMNode *next_sibling;
+               WebKitDOMNode *next_block;
 
                block = get_parent_block_node_from_child (
                        WEBKIT_DOM_NODE (selection_start_marker));
 
-               next_sibling = webkit_dom_node_get_next_sibling (block);
+               next_block = webkit_dom_node_get_next_sibling (block);
 
                /* Next block is quoted content */
-               if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling))
+               if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_block))
                        goto restore;
 
                /* Delete was pressed in block without any content */
@@ -7863,11 +8077,27 @@ dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *documen
                                save_history_for_delete_or_backspace (
                                        document, extension, key_val == GDK_KEY_Delete, (state & 
GDK_CONTROL_MASK) != 0);
 
-                       /* Remove the empty block and move caret into the beginning of the citation */
+                       /* Remove the empty block and move caret to the right place. */
                        remove_node (block);
 
-                       dom_move_caret_into_element (
-                               document, WEBKIT_DOM_ELEMENT (next_sibling), TRUE);
+                       if (delete_key) {
+                               /* To the beginning of the next block. */
+                               dom_move_caret_into_element (
+                                       document, WEBKIT_DOM_ELEMENT (next_block), TRUE);
+                       } else {
+                               WebKitDOMNode *prev_block;
+
+                               /* On the end of previous block. */
+                               prev_block = webkit_dom_node_get_previous_sibling (next_block);
+                               while (prev_block && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (prev_block))
+                                       prev_block = webkit_dom_node_get_last_child (prev_block);
+
+                               if (prev_block)
+                                       dom_move_caret_into_element (
+                                               document,
+                                               WEBKIT_DOM_ELEMENT (prev_block),
+                                               FALSE);
+                       }
 
                        return TRUE;
                }
@@ -7895,12 +8125,6 @@ dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *documen
                if (!element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted"))
                        goto restore;
 
-               webkit_dom_node_insert_before (
-                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (node)),
-                       WEBKIT_DOM_NODE (selection_start_marker),
-                       WEBKIT_DOM_NODE (node),
-                       NULL);
-
                block = get_parent_block_node_from_child (
                        WEBKIT_DOM_NODE (selection_start_marker));
                end_block = get_parent_block_node_from_child (
@@ -7956,48 +8180,73 @@ static gboolean
 split_citation (WebKitDOMDocument *document,
                 EHTMLEditorWebExtension *extension)
 {
-       EHTMLEditorHistoryEvent *ev;
+       EHTMLEditorHistoryEvent *ev = NULL;
        EHTMLEditorUndoRedoManager *manager;
        WebKitDOMElement *element;
 
-       ev = g_new0 (EHTMLEditorHistoryEvent, 1);
-       ev->type = HISTORY_CITATION_SPLIT;
+       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
 
-       dom_selection_get_coordinates (
-               document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, &ev->before.end.y);
+       if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+               ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+               ev->type = HISTORY_CITATION_SPLIT;
 
-       if (!dom_selection_is_collapsed (document)) {
-               WebKitDOMDocumentFragment *fragment;
-               WebKitDOMDOMWindow *dom_window;
-               WebKitDOMDOMSelection *dom_selection;
-               WebKitDOMRange *range;
+               dom_selection_get_coordinates (
+                       document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, 
&ev->before.end.y);
 
-               dom_window = webkit_dom_document_get_default_view (document);
-               dom_selection = webkit_dom_dom_window_get_selection (dom_window);
-               g_object_unref (dom_window);
+               if (!dom_selection_is_collapsed (document)) {
+                       WebKitDOMDocumentFragment *fragment;
+                       WebKitDOMDOMWindow *dom_window;
+                       WebKitDOMDOMSelection *dom_selection;
+                       WebKitDOMRange *range;
 
-               if (!webkit_dom_dom_selection_get_range_count (dom_selection)) {
+                       dom_window = webkit_dom_document_get_default_view (document);
+                       dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+                       g_object_unref (dom_window);
+
+                       if (!webkit_dom_dom_selection_get_range_count (dom_selection)) {
+                               g_object_unref (dom_selection);
+                               return FALSE;
+                       }
+
+                       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+                       fragment = webkit_dom_range_clone_contents (range, NULL);
+
+                       g_object_unref (range);
                        g_object_unref (dom_selection);
-                       return FALSE;
-               }
 
-               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-               fragment = webkit_dom_range_clone_contents (range, NULL);
+                       ev->data.fragment = fragment;
+               } else {
+                       WebKitDOMElement *selection_end;
+                       WebKitDOMNode *sibling;
 
-               g_object_unref (range);
-               g_object_unref (dom_selection);
+                       dom_selection_save (document);
 
-               ev->data.fragment = fragment;
-       } else
-               ev->data.fragment = NULL;
+                       selection_end = webkit_dom_document_get_element_by_id (
+                               document, "-x-evo-selection-end-marker");
+
+                       sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end));
+                       if (!sibling || (WEBKIT_DOM_IS_HTML_BR_ELEMENT (sibling) &&
+                           !element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-wrap-br"))) {
+                               WebKitDOMDocumentFragment *fragment;
+
+                               fragment = webkit_dom_document_create_document_fragment (document);
+                               ev->data.fragment = fragment;
+                       } else {
+                               ev->data.fragment = NULL;
+                       }
+
+                       dom_selection_restore (document);
+               }
+       }
 
        element = dom_insert_new_line_into_citation (document, extension, "");
 
-       dom_selection_get_coordinates (
-               document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
+       if (ev) {
+               dom_selection_get_coordinates (
+                       document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
 
-       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
-       e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+               e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+       }
 
        return element != NULL;
 }
@@ -8157,6 +8406,7 @@ dom_delete_character_from_quoted_line_start (WebKitDOMDocument *document,
                                             guint key_val,
                                             guint state)
 {
+       gboolean success = FALSE;
        WebKitDOMElement *element;
        WebKitDOMNode *node, *beginning;
 
@@ -8178,46 +8428,112 @@ dom_delete_character_from_quoted_line_start (WebKitDOMDocument *document,
 
        /* We have to be on the end of line. */
        if (webkit_dom_node_get_next_sibling (node))
-               return FALSE;
+               goto out;
 
        /* Before the caret is just text. */
        node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
        if (!(node && WEBKIT_DOM_IS_TEXT (node)))
-               return FALSE;
+               goto out;
 
        /* There is just one character. */
        if (webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (node)) != 1)
-               return FALSE;
+               goto out;
 
        beginning = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (node));
        if (!(beginning && WEBKIT_DOM_IS_ELEMENT (beginning)))
-               return FALSE;
+               goto out;
 
        /* Before the text is the beginning of line. */
        if (!(element_has_class (WEBKIT_DOM_ELEMENT (beginning), "-x-evo-quoted")))
-               return FALSE;
+               goto out;
 
-       if (key_val != ~0)
-               save_history_for_delete_or_backspace (
-                       document, extension, key_val == GDK_KEY_Delete, (state & GDK_CONTROL_MASK) != 0);
+       /* If we are just on the beginning of the line and not on the beginning of
+        * the block we need to remove the last character ourselves as well, otherwise
+        * WebKit will put the caret to wrong position. */
+       if (webkit_dom_node_get_previous_sibling (beginning)) {
+               EHTMLEditorHistoryEvent *ev = NULL;
+               WebKitDOMDocumentFragment *fragment;
+               WebKitDOMNode *prev_sibling;
 
-       element = webkit_dom_node_get_parent_element (beginning);
+               if (key_val != ~0) {
+                       ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+                       ev->type = HISTORY_DELETE;
 
-       dom_remove_quoting_from_element (element);
+                       dom_selection_get_coordinates (
+                               document,
+                               &ev->before.start.x,
+                               &ev->before.start.y,
+                               &ev->before.end.x,
+                               &ev->before.end.y);
 
-       webkit_dom_node_append_child (
-               WEBKIT_DOM_NODE (element),
-               WEBKIT_DOM_NODE (
-                       webkit_dom_document_create_element (document, "br", NULL)),
-               NULL);
+                       fragment = webkit_dom_document_create_document_fragment (document);
+               }
 
-       webkit_dom_element_set_attribute (element, "data-no-quote", "", NULL);
+               prev_sibling = webkit_dom_node_get_previous_sibling (beginning);
+               if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (prev_sibling)) {
+                       if (key_val != ~0)
+                               webkit_dom_node_append_child (WEBKIT_DOM_NODE (fragment), prev_sibling, NULL);
+                       else
+                               remove_node (prev_sibling);
+               }
 
-       remove_node (node);
+               prev_sibling = webkit_dom_node_get_previous_sibling (beginning);
+               if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
+                   webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (prev_sibling), 
"data-hidden-space")) {
+                       if (key_val != ~0)
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (fragment),
+                                       prev_sibling,
+                                       webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+                                       NULL);
+                       else
+                               remove_node (prev_sibling);
+               }
+
+               if (key_val != ~0)
+                       webkit_dom_node_append_child (WEBKIT_DOM_NODE (fragment), beginning, NULL);
+               else
+                       remove_node (beginning);
+
+               if (key_val != ~0) {
+                       EHTMLEditorUndoRedoManager *manager;
 
+                       webkit_dom_node_append_child (WEBKIT_DOM_NODE (fragment), node, NULL);
+
+                       dom_selection_get_coordinates (
+                               document,
+                               &ev->after.start.x,
+                               &ev->after.start.y,
+                               &ev->after.end.x,
+                               &ev->after.end.y);
+
+                       ev->data.fragment = fragment;
+
+                       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+                       e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+               } else
+                       remove_node (node);
+
+               dom_selection_restore (document);
+
+               return TRUE;
+       }
+
+       if (key_val != ~0)
+               save_history_for_delete_or_backspace (
+                       document, extension, key_val == GDK_KEY_Delete, (state & GDK_CONTROL_MASK) != 0);
+
+       element = webkit_dom_node_get_parent_element (beginning);
+       remove_node (WEBKIT_DOM_NODE (element));
+
+       success = TRUE;
+ out:
        dom_selection_restore (document);
 
-       return TRUE;
+       if (success)
+               dom_insert_new_line_into_citation (document, extension, NULL);
+
+       return success;
 }
 
 static gboolean
@@ -8233,76 +8549,76 @@ static gboolean
 insert_tabulator (WebKitDOMDocument *document,
                   EHTMLEditorWebExtension *extension)
 {
-       EHTMLEditorHistoryEvent *ev;
+       EHTMLEditorUndoRedoManager *manager;
+       EHTMLEditorHistoryEvent *ev = NULL;
        gboolean success;
 
-       ev = g_new0 (EHTMLEditorHistoryEvent, 1);
-       ev->type = HISTORY_INPUT;
-
-       if (!dom_selection_is_collapsed (document)) {
-               WebKitDOMRange *tmp_range;
-
-               tmp_range = dom_get_current_range (document);
-               insert_delete_event (document, extension, tmp_range);
-               g_object_unref (tmp_range);
-       }
-
-       dom_selection_get_coordinates (
-               document,
-               &ev->before.start.x,
-               &ev->before.start.y,
-               &ev->before.end.x,
-               &ev->before.end.y);
+       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
 
-       ev->before.end.x = ev->before.start.x;
-       ev->before.end.y = ev->before.start.y;
+       if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+               ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+               ev->type = HISTORY_INPUT;
 
-       success = dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, "\t");
+               if (!dom_selection_is_collapsed (document)) {
+                       WebKitDOMRange *tmp_range;
 
-       if (success) {
-               EHTMLEditorUndoRedoManager *manager;
-               WebKitDOMElement *element;
-               WebKitDOMDocumentFragment *fragment;
+                       tmp_range = dom_get_current_range (document);
+                       insert_delete_event (document, extension, tmp_range);
+                       g_object_unref (tmp_range);
+               }
 
                dom_selection_get_coordinates (
                        document,
-                       &ev->after.start.x,
-                       &ev->after.start.y,
-                       &ev->after.end.x,
-                       &ev->after.end.y);
+                       &ev->before.start.x,
+                       &ev->before.start.y,
+                       &ev->before.end.x,
+                       &ev->before.end.y);
 
-               fragment = webkit_dom_document_create_document_fragment (document);
-               element = webkit_dom_document_create_element (document, "span", NULL);
-               webkit_dom_html_element_set_inner_text (
-                       WEBKIT_DOM_HTML_ELEMENT (element), "\t", NULL);
-               webkit_dom_element_set_attribute (
-                       element, "class", "Apple-tab-span", NULL);
-               webkit_dom_element_set_attribute (
-                       element, "style", "white-space:pre", NULL);
-               webkit_dom_node_append_child (
-                       WEBKIT_DOM_NODE (fragment), WEBKIT_DOM_NODE (element), NULL);
-               webkit_dom_node_append_child (
-                       WEBKIT_DOM_NODE (fragment),
-                       WEBKIT_DOM_NODE (dom_create_selection_marker (document, TRUE)),
-                       NULL);
-               webkit_dom_node_append_child (
-                       WEBKIT_DOM_NODE (fragment),
-                       WEBKIT_DOM_NODE (dom_create_selection_marker (document, FALSE)),
-                       NULL);
-               ev->data.fragment = fragment;
+               ev->before.end.x = ev->before.start.x;
+               ev->before.end.y = ev->before.start.y;
+       }
 
-               manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
-               e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+       success = dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, "\t");
 
-               e_html_editor_web_extension_set_content_changed (extension);
-       } else {
-               EHTMLEditorUndoRedoManager *manager;
+       if (ev) {
+               if (success) {
+                       WebKitDOMElement *element;
+                       WebKitDOMDocumentFragment *fragment;
 
-               manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+                       dom_selection_get_coordinates (
+                               document,
+                               &ev->after.start.x,
+                               &ev->after.start.y,
+                               &ev->after.end.x,
+                               &ev->after.end.y);
 
-               e_html_editor_undo_redo_manager_remove_current_history_event (manager);
-               e_html_editor_undo_redo_manager_remove_current_history_event (manager);
-               g_free (ev);
+                       fragment = webkit_dom_document_create_document_fragment (document);
+                       element = webkit_dom_document_create_element (document, "span", NULL);
+                       webkit_dom_html_element_set_inner_text (
+                               WEBKIT_DOM_HTML_ELEMENT (element), "\t", NULL);
+                       webkit_dom_element_set_attribute (
+                               element, "class", "Apple-tab-span", NULL);
+                       webkit_dom_element_set_attribute (
+                               element, "style", "white-space:pre", NULL);
+                       webkit_dom_node_append_child (
+                               WEBKIT_DOM_NODE (fragment), WEBKIT_DOM_NODE (element), NULL);
+                       webkit_dom_node_append_child (
+                               WEBKIT_DOM_NODE (fragment),
+                               WEBKIT_DOM_NODE (dom_create_selection_marker (document, TRUE)),
+                               NULL);
+                       webkit_dom_node_append_child (
+                               WEBKIT_DOM_NODE (fragment),
+                               WEBKIT_DOM_NODE (dom_create_selection_marker (document, FALSE)),
+                               NULL);
+                       ev->data.fragment = fragment;
+
+                       e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+                       e_html_editor_web_extension_set_content_changed (extension);
+               } else {
+                       e_html_editor_undo_redo_manager_remove_current_history_event (manager);
+                       e_html_editor_undo_redo_manager_remove_current_history_event (manager);
+                       g_free (ev);
+               }
        }
 
        return success;
@@ -8468,138 +8784,273 @@ change_smiley_to_plain_text (WebKitDOMDocument *document)
 }
 
 gboolean
-dom_process_on_key_press (WebKitDOMDocument *document,
-                          EHTMLEditorWebExtension *extension,
-                          guint key_val,
-                         guint state)
+key_press_event_process_return_key (WebKitDOMDocument *document,
+                                   EHTMLEditorWebExtension *extension)
 {
-       e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+       gboolean first_cell = FALSE;
+       WebKitDOMNode *table = NULL;
 
-       if (key_val == GDK_KEY_Tab || key_val == GDK_KEY_ISO_Left_Tab) {
-               if (jump_to_next_table_cell (document, key_val == GDK_KEY_ISO_Left_Tab))
+       /* Return pressed in the beginning of the first cell will insert
+        * new block before the table (and move the caret there) if none
+        * is already there, otherwise it will act as normal return. */
+       if (selection_is_in_table (document, &first_cell, &table) && first_cell) {
+               WebKitDOMNode *node;
+
+               node = webkit_dom_node_get_previous_sibling (table);
+               if (!node) {
+                       node = webkit_dom_node_get_next_sibling (table);
+                       node = webkit_dom_node_clone_node (node, FALSE);
+                       webkit_dom_node_append_child (
+                               node,
+                               WEBKIT_DOM_NODE (webkit_dom_document_create_element (
+                                       document, "br", NULL)),
+                               NULL);
+                       dom_add_selection_markers_into_element_start (
+                               document, WEBKIT_DOM_ELEMENT (node), NULL, NULL);
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_parent_node (table),
+                               node,
+                               table,
+                               NULL);
+                       dom_selection_restore (document);
+                       e_html_editor_web_extension_set_content_changed (extension);
                        return TRUE;
+               }
+       }
 
-               if (key_val == GDK_KEY_Tab)
-                       return insert_tabulator (document, extension);
-               else
-                       return FALSE;
+       /* When user presses ENTER in a citation block, WebKit does
+        * not break the citation automatically, so we need to use
+        * the special command to do it. */
+       if (dom_selection_is_citation (document)) {
+               dom_remove_input_event_listener_from_body (document, extension);
+               if (split_citation (document, extension)) {
+                       e_html_editor_web_extension_set_content_changed (extension);
+                       return TRUE;
+               }
+               return FALSE;
        }
 
-       if (is_return_key (key_val)) {
-               gboolean first_cell = FALSE;
-               WebKitDOMNode *table = NULL;
+       /* If the ENTER key is pressed inside an empty list item then the list
+        * is broken into two and empty paragraph is inserted between lists. */
+       if (return_pressed_in_empty_list_item (document, extension, TRUE))
+               return TRUE;
 
-               /* Return pressed in the beginning of the first cell will insert
-                * new block before the table (and move the caret there) if none
-                * is already there, otherwise it will act as normal return. */
-               if (selection_is_in_table (document, &first_cell, &table) && first_cell) {
-                       WebKitDOMNode *node;
+       return FALSE;
+}
 
-                       node = webkit_dom_node_get_previous_sibling (table);
-                       if (!node) {
-                               node = webkit_dom_node_get_next_sibling (table);
-                               node = webkit_dom_node_clone_node (node, FALSE);
-                               webkit_dom_node_append_child (
-                                       node,
-                                       WEBKIT_DOM_NODE (webkit_dom_document_create_element (
-                                               document, "br", NULL)),
-                                       NULL);
-                               dom_add_selection_markers_into_element_start (
-                                       document, WEBKIT_DOM_ELEMENT (node), NULL, NULL);
-                               webkit_dom_node_insert_before (
-                                       webkit_dom_node_get_parent_node (table),
-                                       node,
-                                       table,
-                                       NULL);
-                               dom_selection_restore (document);
-                               e_html_editor_web_extension_set_content_changed (extension);
-                               return TRUE;
-                       }
+gboolean
+key_press_event_process_backspace_key (WebKitDOMDocument *document,
+                                      EHTMLEditorWebExtension *extension)
+{
+       /* BackSpace pressed in the beginning of quoted content changes
+        * format to normal and inserts text into body */
+       if (dom_selection_is_collapsed (document)) {
+               dom_selection_save (document);
+               if (dom_change_quoted_block_to_normal (document, extension) || delete_hidden_space (document, 
extension)) {
+                       dom_selection_restore (document);
+                       dom_force_spell_check_for_current_paragraph (document, extension);
+                       e_html_editor_web_extension_set_content_changed (extension);
+                       return TRUE;
                }
+               dom_selection_restore (document);
+       }
 
-               /* When user presses ENTER in a citation block, WebKit does
-                * not break the citation automatically, so we need to use
-                * the special command to do it. */
-               if (dom_selection_is_citation (document)) {
-                       dom_remove_input_event_listener_from_body (document, extension);
-                       if (split_citation (document, extension)) {
-                               e_html_editor_web_extension_set_content_changed (extension);
-                               return TRUE;
-                       }
-                       return FALSE;
-               }
+       /* BackSpace in indented block decrease indent level by one */
+       if (dom_selection_is_indented (document) &&
+           dom_selection_is_collapsed (document)) {
+               WebKitDOMElement *selection_start;
+               WebKitDOMNode *prev_sibling;
+
+               dom_selection_save (document);
+               selection_start = webkit_dom_document_get_element_by_id (
+                       document, "-x-evo-selection-start-marker");
 
-               /* If the ENTER key is pressed inside an empty list item then the list
-                * is broken into two and empty paragraph is inserted between lists. */
-               if (return_pressed_in_empty_list_item (document, extension, TRUE))
+               /* Empty text node before caret */
+               prev_sibling = webkit_dom_node_get_previous_sibling (
+                       WEBKIT_DOM_NODE (selection_start));
+               if (prev_sibling && WEBKIT_DOM_IS_TEXT (prev_sibling))
+                       if (webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (prev_sibling)) 
== 0)
+                               prev_sibling = webkit_dom_node_get_previous_sibling (prev_sibling);
+
+               dom_selection_restore (document);
+               if (!prev_sibling) {
+                       dom_selection_unindent (document, extension);
+                       e_html_editor_web_extension_set_content_changed (extension);
                        return TRUE;
+               }
        }
 
-       if (key_val == GDK_KEY_BackSpace) {
-               /* BackSpace pressed in the beginning of quoted content changes
-                * format to normal and inserts text into body */
-               if (dom_selection_is_collapsed (document)) {
-                       dom_selection_save (document);
-                       if (dom_change_quoted_block_to_normal (document, extension)) {
-                               dom_selection_restore (document);
-                               dom_force_spell_check_for_current_paragraph (document, extension);
-                               e_html_editor_web_extension_set_content_changed (extension);
-                               return TRUE;
-                       }
+       if (prevent_from_deleting_last_element_in_body (document))
+               return TRUE;
+
+       return FALSE;
+}
+
+gboolean
+key_press_event_process_delete_or_backspace_key (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                guint key_val,
+                                                guint state,
+                                                gboolean delete)
+{
+       gboolean html_mode;
+       gboolean local_delete;
+
+       html_mode = e_html_editor_web_extension_get_html_mode (extension);
+       local_delete = (key_val == GDK_KEY_Delete) || delete;
+
+       if (!html_mode && e_html_editor_web_extension_get_magic_links_enabled (extension)) {
+               /* If deleting something in a smiley it won't be a smiley
+                * anymore (at least from Evolution' POV), so remove all
+                * the elements that are hidden in the wrapper and leave
+                * just the text. Also this ensures that when a smiley is
+                * recognized and we press the BackSpace key we won't delete
+                * the UNICODE_HIDDEN_SPACE, but we will correctly delete
+                * the last character of smiley. */
+               change_smiley_to_plain_text (document);
+       }
+
+       if (!local_delete && !html_mode &&
+           dom_delete_character_from_quoted_line_start (document, extension, key_val, state))
+               goto out;
+
+       if (dom_fix_structure_after_delete_before_quoted_content (document, extension, key_val, state, FALSE))
+               goto out;
+
+       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 || !dom_selection_is_collapsed (document))
+                       return FALSE;
+
+               dom_selection_save (document);
+
+               selection_start_marker = webkit_dom_document_get_element_by_id (
+                       document, "-x-evo-selection-start-marker");
+               sibling = webkit_dom_node_get_previous_sibling (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+               /* Check if the key was pressed in the beginning of block. */
+               if (!(sibling && WEBKIT_DOM_IS_ELEMENT (sibling) &&
+                     element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-quoted"))) {
                        dom_selection_restore (document);
+                       return FALSE;
                }
 
-               /* BackSpace in indented block decrease indent level by one */
-               if (dom_selection_is_indented (document) &&
-                   dom_selection_is_collapsed (document)) {
-                       WebKitDOMElement *selection_start;
-                       WebKitDOMNode *prev_sibling;
+               sibling = webkit_dom_node_get_next_sibling (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+               sibling = webkit_dom_node_get_next_sibling (sibling);
 
-                       dom_selection_save (document);
-                       selection_start = webkit_dom_document_get_element_by_id (
-                               document, "-x-evo-selection-start-marker");
+               /* And also the current block was empty. */
+               if (!(!sibling || (sibling && WEBKIT_DOM_IS_HTML_BR_ELEMENT (sibling) &&
+                     !element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-wrap-br")))) {
+                       dom_selection_restore (document);
+                       return FALSE;
+               }
 
-                       /* Empty text node before caret */
-                       prev_sibling = webkit_dom_node_get_previous_sibling (
-                               WEBKIT_DOM_NODE (selection_start));
-                       if (prev_sibling && WEBKIT_DOM_IS_TEXT (prev_sibling))
-                               if (webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA 
(prev_sibling)) == 0)
-                                       prev_sibling = webkit_dom_node_get_previous_sibling (prev_sibling);
+               block = get_parent_block_node_from_child (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+               next_block = webkit_dom_node_get_next_sibling (block);
+
+               remove_node (block);
+
+               dom_move_caret_into_element (
+                       document, WEBKIT_DOM_ELEMENT (next_block), TRUE);
+
+               goto out;
+       } else {
+               /* Concatenating a non-quoted block with Backspace key to the
+                * previous block that is inside a quoted content. */
+               WebKitDOMElement *selection_start_marker;
+               WebKitDOMNode *node, *block, *prev_block, *last_child, *child;
+
+               if (html_mode || !dom_selection_is_collapsed (document) ||
+                   dom_selection_is_citation (document))
+                       return FALSE;
+
+               dom_selection_save (document);
+
+               selection_start_marker = webkit_dom_document_get_element_by_id (
+                       document, "-x-evo-selection-start-marker");
 
+               node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker));
+               if (node) {
                        dom_selection_restore (document);
-                       if (!prev_sibling) {
-                               dom_selection_unindent (document, extension);
-                               e_html_editor_web_extension_set_content_changed (extension);
-                               return TRUE;
-                       }
+                       return FALSE;
                }
 
-               if (prevent_from_deleting_last_element_in_body (document))
-                       return TRUE;
+               block = get_parent_block_node_from_child (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+
+               prev_block = webkit_dom_node_get_previous_sibling (block);
+               if (!prev_block || !WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (prev_block)) {
+                       dom_selection_restore (document);
+                       return FALSE;
+               }
+
+               last_child = webkit_dom_node_get_last_child (prev_block);
+               while (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (last_child))
+                       last_child = webkit_dom_node_get_last_child (last_child);
+
+               dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (last_child));
+               dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (last_child));
+
+               node = webkit_dom_node_get_last_child (last_child);
+               if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (node))
+                       remove_node (node);
+
+               while ((child = webkit_dom_node_get_first_child (block)))
+                       webkit_dom_node_append_child (last_child, child, NULL);
+
+               remove_node (block);
+
+               if (WEBKIT_DOM_IS_ELEMENT (last_child))
+                       wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_child));
+
+               dom_selection_restore (document);
+
+               goto out;
        }
 
-       if (key_val == GDK_KEY_Delete || key_val == GDK_KEY_BackSpace) {
-               gboolean html_mode;
+       return FALSE;
+ out:
+       dom_force_spell_check_for_current_paragraph (document, extension);
+       e_html_editor_web_extension_set_content_changed (extension);
 
-               html_mode = e_html_editor_web_extension_get_html_mode (extension);
-               if (!html_mode && e_html_editor_web_extension_get_magic_links_enabled (extension)) {
-                       /* If deleting something in a smiley it won't be a smiley
-                        * anymore (at least from Evolution' POV), so remove all
-                        * the elements that are hidden in the wrapper and leave
-                        * just the text. Also this ensures that when a smiley is
-                        * recognized and we press the BackSpace key we won't delete
-                        * the UNICODE_HIDDEN_SPACE, but we will correctly delete
-                        * the last character of smiley. */
-                       change_smiley_to_plain_text (document);
-               }
-               if (key_val == GDK_KEY_BackSpace && !html_mode) {
-                       if (dom_delete_character_from_quoted_line_start (document, extension, key_val, 
state)) {
-                               e_html_editor_web_extension_set_content_changed (extension);
-                               return TRUE;
-                       }
-               }
-               if (dom_fix_structure_after_delete_before_quoted_content (document, extension, key_val, 
state))
+       return TRUE;
+}
+
+gboolean
+dom_process_on_key_press (WebKitDOMDocument *document,
+                          EHTMLEditorWebExtension *extension,
+                          guint key_val,
+                         guint state)
+{
+       e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+
+       if (key_val == GDK_KEY_Tab || key_val == GDK_KEY_ISO_Left_Tab) {
+               if (jump_to_next_table_cell (document, key_val == GDK_KEY_ISO_Left_Tab))
                        return TRUE;
+
+               if (key_val == GDK_KEY_Tab)
+                       return insert_tabulator (document, extension);
+               else
+                       return FALSE;
+       }
+
+       if (is_return_key (key_val) && key_press_event_process_return_key (document, extension))
+               return TRUE;
+
+       if (key_val == GDK_KEY_BackSpace &&
+           key_press_event_process_backspace_key (document, extension)) {
+               return TRUE;
+       }
+
+       if ((key_val == GDK_KEY_Delete || key_val == GDK_KEY_BackSpace) &&
+           key_press_event_process_delete_or_backspace_key (document, extension, key_val, state, key_val == 
GDK_KEY_Delete)) {
+               return TRUE;
        }
 
        return FALSE;
diff --git a/web-extensions/composer/e-html-editor-view-dom-functions.h 
b/web-extensions/composer/e-html-editor-view-dom-functions.h
index bcc9d59..8fc6691 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.h
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.h
@@ -169,7 +169,8 @@ gboolean    dom_fix_structure_after_delete_before_quoted_content
                                                (WebKitDOMDocument *document,
                                                 EHTMLEditorWebExtension *extension,
                                                 guint key_val,
-                                                guint state);
+                                                guint state,
+                                                gboolean delete_key);
 void           dom_disable_quote_marks_select  (WebKitDOMDocument *document);
 void           dom_remove_node_and_parents_if_empty
                                                (WebKitDOMNode *node);
@@ -180,6 +181,34 @@ gboolean   return_pressed_in_empty_list_item
 void           dom_merge_siblings_if_necessarry
                                                (WebKitDOMDocument *document,
                                                 WebKitDOMDocumentFragment *deleted_content);
+void           body_key_up_event_process_return_key
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension);
+gboolean       key_press_event_process_backspace_key
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension);
+gboolean       key_press_event_process_delete_or_backspace_key
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                guint key_val,
+                                                guint state,
+                                                gboolean delete);
+void           body_input_event_process        (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                WebKitDOMEvent *event);
+void           body_key_up_event_process_backspace_or_delete
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                gboolean delete);
+gboolean       key_press_event_process_return_key
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension);
+WebKitDOMElement *
+               wrap_and_quote_element          (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                WebKitDOMElement *element);
+gint           get_citation_level              (WebKitDOMNode *node,
+                                                gboolean set_plaintext_quoted);
 
 G_END_DECLS
 
diff --git a/web-extensions/composer/e-html-editor-web-extension.c 
b/web-extensions/composer/e-html-editor-web-extension.c
index b7fa35f..6a47af6 100644
--- a/web-extensions/composer/e-html-editor-web-extension.c
+++ b/web-extensions/composer/e-html-editor-web-extension.c
@@ -96,6 +96,7 @@ struct _EHTMLEditorWebExtensionPrivate {
        gboolean dont_save_history_in_body_input;
        gboolean composition_in_progress;
        gboolean is_pasting_content_from_itself;
+       gboolean renew_history_after_coordinates;
 
        GHashTable *inline_images;
 
@@ -2983,6 +2984,7 @@ e_html_editor_web_extension_init (EHTMLEditorWebExtension *extension)
        extension->priv->dont_save_history_in_body_input = FALSE;
        extension->priv->is_pasting_content_from_itself = FALSE;
        extension->priv->composition_in_progress = FALSE;
+       extension->priv->renew_history_after_coordinates = TRUE;
 
        extension->priv->node_under_mouse_click = NULL;
 
@@ -3656,6 +3658,19 @@ e_html_editor_web_extension_is_pasting_content_from_itself (EHTMLEditorWebExtens
        return extension->priv->is_pasting_content_from_itself;
 }
 
+gboolean
+e_html_editor_web_extension_get_renew_history_after_coordinates (EHTMLEditorWebExtension *extension)
+{
+       return extension->priv->renew_history_after_coordinates;
+}
+
+void
+e_html_editor_web_extension_set_renew_history_after_coordinates (EHTMLEditorWebExtension *extension,
+                                                                gboolean renew_history_after_coordinates)
+{
+       extension->priv->renew_history_after_coordinates = renew_history_after_coordinates;
+}
+
 EHTMLEditorUndoRedoManager *
 e_html_editor_web_extension_get_undo_redo_manager (EHTMLEditorWebExtension *extension)
 {
diff --git a/web-extensions/composer/e-html-editor-web-extension.h 
b/web-extensions/composer/e-html-editor-web-extension.h
index 2d74427..65eca0a 100644
--- a/web-extensions/composer/e-html-editor-web-extension.h
+++ b/web-extensions/composer/e-html-editor-web-extension.h
@@ -216,6 +216,11 @@ void               e_html_editor_web_extension_set_dont_save_history_in_body_input
                                                 gboolean value);
 gboolean       e_html_editor_web_extension_is_pasting_content_from_itself
                                                (EHTMLEditorWebExtension *extension);
+gboolean       e_html_editor_web_extension_get_renew_history_after_coordinates
+                                               (EHTMLEditorWebExtension *extension);
+void           e_html_editor_web_extension_set_renew_history_after_coordinates
+                                               (EHTMLEditorWebExtension *extension,
+                                                gboolean renew_history_after_coordinates);
 
 struct _EHTMLEditorUndoRedoManager *
                e_html_editor_web_extension_get_undo_redo_manager


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