[evolution/wip/webkit2] Bug 750615 - Using Ctrl+Z in plain text composer messes up content



commit dd80bec9b548053e4e4a394bd1dde302c6f5a1ae
Author: Tomas Popela <tpopela redhat com>
Date:   Thu Feb 25 21:01:32 2016 +0100

    Bug 750615 - Using Ctrl+Z in plain text composer messes up content

 .../e-html-editor-selection-dom-functions.c        |   10 +-
 .../e-html-editor-selection-dom-functions.h        |    1 +
 .../composer/e-html-editor-undo-redo-manager.c     |  237 ++++++++--
 .../composer/e-html-editor-view-dom-functions.c    |  535 ++++++++++++++-----
 .../composer/e-html-editor-view-dom-functions.h    |   13 +
 5 files changed, 614 insertions(+), 182 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 a2576bc..03918f5 100644
--- a/web-extensions/composer/e-html-editor-selection-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-selection-dom-functions.c
@@ -839,8 +839,8 @@ dom_create_selection_marker (WebKitDOMDocument *document,
        return element;
 }
 
-static void
-remove_selection_markers (WebKitDOMDocument *document)
+void
+dom_remove_selection_markers (WebKitDOMDocument *document)
 {
        WebKitDOMElement *marker;
 
@@ -862,7 +862,7 @@ dom_add_selection_markers_into_element_start (WebKitDOMDocument *document,
 {
        WebKitDOMElement *marker;
 
-       remove_selection_markers (document);
+       dom_remove_selection_markers (document);
        marker = dom_create_selection_marker (document, FALSE);
        webkit_dom_node_insert_before (
                WEBKIT_DOM_NODE (element),
@@ -890,7 +890,7 @@ dom_add_selection_markers_into_element_end (WebKitDOMDocument *document,
 {
        WebKitDOMElement *marker;
 
-       remove_selection_markers (document);
+       dom_remove_selection_markers (document);
        marker = dom_create_selection_marker (document, TRUE);
        webkit_dom_node_append_child (
                WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (marker), NULL);
@@ -1443,7 +1443,7 @@ dom_selection_save (WebKitDOMDocument *document)
        WebKitDOMElement *start_marker = NULL, *end_marker = NULL;
 
        /* First remove all markers (if present) */
-       remove_selection_markers (document);
+       dom_remove_selection_markers (document);
 
        dom_window = webkit_dom_document_get_default_view (document);
        dom_selection = webkit_dom_dom_window_get_selection (dom_window);
diff --git a/web-extensions/composer/e-html-editor-selection-dom-functions.h 
b/web-extensions/composer/e-html-editor-selection-dom-functions.h
index 8220bff..855b3b7 100644
--- a/web-extensions/composer/e-html-editor-selection-dom-functions.h
+++ b/web-extensions/composer/e-html-editor-selection-dom-functions.h
@@ -284,6 +284,7 @@ void                dom_selection_get_coordinates   (WebKitDOMDocument *document,
                                                 guint *start_y,
                                                 guint *end_x,
                                                 guint *end_y);
+void           dom_remove_selection_markers    (WebKitDOMDocument *document);
 G_END_DECLS
 
 #endif /* E_HTML_EDITOR_SELECTION_DOM_FUNCTIONS_H */
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 a76eee2..ecaf56a 100644
--- a/web-extensions/composer/e-html-editor-undo-redo-manager.c
+++ b/web-extensions/composer/e-html-editor-undo-redo-manager.c
@@ -328,6 +328,61 @@ event_selection_was_collapsed (EHTMLEditorHistoryEvent *ev)
 }
 
 static void
+merge_duplicates_if_necessarry (WebKitDOMDocument *document,
+                                WebKitDOMDocumentFragment *deleted_content)
+{
+       gboolean equal_nodes;
+       WebKitDOMElement *element, *prev_element;
+       WebKitDOMNode *child;
+
+       element = webkit_dom_document_query_selector (document, "blockquote + blockquote", NULL);
+       if (!element)
+               goto signature;
+
+       prev_element = WEBKIT_DOM_ELEMENT (webkit_dom_node_get_previous_sibling (
+               WEBKIT_DOM_NODE (element)));
+       equal_nodes = webkit_dom_node_is_equal_node (
+               webkit_dom_node_clone_node (WEBKIT_DOM_NODE (element), FALSE),
+               webkit_dom_node_clone_node (WEBKIT_DOM_NODE (prev_element), FALSE));
+
+       if (equal_nodes) {
+               if (webkit_dom_element_get_child_element_count (element) >
+                   webkit_dom_element_get_child_element_count (prev_element)) {
+                       while ((child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element))))
+                               webkit_dom_node_append_child (
+                                       WEBKIT_DOM_NODE (prev_element), child, NULL);
+                       remove_node (WEBKIT_DOM_NODE (element));
+               } else {
+                       while ((child = webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (prev_element))))
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (element),
+                                       child,
+                                       webkit_dom_node_get_first_child (
+                                               WEBKIT_DOM_NODE (element)),
+                                       NULL);
+                       remove_node (WEBKIT_DOM_NODE (prev_element));
+               }
+       }
+
+ signature:
+       /* Replace the corrupted signatures with the right one. */
+       element = webkit_dom_document_query_selector (
+               document, ".-x-evo-signature-wrapper + .-x-evo-signature-wrapper", NULL);
+       if (element) {
+               WebKitDOMElement *right_signature;
+
+               right_signature = webkit_dom_document_fragment_query_selector (
+                       deleted_content, ".-x-evo-signature-wrapper", NULL);
+               remove_node (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element)));
+               webkit_dom_node_replace_child (
+                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                       webkit_dom_node_clone_node (WEBKIT_DOM_NODE (right_signature), TRUE),
+                       WEBKIT_DOM_NODE (element),
+                       NULL);
+       }
+}
+
+static void
 undo_delete (WebKitDOMDocument *document,
              EHTMLEditorWebExtension *extension,
              EHTMLEditorHistoryEvent *event)
