[evolution] Fix various problems with deleting the selection that ends or starts in the quoted content



commit 80405083300384a2c63566e95cc27f61bfc488ec
Author: Tomas Popela <tpopela redhat com>
Date:   Wed Jan 28 11:13:30 2015 +0100

    Fix various problems with deleting the selection that ends or starts in the quoted content

 e-util/e-html-editor-selection.c |   13 ++--
 e-util/e-html-editor-selection.h |    3 +-
 e-util/e-html-editor-view.c      |  164 +++++++++++++++++++++++++++++++++++--
 3 files changed, 164 insertions(+), 16 deletions(-)
---
diff --git a/e-util/e-html-editor-selection.c b/e-util/e-html-editor-selection.c
index b755072..5684e5e 100644
--- a/e-util/e-html-editor-selection.c
+++ b/e-util/e-html-editor-selection.c
@@ -3771,7 +3771,7 @@ e_html_editor_selection_set_monospaced (EHTMLEditorSelection *selection,
                                range, WEBKIT_DOM_NODE (monospace), NULL);
 
                        e_html_editor_selection_move_caret_into_element (
-                               document, monospace);
+                               document, monospace, FALSE);
                }
        } else {
                gboolean is_bold, is_italic, is_underline, is_strikethrough;
@@ -4857,7 +4857,8 @@ e_html_editor_selection_replace_image_src (EHTMLEditorSelection *selection,
 
 void
 e_html_editor_selection_move_caret_into_element (WebKitDOMDocument *document,
-                                                 WebKitDOMElement *element)
+                                                 WebKitDOMElement *element,
+                                                 gboolean to_start)
 {
        WebKitDOMDOMWindow *window;
        WebKitDOMDOMSelection *window_selection;
@@ -4871,8 +4872,8 @@ e_html_editor_selection_move_caret_into_element (WebKitDOMDocument *document,
        new_range = webkit_dom_document_create_range (document);
 
        webkit_dom_range_select_node_contents (
-                       new_range, WEBKIT_DOM_NODE (element), NULL);
-       webkit_dom_range_collapse (new_range, FALSE, NULL);
+               new_range, WEBKIT_DOM_NODE (element), NULL);
+       webkit_dom_range_collapse (new_range, to_start, NULL);
        webkit_dom_dom_selection_remove_all_ranges (window_selection);
        webkit_dom_dom_selection_add_range (window_selection, new_range);
 }
@@ -5071,13 +5072,13 @@ e_html_editor_selection_restore_caret_position (EHTMLEditorSelection *selection)
                                remove_node (WEBKIT_DOM_NODE (element));
 
                                e_html_editor_selection_move_caret_into_element (
-                                       document, WEBKIT_DOM_ELEMENT (next_sibling));
+                                       document, WEBKIT_DOM_ELEMENT (next_sibling), FALSE);
 
                                goto out;
                        }
                }
 
