[evolution/wip/webkit2] EHTMLEditorSelection - Correctly wrap text nodes around selection markers



commit ded25a94b2860d5621c54268e83327665ce34747
Author: Tomas Popela <tpopela redhat com>
Date:   Tue Mar 1 13:29:59 2016 +0100

    EHTMLEditorSelection - Correctly wrap text nodes around selection markers

 .../e-html-editor-selection-dom-functions.c        |  105 ++++++++++++++++++--
 1 files changed, 95 insertions(+), 10 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 a3133f7..fe41cf5 100644
--- a/web-extensions/composer/e-html-editor-selection-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-selection-dom-functions.c
@@ -2120,6 +2120,62 @@ mark_and_remove_leading_space (WebKitDOMDocument *document,
                WEBKIT_DOM_CHARACTER_DATA (node), 0, 1, "", NULL);
 }
 
+static void
+append_sibling_text_to_previous_node (WebKitDOMNode *node,
+                                      gboolean collapsed)
+{
+       WebKitDOMNode *next_text;
+
+       next_text = webkit_dom_node_get_next_sibling (node);
+       if (WEBKIT_DOM_IS_CHARACTER_DATA (next_text)) {
+               gchar *data;
+
+               data = webkit_dom_character_data_get_data (
+                       WEBKIT_DOM_CHARACTER_DATA (next_text));
+               /* If there is a space or dash we would split anyway at that point
+                * so skip it. */
+               if (data && !(*data == ' ' || *data == '-')) {
+                       WebKitDOMNode *prev_sibling;
+
+                       prev_sibling = webkit_dom_node_get_previous_sibling (node);
+                       if (collapsed)
+                               prev_sibling = webkit_dom_node_get_previous_sibling (prev_sibling);
+                       if (WEBKIT_DOM_IS_CHARACTER_DATA (prev_sibling)) {
+                               glong length;
+
+                               length = webkit_dom_character_data_get_length (
+                                       WEBKIT_DOM_CHARACTER_DATA (next_text));
+                               webkit_dom_character_data_append_data (
+                                       WEBKIT_DOM_CHARACTER_DATA (prev_sibling), data, NULL);
+                               g_object_set_data (
+                                       G_OBJECT (prev_sibling),
+                                       "-x-evo-char-count",
+                                       GINT_TO_POINTER (length));
+                       }
+               }
+               g_free (data);
+       }
+}
+
+static void
+temporary_remove_selection_point (WebKitDOMNode *selection_start_marker,
+                                  WebKitDOMNode *selection_end_marker)
+{
+       WebKitDOMNode *next_sibling;
+
+       next_sibling = webkit_dom_node_get_next_sibling (selection_start_marker);
+       if (next_sibling && webkit_dom_node_is_same_node (next_sibling, selection_end_marker)) {
+               append_sibling_text_to_previous_node (selection_end_marker, TRUE);
+       } else {
+               /* Selection is not collapsed, so we have to prepare
+                * the start point as well as end point. */
+               append_sibling_text_to_previous_node (selection_start_marker, FALSE);
+
+               if (selection_end_marker)
+                       append_sibling_text_to_previous_node (selection_end_marker, FALSE);
+       }
+}
+
 static WebKitDOMElement *
 wrap_lines (WebKitDOMDocument *document,
             EHTMLEditorWebExtension *extension,
@@ -2234,15 +2290,6 @@ wrap_lines (WebKitDOMDocument *document,
                        g_object_unref (list);
                }
 
-               webkit_dom_node_normalize (block_clone);
-               node = webkit_dom_node_get_first_child (block_clone);
-               if (node) {
-                       text_content = webkit_dom_node_get_text_content (node);
-                       if (g_strcmp0 ("\n", text_content) == 0)
-                               node = webkit_dom_node_get_next_sibling (node);
-                       g_free (text_content);
-               }
-
                /* We have to start from the end of the last wrapped line */
                selection_start_marker = webkit_dom_element_query_selector (
                        WEBKIT_DOM_ELEMENT (block_clone),
@@ -2281,6 +2328,15 @@ wrap_lines (WebKitDOMDocument *document,
                        }
                }
 
+               webkit_dom_node_normalize (block_clone);
+               node = webkit_dom_node_get_first_child (block_clone);
+               if (node) {
+                       text_content = webkit_dom_node_get_text_content (node);
+                       if (g_strcmp0 ("\n", text_content) == 0)
+                               node = webkit_dom_node_get_next_sibling (node);
+                       g_free (text_content);
+               }
+
                if (start_point) {
                        if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (start_point))
                                node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (start_point));
@@ -2289,6 +2345,19 @@ wrap_lines (WebKitDOMDocument *document,
                        start_node = block_clone;
                } else
                        start_node = node;
+
+               if (selection_start_marker || selection_end_marker) {
+                       /* The word could be split by selection markers and in this
+                        * case we would wrap it wrongly as the other part of the
+                        * word is in another text node after the marker.
+                        * As a solution temporary append the text of a node that
+                        * is after the caret to the node that is before the caret
+                        * and remove this appended text after we wrap the text
+                        * that is before the caret. */
+                       temporary_remove_selection_point (
+                               WEBKIT_DOM_NODE (selection_start_marker),
+                               WEBKIT_DOM_NODE (selection_end_marker));
+               }
        }
 
        line_length = 0;
@@ -2457,6 +2526,7 @@ wrap_lines (WebKitDOMDocument *document,
                /* wrap until we have something */
                while (node && (length_left + line_length) > length_to_wrap) {
                        gint max_length;
+                       gpointer object_data;
 
                        element = webkit_dom_document_create_element (document, "BR", NULL);
                        element_add_class (element, "-x-evo-wrap-br");
@@ -2478,7 +2548,22 @@ wrap_lines (WebKitDOMDocument *document,
                        /* Allow anchors to break on any character. */
                        if (g_object_steal_data (G_OBJECT (node), "-x-evo-anchor-text"))
                                offset = max_length;
-                       else {
+                       else if ((object_data  = g_object_steal_data (G_OBJECT (node), "-x-evo-char-count"))) 
{
+                               glong characters_count;
+
+                               offset = find_where_to_break_line (
+                                       WEBKIT_DOM_CHARACTER_DATA (node), max_length);
+
+                               /* Truncate the temporary text that was added to
+                                * the node previously and unmark the node. */
+                               characters_count = GPOINTER_TO_INT (object_data);
+                               webkit_dom_character_data_delete_data (
+                                       WEBKIT_DOM_CHARACTER_DATA (node),
+                                       webkit_dom_character_data_get_length (
+                                               WEBKIT_DOM_CHARACTER_DATA (node)) - characters_count,
+                                       characters_count,
+                                       NULL);
+                       } else {
                                /* Find where we can line-break the node so that it
                                 * effectively fills the rest of current row. */
                                offset = find_where_to_break_line (


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