@@ -392,6 +447,8 @@ undo_delete (WebKitDOMDocument *document,
 
        /* 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;
@@ -414,11 +471,68 @@ undo_delete (WebKitDOMDocument *document,
                /* All the nodes that are in current block after the caret position
                 * belongs on the end of the deleted content. */
                node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+
+               /* 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
+                * 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);
+               delete = signature && webkit_dom_node_contains (WEBKIT_DOM_NODE (signature), WEBKIT_DOM_NODE 
(element));
+               if (!delete) {
+                       WebKitDOMNode *tmp_node;
+
+                       tmp_node = webkit_dom_node_get_last_child (fragment);
+                       delete = tmp_node && WEBKIT_DOM_IS_ELEMENT (tmp_node) &&
+                               element_has_class (WEBKIT_DOM_ELEMENT (tmp_node), "-x-evo-signature-wrapper");
+               }
+
                while (node) {
                        WebKitDOMNode *next_sibling;
 
                        next_sibling = webkit_dom_node_get_next_sibling (node);
-                       webkit_dom_node_append_child (last_child, node, NULL);
+                       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. */
+                               if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element))) {
+                                       WebKitDOMNode *tmp_node;
+                                       WebKitDOMElement *tmp_element;
+
+                                       tmp_node = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE 
(element));
+                                       webkit_dom_node_replace_child (
+                                               webkit_dom_node_get_parent_node (tmp_node),
+                                               fragment,
+                                               tmp_node,
+                                               NULL);
+
+                                       tmp_element = webkit_dom_document_get_element_by_id (
+                                               document, "-x-evo-tmp-block");
+                                       if (tmp_element)
+                                               webkit_dom_element_remove_attribute (tmp_element, "id");
+
+                                       /* Remove empty blockquotes, if presented. */
+                                       tmp_element = webkit_dom_document_query_selector (
+                                               document, "blockquote[type=cite]:empty", NULL);
+                                       if (tmp_element)
+                                               remove_node (WEBKIT_DOM_NODE (tmp_element));
+
+                                       merge_duplicates_if_necessarry (document, event->data.fragment);
+
+                                       dom_remove_selection_markers (document);
+
+                                       restore_selection_to_history_event_state (document, event->before);
+
+                                       dom_force_spell_check_in_viewport (document, extension);
+
+                                       g_object_unref (dom_selection);
+
+                                       return;
+                               }
+                       }
+                       if (delete)
+                               remove_node (node);
+                       else
+                               webkit_dom_node_append_child (last_child, node, NULL);
                        node = next_sibling;
                }
 