-               e_html_editor_selection_move_caret_into_element (document, element);
+               e_html_editor_selection_move_caret_into_element (document, element, FALSE);
 
                if (fix_after_quoting) {
                        prev_sibling = webkit_dom_node_get_previous_sibling (
diff --git a/e-util/e-html-editor-selection.h b/e-util/e-html-editor-selection.h
index 3290dfe..5ae9492 100644
--- a/e-util/e-html-editor-selection.h
+++ b/e-util/e-html-editor-selection.h
@@ -185,7 +185,8 @@ void                e_html_editor_selection_insert_image
                                                 const gchar *image_uri);
 void           e_html_editor_selection_move_caret_into_element
                                                (WebKitDOMDocument *document,
-                                                WebKitDOMElement *element);
+                                                WebKitDOMElement *element,
+                                                gboolean to_start);
 void           e_html_editor_selection_clear_caret_position_marker
                                                (EHTMLEditorSelection *selection);
 WebKitDOMNode *
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 77a1df7..76a767a 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -2179,10 +2179,13 @@ body_keyup_event_cb (WebKitDOMElement *element,
                 * BackSpace or Delete. */
                gint level;
                WebKitDOMElement *selection_start_marker, *selection_end_marker;
-               WebKitDOMElement *br_element;
+               WebKitDOMElement *tmp_element;
                WebKitDOMDocument *document;
                WebKitDOMNode *node, *parent;
 
+               if (e_html_editor_view_get_html_mode (view))
+                       return;
+
                document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
 
                e_html_editor_selection_save (selection);
@@ -2191,6 +2194,33 @@ body_keyup_event_cb (WebKitDOMElement *element,
                selection_end_marker = webkit_dom_document_get_element_by_id (
                        document, "-x-evo-selection-end-marker");
 
+               /* Situation where the end of the selection was in the
+                * middle of quoted content and the start in the beginning of
+                * the non quoted content before the citation. WebKit took out
+                * the block from citation and inserted the block before the citation.
+                * We made a clone of the original block so we have to move the
+                * content there and reinsert the quote marks.
+                *
+                * |xxx
+                * > x|xx
+                * */
+               tmp_element = webkit_dom_document_get_element_by_id (document, "-x-evo-repair-block");
+               if (tmp_element) {
+                       parent = get_parent_block_node_from_child (
+                               WEBKIT_DOM_NODE (selection_start_marker));
+
+                       while ((node = webkit_dom_node_get_first_child (parent)))
+                               webkit_dom_node_append_child (
+                                       WEBKIT_DOM_NODE (tmp_element), node, NULL);
+
+                       level = get_citation_level (WEBKIT_DOM_NODE (tmp_element), FALSE);
+                       quote_plain_text_element_after_wrapping (
+                               document, tmp_element, level);
+                       webkit_dom_element_remove_attribute (tmp_element, "id");
+                       remove_node (parent);
+                       goto restore;
+               }
+
                level = get_citation_level (
                        WEBKIT_DOM_NODE (selection_start_marker), FALSE);
 
@@ -2212,10 +2242,29 @@ body_keyup_event_cb (WebKitDOMElement *element,
                parent = get_parent_block_node_from_child (
                        WEBKIT_DOM_NODE (selection_start_marker));
 
+               if (!node) {
+                       /* Situation where the end of the selection was in the
+                        * beginning of the block inside the quoted content and
+                        * the start in non quoted content before the citation.
+                        * In this situation WebKit will do the things right, but
+                        * it will remove the quote marks so we have to restore them.
+                        *
+                        * xx|x
+                        * > |xxx
+                        * */
+                       tmp_element = webkit_dom_element_query_selector (
+                               WEBKIT_DOM_ELEMENT (parent), "span.-x-evo-quoted", NULL);
+                       if (!tmp_element) {
+                               quote_plain_text_element_after_wrapping (
+                                       document, WEBKIT_DOM_ELEMENT (parent), level);
+                               goto restore;
+                       }
+               }
+
                node = webkit_dom_node_get_previous_sibling (parent);
                if (!node) {
-                       /* Situation where the start of the selection was in the
-                        * multiple quoted content and that start on the beginning
+                       /* Situation where the end of the selection was in the
+                        * multiple quoted content and the start on the beginning
                         * of the citation.
                         *
                         * >
@@ -2232,9 +2281,9 @@ body_keyup_event_cb (WebKitDOMElement *element,
                                goto restore;
                }
 
-               br_element = webkit_dom_element_query_selector (
+               tmp_element = webkit_dom_element_query_selector (
                        WEBKIT_DOM_ELEMENT (node), "span.-x-evo-quote-character > br", NULL);
-               if (br_element) {
+               if (tmp_element) {
                        WebKitDOMNode *tmp;
 
                        if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node)) {
@@ -2247,7 +2296,7 @@ body_keyup_event_cb (WebKitDOMElement *element,
                                 */
                                /* <span class="-x-evo-quote-character"> */
                                node = webkit_dom_node_get_parent_node (
-                                       WEBKIT_DOM_NODE (br_element));
+                                       WEBKIT_DOM_NODE (tmp_element));
                                /* <span class="-x-evo-quoted"> */
                                node = webkit_dom_node_get_parent_node (node);
                                /* right block */
@@ -2269,9 +2318,9 @@ body_keyup_event_cb (WebKitDOMElement *element,
 
                        if (!WEBKIT_DOM_IS_HTMLBR_ELEMENT (webkit_dom_node_get_last_child (node)))
                                webkit_dom_node_append_child (
-                                       node, WEBKIT_DOM_NODE (br_element), NULL);
+                                       node, WEBKIT_DOM_NODE (tmp_element), NULL);
                        else
-                               remove_node (WEBKIT_DOM_NODE (br_element));
+                               remove_node (WEBKIT_DOM_NODE (tmp_element));
 
                        remove_node (parent);
                }
@@ -2859,6 +2908,99 @@ change_quoted_block_to_normal (EHTMLEditorView *view)
 }
 
 static gboolean
+fix_structure_after_delete_before_quoted_content (EHTMLEditorView *view)
+{
+       EHTMLEditorSelection *selection;
+       gboolean collapsed = FALSE;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker;
+       WebKitDOMNode *block, *next_sibling, *node;
+
+       selection = e_html_editor_view_get_selection (view);
+
+       collapsed = e_html_editor_selection_is_collapsed (selection);
+
+       e_html_editor_selection_save (selection);
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+       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) {
+               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_HTMLBR_ELEMENT (node))
+                       goto restore;
+               else {
+                       /* Remove the empty block and move caret into the beginning of the citation */
+                       remove_node (block);
+
+                       e_html_editor_selection_move_caret_into_element (
+                               document, WEBKIT_DOM_ELEMENT (next_sibling), TRUE);
+
+                       return TRUE;
+               }
+       } else {
+               gint level_start, level_end;
+
+               printf ("%s\n", webkit_dom_html_element_get_outer_html (WEBKIT_DOM_HTML_ELEMENT 
(webkit_dom_document_get_body (document))));
+               /* Delete was pressed in block without any content */
+               if (webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
+                       goto restore;
+
+               /* Situation where the end of the selection is in the
+                * middle of quoted content and the start in the beginning of
+                * the non quoted content before the citation. WebKit will take
+                * the block out from citation and insert the block before the citation.
+                * We have to make a clone of the block to restore it correctly later.
+                *
+                * |xxx
+                * > x|xx
+                * */
+               level_start = get_citation_level (WEBKIT_DOM_NODE (selection_start_marker), FALSE);
+               level_end = get_citation_level (WEBKIT_DOM_NODE (selection_end_marker), FALSE);
+
+               if (level_start == 0 && level_end > 0) {
+                       WebKitDOMNode *clone;
+
+                       block = get_parent_block_node_from_child (
+                               WEBKIT_DOM_NODE (selection_end_marker));
+
+                       clone = webkit_dom_node_clone_node (block, FALSE);
+                       webkit_dom_element_set_id (WEBKIT_DOM_ELEMENT (clone), "-x-evo-repair-block");
+
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_parent_node (block),
+                               clone,
+                               webkit_dom_node_get_next_sibling (block),
+                               NULL);
+               }
+       }
+ restore:
+       e_html_editor_selection_restore (selection);
+
+       return FALSE;
+}
+
+static gboolean
 html_editor_view_key_press_event (GtkWidget *widget,
                                   GdkEventKey *event)
 {
@@ -2950,6 +3092,10 @@ html_editor_view_key_press_event (GtkWidget *widget,
                        return TRUE;
        }
 
+       if (event->keyval == GDK_KEY_Delete || event->keyval == GDK_KEY_BackSpace)
+               if (fix_structure_after_delete_before_quoted_content (view))
+                       return TRUE;
+
        /* Chain up to parent's key_press_event() method. */
        return GTK_WIDGET_CLASS (e_html_editor_view_parent_class)->
                key_press_event (widget, event);
@@ -7091,7 +7237,7 @@ html_editor_view_load_status_changed (EHTMLEditorView *view)
        if (webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (body), "data-evo-draft")) {
                /* Restore the selection how it was when the draft was saved */
                e_html_editor_selection_move_caret_into_element (
-                       document, WEBKIT_DOM_ELEMENT (body));
+                       document, WEBKIT_DOM_ELEMENT (body), FALSE);
                e_html_editor_selection_restore (
                        e_html_editor_view_get_selection (view));
        }


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