@@ -441,27 +555,31 @@ undo_delete (WebKitDOMDocument *document,
                remove_node (first_child);
 
                /* Move the deleted content back to the body. Start from the next sibling
-                * of the first block (if presented) where the delete occured. */
+                * of the first block (if presented) where the delete occurred. */
                while (parent_deleted_content) {
-                       WebKitDOMNode *tmp, *sibling;
+                       WebKitDOMNode *tmp, *child;
 
                        /* Move all the siblings from current level back to the body. */
-                       sibling = webkit_dom_node_get_first_child (parent_deleted_content);
-                       while (sibling) {
+                       child = webkit_dom_node_get_first_child (parent_deleted_content);
+                       while (child) {
                                WebKitDOMNode *next_sibling;
 
-                               next_sibling = webkit_dom_node_get_next_sibling (sibling);
+                               next_sibling = webkit_dom_node_get_next_sibling (child);
                                webkit_dom_node_insert_before (
-                                       parent_current_block, sibling, insert_before, NULL);
-                               sibling = next_sibling;
+                                       parent_current_block, child, insert_before, NULL);
+                               child = next_sibling;
                        }
                        tmp = webkit_dom_node_get_parent_node (parent_deleted_content);
                        remove_node (parent_deleted_content);
                        parent_deleted_content = tmp;
                        insert_before = webkit_dom_node_get_next_sibling (parent_current_block);
-                       parent_current_block = webkit_dom_node_get_parent_node (parent_current_block);
+                       /* 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);
                }
 
+               merge_duplicates_if_necessarry (document, event->data.fragment);
+
                dom_selection_restore (document);
                dom_force_spell_check_in_viewport (document, extension);
        } else {
@@ -504,8 +622,8 @@ undo_delete (WebKitDOMDocument *document,
                remove_node (WEBKIT_DOM_NODE (element));
 
                /* If the selection markers are presented restore the selection,
-                * otherwise the selection was not callapsed so select the deleted
-                * content as it was before the delete occured. */
+                * otherwise the selection was not collapsed so select the deleted
+                * content as it was before the delete occurred. */
                if (webkit_dom_document_fragment_query_selector (event->data.fragment, 
"span#-x-evo-selection-start-marker", NULL))
                        dom_selection_restore (document);
                else
@@ -552,7 +670,7 @@ redo_delete (WebKitDOMDocument *document,
 
                        text_content = webkit_dom_node_get_text_content (WEBKIT_DOM_NODE (fragment));
                        length = g_utf8_strlen (text_content, -1);
-                       control_key = control_key && length > 1;
+                       control_key = length > 1;
 
                        g_free (text_content);
                }
@@ -569,8 +687,15 @@ redo_delete (WebKitDOMDocument *document,
                }
 
                g_object_unref (dom_selection);
-       } else
-               dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+       } 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);
+       }
+
+       restore_selection_to_history_event_state (document, event->after);
 
        dom_force_spell_check_for_current_paragraph (document, extension);
 }
@@ -1450,6 +1575,14 @@ undo_redo_citation_split (WebKitDOMDocument *document,
                           EHTMLEditorHistoryEvent *event,
                           gboolean undo)
 {
+       gboolean in_situ = FALSE;
+
+       if (event->before.start.x == event->after.start.x &&
+           event->before.start.y == event->after.start.y &&
+           event->after.end.x == event->after.end.x &&
+           event->after.end.y == event->after.end.y)
+               in_situ = TRUE;
+
        if (undo) {
                gint citation_level = 1, length, word_wrap_length;
                WebKitDOMElement *selection_start, *parent;
@@ -1466,12 +1599,16 @@ undo_redo_citation_split (WebKitDOMDocument *document,
                parent = get_parent_block_element (WEBKIT_DOM_NODE (selection_start));
 
                citation_before = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (parent));
-               if (!dom_node_is_citation_node (citation_before))
+               if (!dom_node_is_citation_node (citation_before)) {
+                       dom_selection_restore (document);
                        return;
+               }
 
                citation_after = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent));
-               if (!dom_node_is_citation_node (citation_after))
+               if (!dom_node_is_citation_node (citation_after)) {
+                       dom_selection_restore (document);
                        return;
+               }
 
                /* Get first block in next citation. */
                child = webkit_dom_node_get_first_child (citation_after);
@@ -1480,48 +1617,77 @@ undo_redo_citation_split (WebKitDOMDocument *document,
                        child = webkit_dom_node_get_first_child (child);
                }
 
-               dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (child));
-               dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (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);
 
-               dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (last_child));
-               dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (last_child));
+               if (in_situ) {
+                       webkit_dom_node_append_child (
+                               webkit_dom_node_get_parent_node (last_child),
+                               webkit_dom_node_clone_node (
+                                       WEBKIT_DOM_NODE (event->data.fragment), TRUE),
+                               NULL);
+               } else {
+                       dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (child));
+                       dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (child));
 
-               /* Copy the content of the first block to the last block to get
-                * to the state how the block looked like before it was split. */
-               while ((tmp = webkit_dom_node_get_first_child (child)))
-                       webkit_dom_node_append_child (last_child, tmp, NULL);
+                       dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (last_child));
+                       dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (last_child));
 
-               word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
-               length = word_wrap_length - 2 * citation_level;
+                       /* Copy the content of the first block to the last block to get
+                        * to the state how the block looked like before it was split. */
+                       while ((tmp = webkit_dom_node_get_first_child (child)))
+                               webkit_dom_node_append_child (last_child, tmp, NULL);
 
-               /* 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);
+                       word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
+                       length = word_wrap_length - 2 * citation_level;
 
-               remove_node (child);
+                       /* 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);
+
+                       remove_node (child);
+               }
 
                /* Move all the block from next citation to the previous one. */
                while ((child = webkit_dom_node_get_first_child (citation_after)))
                        webkit_dom_node_append_child (citation_before, child, NULL);
 
+               dom_remove_selection_markers (document);
+
                remove_node (WEBKIT_DOM_NODE (parent));
                remove_node (WEBKIT_DOM_NODE (citation_after));
 
                /* If enter was pressed when some text was selected, restore it. */
-               if (event->data.fragment != NULL)
+               if (event->data.fragment != NULL && !in_situ)
                        undo_delete (document, extension, event);
 
                restore_selection_to_history_event_state (document, event->before);
 
                dom_force_spell_check_in_viewport (document, extension);
        } else {
+               if (in_situ) {
+                       WebKitDOMElement *selection_start_marker;
+                       WebKitDOMNode *block;
+
+                       dom_selection_save (document);
+
+                       selection_start_marker = webkit_dom_document_get_element_by_id (
+                               document, "-x-evo-selection-start-marker");
+
+                       block = get_parent_block_node_from_child (
+                               WEBKIT_DOM_NODE (selection_start_marker));
+                       dom_remove_selection_markers (document);
+
+                       /* 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);
+               }
+
                dom_insert_new_line_into_citation (document, extension, "");
        }
 }
@@ -1612,9 +1778,8 @@ undo_redo_unquote (WebKitDOMDocument *document,
                }
 
                remove_node (WEBKIT_DOM_NODE (block));
-       } else {
+       } else
                dom_change_quoted_block_to_normal (document, extension);
-       }
 
        if (undo)
                restore_selection_to_history_event_state (document, event->before);
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 4ec593f..b6f69ba 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.c
@@ -2585,8 +2585,8 @@ remove_empty_blocks (WebKitDOMDocument *document)
  * the selection. This will avoid it as when the delete or backspace key is pressed
  * we will make the quote marks user selectable so they will act as any other text.
  * On HTML keyup event callback we will make them again non-selectable. */
-static void
-disable_quote_marks_select (WebKitDOMDocument *document)
+void
+dom_disable_quote_marks_select (WebKitDOMDocument *document)
 {
        WebKitDOMHTMLHeadElement *head;
        WebKitDOMElement *style_element;
@@ -2615,6 +2615,39 @@ enable_quote_marks_select (WebKitDOMDocument *document)
                remove_node (WEBKIT_DOM_NODE (style_element));
 }
 
+void
+dom_remove_node_and_parents_if_empty (WebKitDOMNode *node)
+{
+       WebKitDOMNode *parent;
+
+       parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (node));
+
+       remove_node (WEBKIT_DOM_NODE (node));
+
+       while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+               WebKitDOMNode *prev_sibling, *next_sibling;
+
+               prev_sibling = webkit_dom_node_get_previous_sibling (parent);
+               next_sibling = webkit_dom_node_get_next_sibling (parent);
+               /* Empty or BR as sibling, but no sibling after it. */
+               if ((!prev_sibling ||
+                    (WEBKIT_DOM_IS_HTML_BR_ELEMENT (prev_sibling) &&
+                     !webkit_dom_node_get_previous_sibling (prev_sibling))) &&
+                   (!next_sibling ||
+                    (WEBKIT_DOM_IS_HTML_BR_ELEMENT (next_sibling) &&
+                     !webkit_dom_node_get_next_sibling (next_sibling)))) {
+                       WebKitDOMNode *tmp;
+
+                       tmp = webkit_dom_node_get_parent_node (parent);
+                       remove_node (parent);
+                       parent = tmp;
+               } else {
+                       remove_node (parent);
+                       return;
+               }
+       }
+}
+
 static void
 body_keyup_event_cb (WebKitDOMElement *element,
                      WebKitDOMUIEvent *event,
@@ -2638,12 +2671,12 @@ body_keyup_event_cb (WebKitDOMElement *element,
                gint level;
                WebKitDOMElement *selection_start_marker, *selection_end_marker;
                WebKitDOMElement *tmp_element;
-               WebKitDOMNode *parent;
+               WebKitDOMNode *parent, *node;
 
                if (e_html_editor_web_extension_get_html_mode (extension))
                        return;
 
-               disable_quote_marks_select (document);
+               dom_disable_quote_marks_select (document);
                /* Remove empty blocks if presented. */
                remove_empty_blocks (document);
 
@@ -2675,7 +2708,8 @@ body_keyup_event_cb (WebKitDOMElement *element,
                /* 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);
-               if (level > 0) {
+               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 (
@@ -2687,19 +2721,77 @@ body_keyup_event_cb (WebKitDOMElement *element,
 
                                block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
                                        WEBKIT_DOM_NODE (selection_start_marker)));
-                               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));
+                               if (webkit_dom_element_has_attribute (block, "data-no-quote")) {
+                                       webkit_dom_element_remove_attribute (block, "data-no-quote");
+                               } else {
+                                       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);
                                }
-                               dom_quote_plain_text_element_after_wrapping (
-                                       document, block, level);
                        }
-               }
+               } else if (node && WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
+                       EHTMLEditorUndoRedoManager *manager;
+                       EHTMLEditorHistoryEvent *event;
+                       WebKitDOMDocumentFragment *fragment;
+                       WebKitDOMNode *block;
+
+                       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_remove_selection_markers (document);
+
+                       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+                       event->type = HISTORY_AND;
+
+                       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+
+                       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+                       event->type = HISTORY_CITATION_SPLIT;
+
+                       dom_selection_get_coordinates (
+                               document,
+                               &event->before.start.x,
+                               &event->before.start.y,
+                               &event->before.end.x,
+                               &event->before.end.y);
+
+                       fragment = webkit_dom_document_create_document_fragment (document);
+
+                       /* Save the current block as it will be removed few lines after this. */
+                       webkit_dom_node_append_child (
+                               WEBKIT_DOM_NODE (fragment),
+                               webkit_dom_node_clone_node (block, TRUE),
+                               NULL);
+
+                       event->data.fragment = fragment;
+
+                       /* 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);
+
+                       dom_insert_new_line_into_citation (document, extension, "");
+
+                       dom_selection_get_coordinates (
+                               document,
+                               &event->after.start.x,
+                               &event->after.start.y,
+                               &event->after.end.x,
+                               &event->after.end.y);
+
+                       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+
+                       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
@@ -2715,6 +2807,18 @@ body_keyup_event_cb (WebKitDOMElement *element,
                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);
+
                        webkit_dom_element_remove_attribute (tmp_element, "id");
 
                        parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp_element));
@@ -4400,7 +4504,7 @@ clear_attributes (WebKitDOMDocument *document)
                remove_node (webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (head)));
 
        /* Make the quote marks non-selectable. */
-       disable_quote_marks_select (document);
+       dom_disable_quote_marks_select (document);
 
        /* Remove non Evolution attributes from BODY element */
        attributes = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (body));
@@ -6847,7 +6951,7 @@ dom_process_content_after_load (WebKitDOMDocument *document,
        if (e_html_editor_web_extension_get_convert_in_situ (extension)) {
                dom_convert_content (document, extension, NULL);
                /* Make the quote marks non-selectable. */
-               disable_quote_marks_select (document);
+               dom_disable_quote_marks_select (document);
                dom_set_links_active (document, FALSE);
                e_html_editor_web_extension_set_convert_in_situ (extension, FALSE);
 
@@ -6855,7 +6959,7 @@ dom_process_content_after_load (WebKitDOMDocument *document,
        }
 
        /* Make the quote marks non-selectable. */
-       disable_quote_marks_select (document);
+       dom_disable_quote_marks_select (document);
        dom_set_links_active (document, FALSE);
        put_body_in_citation (document);
        move_elements_to_body (document, extension);
@@ -7102,122 +7206,6 @@ dom_insert_html (WebKitDOMDocument *document,
        }
 }
 
-static gboolean
-fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *document)
-{
-       gboolean collapsed = FALSE;
-       WebKitDOMElement *selection_start_marker, *selection_end_marker;
-       WebKitDOMNode *block, *node;
-
-       collapsed = dom_selection_is_collapsed (document);
-
-       dom_selection_save (document);
-
-       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;
-
-       if (collapsed) {
-               WebKitDOMNode *next_sibling;
-
-               block = get_parent_block_node_from_child (
-                       WEBKIT_DOM_NODE (selection_start_marker));
-
-               next_sibling = webkit_dom_node_get_next_sibling (block);
-
-               /* Next block is quoted content */
-               if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling))
-                       goto restore;
-
-               /* Delete was pressed in block without any content */
-               if (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
-                       goto restore;
-
-               /* If there is just BR element go ahead */
-               node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
-               if (node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node))
-                       goto restore;
-               else {
-                       /* Remove the empty block and move caret into the beginning of the citation */
-                       remove_node (block);
-
-                       dom_move_caret_into_element (
-                               document, WEBKIT_DOM_ELEMENT (next_sibling), TRUE);
-
-                       return TRUE;
-               }
-       } else {
-               WebKitDOMNode *end_block;
-
-               /* Let the quote marks be selectable to nearly correctly remove the
-                * selection. Corrections after are done in body_keyup_event_cb. */
-               enable_quote_marks_select (document);
-
-               node = webkit_dom_node_get_previous_sibling (
-                       WEBKIT_DOM_NODE (selection_start_marker));
-
-               if (!node || !WEBKIT_DOM_IS_ELEMENT (node))
-                       goto restore;
-
-               if (!element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted"))
-                       goto restore;
-
-               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 (
-                       WEBKIT_DOM_NODE (selection_end_marker));
-
-               /* Situation where the start of the selection is in the beginning
-               + * of the block in quoted content and the end in the beginning of
-               + * content that is after the citation or the selection end is in
-               + * the end of the quoted content (showed by ^). We have to
-               + * mark the start block to correctly restore the structure
-               + * afterwards.
-               *
-               * > |xxx
-               * > xxx^
-               * |xxx
-               */
-               if (get_citation_level (end_block, FALSE) > 0) {
-                       WebKitDOMNode *parent;
-
-                       if (webkit_dom_node_get_next_sibling (end_block))
-                               goto restore;
-
-                       parent = webkit_dom_node_get_parent_node (end_block);
-                       while (parent && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent)) {
-                               WebKitDOMNode *next_parent = webkit_dom_node_get_parent_node (parent);
-
-                               if (webkit_dom_node_get_next_sibling (parent) &&
-                                   !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (next_parent))
-                                       goto restore;
-
-                               parent = next_parent;
-                       }
-               }
-               node = webkit_dom_node_get_next_sibling (
-               WEBKIT_DOM_NODE (selection_end_marker));
-               if (!node || WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
-                       webkit_dom_element_set_id (
-                               WEBKIT_DOM_ELEMENT (block), "-x-evo-tmp-block");
-               }
-       }
- restore:
-       dom_selection_restore (document);
-
-       return FALSE;
-}
-
 static void
 save_history_for_delete_or_backspace (WebKitDOMDocument *document,
                                       EHTMLEditorWebExtension *extension,
@@ -7382,11 +7370,123 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
 
                e_html_editor_web_extension_unblock_selection_changed_callback (extension);
        } else {
+               WebKitDOMElement *tmp_element;
+               WebKitDOMNode *sibling;
+
                ev->after.start.x = ev->before.start.x;
                ev->after.start.y = ev->before.start.y;
                ev->after.end.x = ev->before.start.x;
                ev->after.end.y = ev->before.start.y;
+
                fragment = webkit_dom_range_clone_contents (range, NULL);
+
+               tmp_element = webkit_dom_document_fragment_query_selector (
+                       fragment, "#-x-evo-selection-start-marker", NULL);
+               if (tmp_element)
+                       remove_node (WEBKIT_DOM_NODE (tmp_element));
+
+               tmp_element = webkit_dom_document_fragment_query_selector (
+                       fragment, "#-x-evo-selection-end-marker", NULL);
+               if (tmp_element)
+                       remove_node (WEBKIT_DOM_NODE (tmp_element));
+
+               /* If any empty blockquote is presented, remove it. */
+               tmp_element = webkit_dom_document_query_selector (
+                       document, "blockquote[type=cite]:empty", NULL);
+               if (tmp_element)
+                       remove_node (WEBKIT_DOM_NODE (tmp_element));
+
+               /* Selection starts in the beginning of blockquote. */
+               tmp_element = webkit_dom_document_get_element_by_id (
+                       document, "-x-evo-selection-start-marker");
+               sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (tmp_element));
+               if (sibling && WEBKIT_DOM_IS_ELEMENT (sibling) &&
+                   element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-quoted")) {
+                       WebKitDOMNode *child;
+
+                       tmp_element = webkit_dom_document_get_element_by_id (
+                               document, "-x-evo-selection-end-marker");
+
+                       /* If there is no text after the selection end it means that
+                        * the block will be replaced with block that is body's descendant
+                        * and not the blockquote's one. Also if the selection started
+                        * in the beginning of blockquote we have to insert the quote
+                        * characters into the deleted content to correctly restore
+                        * them during undo/redo operations. */
+                       if (!(tmp_element && webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE 
(tmp_element)))) {
+                               child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+                               while (child && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (child))
+                                       child = webkit_dom_node_get_first_child (child);
+
+                               child = webkit_dom_node_get_first_child (child);
+                               if (child && (WEBKIT_DOM_IS_TEXT (child) ||
+                                   (WEBKIT_DOM_IS_ELEMENT (child) &&
+                                    !element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-quoted")))) {
+                                               printf ("%s\n", __FUNCTION__);
+                                               printf ("%s\n", __FUNCTION__);
+                                               printf ("%s\n", __FUNCTION__);
+                                               printf ("%s\n", __FUNCTION__);
+                                               printf ("%s\n", __FUNCTION__);
+                                       webkit_dom_node_insert_before (
+                                               webkit_dom_node_get_parent_node (child),
+                                               webkit_dom_node_clone_node (sibling, TRUE),
+                                               child,
+                                               NULL);
+                               }
+                       }
+               }
+
+               /* When we were cloning the range above and the range contained
+                * quoted content there will still be blockquote missing in the
+                * final range. Let's modify the fragment and add it there. */
+               tmp_element = webkit_dom_document_get_element_by_id (
+                       document, "-x-evo-selection-end-marker");
+               if (tmp_element) {
+                       WebKitDOMNode *node;
+
+                       node = WEBKIT_DOM_NODE (tmp_element);
+                       while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (node))) {
+                               if (webkit_dom_node_get_next_sibling (node))
+                                       break;
+                               node = webkit_dom_node_get_parent_node (node);
+                       }
+
+                       if (node && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node)) {
+                               WebKitDOMNode *last_child;
+
+                               last_child = webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment));
+
+                               if (last_child && !WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (last_child)) {
+                                       WebKitDOMDocumentFragment *tmp_fragment;
+                                       WebKitDOMNode *clone;
+
+                                       tmp_fragment = webkit_dom_document_create_document_fragment 
(document);
+                                       clone = webkit_dom_node_clone_node (node, FALSE);
+                                       clone = webkit_dom_node_append_child (
+                                               WEBKIT_DOM_NODE (tmp_fragment), clone, NULL);
+                                       webkit_dom_node_append_child (clone, WEBKIT_DOM_NODE (fragment), 
NULL);
+                                       fragment = tmp_fragment;
+                               }
+                       }
+               }
+
+               /* FIXME Ugly hack */
+               /* If the deleted selection contained the signature (or at least its
+                * part) replace it with the unchanged signature to correctly perform
+                * undo operation. */
+               tmp_element = webkit_dom_document_fragment_query_selector (fragment, 
".-x-evo-signature-wrapper", NULL);
+               if (tmp_element) {
+                       WebKitDOMElement *signature;
+
+                       signature = webkit_dom_document_query_selector (document, 
".-x-evo-signature-wrapper", NULL);
+                       if (signature) {
+                               webkit_dom_node_replace_child (
+                                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp_element)),
+                                       webkit_dom_node_clone_node (WEBKIT_DOM_NODE (signature), TRUE),
+                                       WEBKIT_DOM_NODE (tmp_element),
+                                       NULL);
+                       }
+               }
        }
 
        g_object_unref (range);
@@ -7398,6 +7498,142 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
        e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
 }
 
+gboolean
+dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *document,
+                                                     EHTMLEditorWebExtension *extension,
+                                                     guint key_val,
+                                                     guint state)
+{
+       gboolean collapsed = FALSE;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker;
+       WebKitDOMNode *block, *node;
+
+       collapsed = dom_selection_is_collapsed (document);
+
+       dom_selection_save (document);
+
+       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;
+
+       if (collapsed) {
+               WebKitDOMNode *next_sibling;
+
+               block = get_parent_block_node_from_child (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+
+               next_sibling = webkit_dom_node_get_next_sibling (block);
+
+               /* Next block is quoted content */
+               if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling))
+                       goto restore;
+
+               /* Delete was pressed in block without any content */
+               if (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
+                       goto restore;
+
+               /* If there is just BR element go ahead */
+               node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
+               if (node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node))
+                       goto restore;
+               else {
+                       if (key_val != ~0)
+                               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_node (block);
+
+                       dom_move_caret_into_element (
+                               document, WEBKIT_DOM_ELEMENT (next_sibling), TRUE);
+
+                       return TRUE;
+               }
+       } else {
+               WebKitDOMNode *end_block, *parent;
+
+               /* Let the quote marks be selectable to nearly correctly remove the
+                * selection. Corrections after are done in body_keyup_event_cb. */
+               enable_quote_marks_select (document);
+
+               parent = webkit_dom_node_get_parent_node (
+                       WEBKIT_DOM_NODE (selection_start_marker));
+               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent) ||
+                   element_has_tag (WEBKIT_DOM_ELEMENT (parent), "b") ||
+                   element_has_tag (WEBKIT_DOM_ELEMENT (parent), "i") ||
+                   element_has_tag (WEBKIT_DOM_ELEMENT (parent), "u"))
+                       node = webkit_dom_node_get_previous_sibling (parent);
+               else
+                       node = webkit_dom_node_get_previous_sibling (
+                               WEBKIT_DOM_NODE (selection_start_marker));
+
+               if (!node || !WEBKIT_DOM_IS_ELEMENT (node))
+                       goto restore;
+
+               if (!element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted"))
+                       goto restore;
+
+               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 (
+                       WEBKIT_DOM_NODE (selection_end_marker));
+
+               /* Situation where the start of the selection is in the beginning
+               + * of the block in quoted content and the end in the beginning of
+               + * content that is after the citation or the selection end is in
+               + * the end of the quoted content (showed by ^). We have to
+               + * mark the start block to correctly restore the structure
+               + * afterwards.
+               *
+               * > |xxx
+               * > xxx^
+               * |xxx
+               */
+               if (get_citation_level (end_block, FALSE) > 0) {
+                       WebKitDOMNode *parent;
+
+                       if (webkit_dom_node_get_next_sibling (end_block))
+                               goto restore;
+
+                       parent = webkit_dom_node_get_parent_node (end_block);
+                       while (parent && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent)) {
+                               WebKitDOMNode *next_parent = webkit_dom_node_get_parent_node (parent);
+
+                               if (webkit_dom_node_get_next_sibling (parent) &&
+                                   !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (next_parent))
+                                       goto restore;
+
+                               parent = next_parent;
+                       }
+               }
+
+               node = webkit_dom_node_get_next_sibling (
+                       WEBKIT_DOM_NODE (selection_end_marker));
+               if (!node || WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
+                       webkit_dom_element_set_id (
+                               WEBKIT_DOM_ELEMENT (block), "-x-evo-tmp-block");
+               }
+       }
+ restore:
+       if (key_val != ~0)
+               save_history_for_delete_or_backspace (
+                       document, extension, key_val == GDK_KEY_Delete, (state & GDK_CONTROL_MASK) != 0);
+
+       dom_selection_restore (document);
+
+       return FALSE;
+}
+
 static gboolean
 split_citation (WebKitDOMDocument *document,
                 EHTMLEditorWebExtension *extension)
@@ -7597,8 +7833,11 @@ jump_to_next_table_cell (WebKitDOMDocument *document,
        return TRUE;
 }
 
-static gboolean
-delete_character_from_quoted_line_start (WebKitDOMDocument *document)
+gboolean
+dom_delete_character_from_quoted_line_start (WebKitDOMDocument *document,
+                                            EHTMLEditorWebExtension *extension,
+                                            guint key_val,
+                                            guint state)
 {
        WebKitDOMElement *element;
        WebKitDOMNode *node, *beginning;
@@ -7640,7 +7879,22 @@ delete_character_from_quoted_line_start (WebKitDOMDocument *document)
        if (!(element_has_class (WEBKIT_DOM_ELEMENT (beginning), "-x-evo-quoted")))
                return FALSE;
 
-       remove_node (beginning);
+       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);
+
+       dom_remove_quoting_from_element (element);
+
+       webkit_dom_node_append_child (
+               WEBKIT_DOM_NODE (element),
+               WEBKIT_DOM_NODE (
+                       webkit_dom_document_create_element (document, "br", NULL)),
+               NULL);
+
+       webkit_dom_element_set_attribute (element, "data-no-quote", "", NULL);
+
        remove_node (node);
 
        dom_selection_restore (document);
@@ -7856,12 +8110,11 @@ dom_process_on_key_press (WebKitDOMDocument *document,
                        }
                        dom_selection_restore (document);
                }
-               save_history_for_delete_or_backspace (document, extension, key_val == GDK_KEY_Delete, (state 
& GDK_CONTROL_MASK) != 0);
                if (key_val == GDK_KEY_BackSpace && !html_mode) {
-                       if (delete_character_from_quoted_line_start (document))
+                       if (dom_delete_character_from_quoted_line_start (document, extension, key_val, state))
                                return TRUE;
                }
-               if (fix_structure_after_delete_before_quoted_content (document))
+               if (dom_fix_structure_after_delete_before_quoted_content (document, extension, key_val, 
state))
                        return TRUE;
        }
 
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 213d3f0..81242f4 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.h
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.h
@@ -160,6 +160,19 @@ void               dom_set_visited_link_color      (WebKitDOMDocument *document,
 gboolean       dom_change_quoted_block_to_normal
                                                (WebKitDOMDocument *document,
                                                 EHTMLEditorWebExtension *extension);
+gboolean       dom_delete_character_from_quoted_line_start
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                guint key_val,
+                                                guint state);
+gboolean       dom_fix_structure_after_delete_before_quoted_content
+                                               (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension,
+                                                guint key_val,
+                                                guint state);
+void           dom_disable_quote_marks_select  (WebKitDOMDocument *document);
+void           dom_remove_node_and_parents_if_empty
+                                               (WebKitDOMNode *node);
 
 G_END_DECLS
 



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