[evolution/wip/webkit-composer: 762/966] Implement word wrapping with CSS



commit c400b0a4ea7a8f7380090d7183c8a0d9ac917710
Author: Tomas Popela <tpopela redhat com>
Date:   Fri Oct 11 14:29:10 2013 +0200

    Implement word wrapping with CSS
    
    Limit width of paragraphs with "ch" length
    (https://developer.mozilla.org/en-US/docs/Web/CSS/length#Font-relative_lengths)
    and enable word-wrapping in CSS with word-wrap: normal;.

 composer/e-composer-private.c |   45 +++-
 e-util/e-editor-actions.c     |    2 +-
 e-util/e-editor-selection.c   |  475 +++++++++++++++++++----------------------
 e-util/e-editor-selection.h   |   10 +-
 e-util/e-editor-widget.c      |  103 ++++-----
 5 files changed, 308 insertions(+), 327 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index b0bf262..24b2343 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -591,11 +591,6 @@ e_composer_paste_text (EMsgComposer *composer,
 
        e_editor_widget_check_magic_links (editor_widget, FALSE);
 
-       if (e_editor_selection_get_block_format (editor_selection) ==
-                       E_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH) {
-               e_editor_selection_wrap_lines (editor_selection, FALSE, NULL);
-       }
-
        g_free (text);
 
        return TRUE;
@@ -794,6 +789,7 @@ composer_move_caret (EMsgComposer *composer)
        WebKitDOMRange *new_range;
        EEditor *editor;
        EEditorWidget *editor_widget;
+       EEditorSelection *editor_selection;
        WebKitDOMDocument *document;
        WebKitDOMDOMWindow *window;
        WebKitDOMDOMSelection *dom_selection;
@@ -813,6 +809,8 @@ composer_move_caret (EMsgComposer *composer)
 
        editor = e_msg_composer_get_editor (composer);
        editor_widget = e_editor_get_editor_widget (editor);
+       editor_selection = e_editor_widget_get_selection (editor_widget);
+
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
        window = webkit_dom_document_get_default_view (document);
        dom_selection = webkit_dom_dom_window_get_selection (window);
@@ -843,10 +841,23 @@ composer_move_caret (EMsgComposer *composer)
        blockquotes = webkit_dom_document_get_elements_by_tag_name (document, "blockquote");
 
        if (!has_paragraphs_in_body) {
+               gchar *style_value;
+               gint word_wrap_length;
+
                element = webkit_dom_document_create_element (document, "DIV", NULL);
-               webkit_dom_element_set_class_name (WEBKIT_DOM_ELEMENT (element), "-x-evo-paragraph");
-               webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-input-start");
-               webkit_dom_html_element_set_inner_html (WEBKIT_DOM_HTML_ELEMENT (element), 
UNICODE_HIDDEN_SPACE, NULL);
+               webkit_dom_element_set_class_name (
+                       WEBKIT_DOM_ELEMENT (element), "-x-evo-paragraph");
+               webkit_dom_html_element_set_id (
+                       WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-input-start");
+
+               word_wrap_length = e_editor_selection_get_word_wrap_length (editor_selection);
+
+               style_value = g_strdup_printf ("width: %dch; word-wrap: normal;", word_wrap_length);
+               webkit_dom_element_set_attribute (
+                       element, "style", style_value, NULL);
+               webkit_dom_html_element_set_inner_html (
+                       WEBKIT_DOM_HTML_ELEMENT (element), UNICODE_HIDDEN_SPACE, NULL);
+               g_free (style_value);
        }
 
        if (start_bottom) {
@@ -868,6 +879,10 @@ composer_move_caret (EMsgComposer *composer)
                                webkit_dom_range_select_node_contents (new_range, WEBKIT_DOM_NODE 
(input_start), NULL);
 
                        webkit_dom_range_collapse (new_range, FALSE, NULL);
+
+                       e_editor_selection_restore_caret_position (editor_selection);
+                       e_editor_widget_quote_plain_text (editor_widget);
+                       e_editor_widget_force_spellcheck (editor_widget);
                } else {
                        if (!has_paragraphs_in_body) {
                                if (webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))) {
@@ -913,8 +928,20 @@ composer_move_caret (EMsgComposer *composer)
                        if (webkit_dom_node_list_get_length (blockquotes) != 0) {
                                WebKitDOMElement *br = webkit_dom_document_create_element (document, "BR", 
NULL);
 
-                               if (!e_editor_widget_get_html_mode (editor_widget))
+                               if (!e_editor_widget_get_html_mode (editor_widget)) {
+                                       WebKitDOMNode *blockquote;
+
+                                       blockquote = webkit_dom_node_list_item (blockquotes, 0);
+
+                                       /* FIXME determine when we can skip this */
+                                       e_editor_selection_wrap_paragraph (
+                                               editor_selection,
+                                               WEBKIT_DOM_ELEMENT (blockquote));
+
+                                       e_editor_selection_restore_caret_position (editor_selection);
                                        e_editor_widget_quote_plain_text (editor_widget);
+                                       e_editor_widget_force_spellcheck (editor_widget);
+                               }
 
                                webkit_dom_node_insert_before (
                                        WEBKIT_DOM_NODE (body),
diff --git a/e-util/e-editor-actions.c b/e-util/e-editor-actions.c
index df2c3d4..3ff1023 100644
--- a/e-util/e-editor-actions.c
+++ b/e-util/e-editor-actions.c
@@ -881,7 +881,7 @@ static void
 action_wrap_lines_cb (GtkAction *action,
                       EEditor *editor)
 {
-       e_editor_selection_wrap_lines (editor->priv->selection, FALSE, NULL);
+       e_editor_selection_wrap_lines (editor->priv->selection);
 }
 
 static void
diff --git a/e-util/e-editor-selection.c b/e-util/e-editor-selection.c
index 35e11a9..03148a9 100644
--- a/e-util/e-editor-selection.c
+++ b/e-util/e-editor-selection.c
@@ -817,6 +817,14 @@ e_editor_selection_init (EEditorSelection *selection)
        g_object_unref (g_settings);
 }
 
+gint
+e_editor_selection_get_word_wrap_length (EEditorSelection *selection)
+{
+       g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), 72);
+
+       return selection->priv->word_wrap_length;
+}
+
 /**
  * e_editor_selection_ref_editor_widget:
  * @selection: an #EEditorSelection
@@ -1498,10 +1506,28 @@ e_editor_selection_set_block_format (EEditorSelection *selection,
 
                paragraph = e_editor_dom_node_find_parent_element (node, "P");
 
-               if (paragraph)
+               if (paragraph) {
+                       gchar *style_value;
+                       gint spaces_per_indentation = 4;
+                       gint word_wrap_length = selection->priv->word_wrap_length;
+                       gint level;
+
                        element_add_class (WEBKIT_DOM_ELEMENT (paragraph), "-x-evo-paragraph");
+                       level = get_indentation_level (WEBKIT_DOM_ELEMENT (paragraph));
+                       style_value =
+                               g_strdup_printf (
+                                       "word-wrap: normal; "
+                                       "width: %dch",
+                                       word_wrap_length - spaces_per_indentation * level);
+
+                       webkit_dom_element_set_attribute (
+                               paragraph,
+                               "style",
+                               style_value,
+                               NULL);
 
-               e_editor_selection_wrap_lines (selection, FALSE, NULL);
+                       g_free (style_value);
+               }
        }
 
        g_object_unref (editor_widget);
@@ -1807,6 +1833,10 @@ e_editor_selection_indent (EEditorSelection *selection)
                WebKitDOMNode *node;
                WebKitDOMNode *clone;
                WebKitDOMElement *element;
+               gchar *style_value;
+               gint spaces_per_indentation = 4;
+               gint word_wrap_length = selection->priv->word_wrap_length;
+               gint level;
 
                document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
 
@@ -1822,17 +1852,34 @@ e_editor_selection_indent (EEditorSelection *selection)
                if (!WEBKIT_DOM_IS_ELEMENT (node))
                        node = WEBKIT_DOM_NODE (webkit_dom_node_get_parent_element (node));
 
+               level = get_indentation_level (WEBKIT_DOM_ELEMENT (node));
+
                element = webkit_dom_node_get_parent_element (node);
 
                clone = webkit_dom_node_clone_node (node, TRUE);
+
+               /* Remove style and let the paragraph inherit it from parent */
+               if (element_has_class (WEBKIT_DOM_ELEMENT (clone), "-x-evo-paragraph"))
+                       webkit_dom_element_remove_attribute (WEBKIT_DOM_ELEMENT (clone), "style");
+
                element = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
                element_add_class (element, "-x-evo-indented");
                /* We don't want vertical space bellow and above blockquote inserted by
                 * WebKit's User Agent Stylesheet. We have to override it through style attribute. */
+               style_value =
+                       g_strdup_printf (
+                               "-webkit-margin-start: %dch; "
+                               "-webkit-margin-end : %dch; "
+                               "word-wrap: normal; "
+                               "width: %dch",
+                               spaces_per_indentation,
+                               spaces_per_indentation,
+                               word_wrap_length - spaces_per_indentation * level);
+
                webkit_dom_element_set_attribute (
                        element,
                        "style",
-                       "-webkit-margin-before: 0em; -webkit-margin-after: 0em;",
+                       style_value,
                        NULL);
 
                webkit_dom_node_append_child (
@@ -1846,6 +1893,7 @@ e_editor_selection_indent (EEditorSelection *selection)
                        node,
                        NULL);
 
+               g_free (style_value);
                e_editor_selection_restore_caret_position (selection);
        } else {
                command = E_EDITOR_WIDGET_COMMAND_INDENT;
@@ -1892,6 +1940,9 @@ e_editor_selection_unindent (EEditorSelection *selection)
                WebKitDOMRange *range;
                gboolean before_node = TRUE;
                gboolean reinsert_caret_position = FALSE;
+               gint word_wrap_length = selection->priv->word_wrap_length;
+               gint spaces_per_indentation = 4;
+               gint level;
 
                document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
 
@@ -1913,34 +1964,57 @@ e_editor_selection_unindent (EEditorSelection *selection)
                        return;
                }
 
+               level = get_indentation_level (element);
                clone = WEBKIT_DOM_NODE (webkit_dom_node_clone_node (WEBKIT_DOM_NODE (element), TRUE));
 
                /* Look if we have previous siblings, if so, we have to
                 * create new blockquote that will include them */
                if (webkit_dom_node_get_previous_sibling (node)) {
+                       gchar *style_value;
                        prev_blockquote = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
                        /* We don't want vertical space bellow and above blockquote inserted by
                         * WebKit's User Agent Stylesheet. We have to override it through style attribute. */
                        element_add_class (prev_blockquote, "-x-evo-indented");
+                       style_value =
+                               g_strdup_printf (
+                                       "-webkit-margin-start: %dch; "
+                                       "-webkit-margin-end : %dch; "
+                                       "word-wrap: normal; "
+                                       "width: %dch",
+                                       spaces_per_indentation,
+                                       spaces_per_indentation,
+                                       word_wrap_length - spaces_per_indentation * level);
                        webkit_dom_element_set_attribute (
                                prev_blockquote,
                                "style",
-                               "-webkit-margin-before: 0em; -webkit-margin-after: 0em;",
+                               style_value,
                                NULL);
+                       g_free (style_value);
                }
 
                /* Look if we have next siblings, if so, we have to
                 * create new blockquote that will include them */
                if (webkit_dom_node_get_next_sibling (node)) {
-                       next_blockquote = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
+                       gchar *style_value;
+                       prev_blockquote = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
                        /* We don't want vertical space bellow and above blockquote inserted by
                         * WebKit's User Agent Stylesheet. We have to override it through style attribute. */
-                       element_add_class (next_blockquote, "-x-evo-indented");
+                       element_add_class (prev_blockquote, "-x-evo-indented");
+                       style_value =
+                               g_strdup_printf (
+                                       "-webkit-margin-start: %dch; "
+                                       "-webkit-margin-end : %dch; "
+                                       "word-wrap: normal; "
+                                       "width: %dch",
+                                       spaces_per_indentation,
+                                       spaces_per_indentation,
+                                       word_wrap_length - spaces_per_indentation * level);
                        webkit_dom_element_set_attribute (
-                               next_blockquote,
+                               prev_blockquote,
                                "style",
-                               "-webkit-margin-before: 0em; -webkit-margin-after: 0em;",
+                               style_value,
                                NULL);
+                       g_free (style_value);
                }
 
                /* Copy nodes that are before / after the element that we want to unindent */
@@ -1993,6 +2067,21 @@ e_editor_selection_unindent (EEditorSelection *selection)
                                NULL);
                }
 
+               if (level == 1 &&
+                   element_has_class (WEBKIT_DOM_ELEMENT (node_clone), "-x-evo-paragraph")) {
+                       gchar *style_value;
+
+                       style_value = g_strdup_printf ("word-wrap: normal; width: %dch",
+                                                       word_wrap_length);
+
+                       webkit_dom_element_set_attribute (
+                               WEBKIT_DOM_ELEMENT (node_clone),
+                               "style",
+                               style_value,
+                               NULL);
+                       g_free (style_value);
+               }
+
                /* Insert the unindented element */
                webkit_dom_node_insert_before (
                        webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
@@ -3130,7 +3219,7 @@ find_where_to_break_line (WebKitDOMNode *node,
        text_start =  webkit_dom_character_data_get_data (WEBKIT_DOM_CHARACTER_DATA (node));
        length = g_utf8_strlen (text_start, -1);
 
-       pos = 0;
+       pos = 1;
        last_space = 0;
        str = text_start;
        do {
@@ -3196,10 +3285,8 @@ static void
 wrap_lines (EEditorSelection *selection,
            WebKitDOMNode *paragraph,
            WebKitDOMDocument *document,
-           gboolean jump_to_previous_line,
            gboolean remove_all_br,
-           gint word_wrap_length,
-           gboolean delete_pressed)
+           gint word_wrap_length)
 {
        WebKitDOMNode *node, *start_node;
        WebKitDOMNode *paragraph_clone;
@@ -3226,9 +3313,17 @@ wrap_lines (EEditorSelection *selection,
                                remove_all_br ? "br" : "br.-x-evo-wrap-br",
                                NULL);
        } else {
+               WebKitDOMElement *caret_node;
+
                paragraph_clone = webkit_dom_node_clone_node (paragraph, TRUE);
+               caret_node =
+                       webkit_dom_element_query_selector (
+                               WEBKIT_DOM_ELEMENT (paragraph_clone),
+                               "span#-x-evo-caret-position", NULL);
                text_content = webkit_dom_node_get_text_content (paragraph_clone);
                paragraph_char_count = g_utf8_strlen (text_content, -1);
+               if (caret_node)
+                       paragraph_char_count--;
                g_free (text_content);
 
                wrap_br = webkit_dom_element_query_selector_all (
@@ -3247,32 +3342,65 @@ wrap_lines (EEditorSelection *selection,
 
        if (selection)
                node = WEBKIT_DOM_NODE (fragment);
-       else
+       else {
+               webkit_dom_node_normalize (paragraph_clone);
                node = webkit_dom_node_get_first_child (paragraph_clone);
+               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);
+       }
 
        start_node = node;
        len = 0;
        while (node) {
                if (WEBKIT_DOM_IS_TEXT (node)) {
-                       if (jump_to_previous_line) {
-                               /* If we need to jump to the previous line (e.g. Backspace pressed
-                                * on the beginning of line, we need to remove last character on
-                                * the line that is above that line */
-                               WebKitDOMNode *next_sibling = webkit_dom_node_get_next_sibling (node);
-
-                               if (is_caret_position_node (next_sibling)) {
-                                       webkit_dom_character_data_delete_data (
-                                               WEBKIT_DOM_CHARACTER_DATA (node),
-                                               webkit_dom_character_data_get_length 
(WEBKIT_DOM_CHARACTER_DATA (node)) - 1,
-                                               1, NULL);
-                               }
-                       }
+                       const gchar *newline;
+                       WebKitDOMNode *next_sibling;
 
                        /* If there is temporary hidden space we remove it */
                        text_content = webkit_dom_node_get_text_content (node);
-                       if (g_strstr_len (text_content, -1, UNICODE_HIDDEN_SPACE))
+                       if (g_strstr_len (text_content, -1, UNICODE_HIDDEN_SPACE)) {
                                webkit_dom_character_data_delete_data (
                                        WEBKIT_DOM_CHARACTER_DATA (node), 0, 1, NULL);
+                               g_free (text_content);
+                               text_content = webkit_dom_node_get_text_content (node);
+                       }
+                       newline = g_strstr_len (text_content, -1, "\n");
+
+                       next_sibling = node;
+                       while (newline) {
+                               WebKitDOMElement *element;
+
+                               next_sibling = WEBKIT_DOM_NODE (webkit_dom_text_split_text (
+                                       WEBKIT_DOM_TEXT (next_sibling),
+                                       g_utf8_pointer_to_offset (text_content, newline),
+                                       NULL));
+
+                               if (!next_sibling)
+                                       break;
+
+                               element = webkit_dom_document_create_element (
+                                               document, "BR", NULL);
+                               element_add_class (element, "-x-evo-temp-wrap-text-br");
+
+                               webkit_dom_node_insert_before (
+                                       webkit_dom_node_get_parent_node (next_sibling),
+                                       WEBKIT_DOM_NODE (element),
+                                       next_sibling,
+                                       NULL);
+
+                               g_free (text_content);
+
+                               text_content = webkit_dom_node_get_text_content (next_sibling);
+                               if (g_str_has_prefix (text_content, "\n")) {
+                                       webkit_dom_character_data_delete_data (
+                                               WEBKIT_DOM_CHARACTER_DATA (next_sibling), 0, 1, NULL);
+                                       g_free (text_content);
+                                       text_content = webkit_dom_node_get_text_content (next_sibling);
+                               }
+                               newline = g_strstr_len (text_content, -1, "\n");
+                       }
                        g_free (text_content);
                } else {
                        /* If element is ANCHOR we wrap it separately */
@@ -3286,10 +3414,10 @@ wrap_lines (EEditorSelection *selection,
                                                        document, "BR", NULL);
                                        element_add_class (element, "-x-evo-wrap-br");
                                        webkit_dom_node_insert_before (
-                                                       webkit_dom_node_get_parent_node (node),
-                                                       WEBKIT_DOM_NODE (element),
-                                                       node,
-                                                       NULL);
+                                               webkit_dom_node_get_parent_node (node),
+                                               WEBKIT_DOM_NODE (element),
+                                               node,
+                                               NULL);
                                        len = anchor_length;
                                } else
                                        len += anchor_length;
@@ -3301,15 +3429,6 @@ wrap_lines (EEditorSelection *selection,
 
                        if (is_caret_position_node (node)) {
                                node = webkit_dom_node_get_next_sibling (node);
-
-                               /* If Delete key is pressed on the end of line, we need to manually
-                                * delete the first character of the line that is below us */
-                               if (delete_pressed && (paragraph_char_count / (br_count + 1)) > 
word_wrap_length) {
-                                       WebKitDOMNode *next_text = webkit_dom_node_get_next_sibling (node);
-                                       if (WEBKIT_DOM_IS_CHARACTER_DATA (next_text))
-                                               webkit_dom_character_data_delete_data (
-                                                       WEBKIT_DOM_CHARACTER_DATA (next_text), 0, 1, NULL);
-                               }
                                continue;
                        }
 
@@ -3322,21 +3441,7 @@ wrap_lines (EEditorSelection *selection,
                                        continue;
                                }
                        }
-
-                       /* Find nearest text node */
-                       if (webkit_dom_node_has_child_nodes (node)) {
-                               node = webkit_dom_node_get_first_child (node);
-                       } else if (webkit_dom_node_get_next_sibling (node)) {
-                               node = webkit_dom_node_get_next_sibling (node);
-                       } else {
-                               if (webkit_dom_node_is_equal_node (node, start_node))
-                                       break;
-
-                               node = webkit_dom_node_get_parent_node (node);
-                               if (node)
-                                       node = webkit_dom_node_get_next_sibling (node);
-                       }
-                       continue;
+                       goto next_node;
                }
 
                /* If length of this node + what we already have is still less
@@ -3361,7 +3466,7 @@ wrap_lines (EEditorSelection *selection,
                                if (offset > 0 && offset <= word_wrap_length) {
                                        if (offset != length_left) {
                                                webkit_dom_text_split_text (
-                                                               WEBKIT_DOM_TEXT (node), offset, NULL);
+                                                       WEBKIT_DOM_TEXT (node), offset, NULL);
                                        }
                                        if (webkit_dom_node_get_next_sibling (node)) {
                                                WebKitDOMNode *nd = webkit_dom_node_get_next_sibling (node);
@@ -3413,18 +3518,19 @@ wrap_lines (EEditorSelection *selection,
                        }
                        len += length_left - offset;
                }
-               /* Skip to next node */
-               if (webkit_dom_node_get_next_sibling (node)) {
+ next_node:
+               /* Move to next node */
+               if (webkit_dom_node_has_child_nodes (node)) {
+                       node = webkit_dom_node_get_first_child (node);
+               } else if (webkit_dom_node_get_next_sibling (node)) {
                        node = webkit_dom_node_get_next_sibling (node);
                } else {
-                       if (webkit_dom_node_is_equal_node (node, start_node)) {
+                       if (webkit_dom_node_is_equal_node (node, start_node))
                                break;
-                       }
 
                        node = webkit_dom_node_get_parent_node (node);
-                       if (node) {
+                       if (node)
                                node = webkit_dom_node_get_next_sibling (node);
-                       }
                }
        }
 
@@ -3433,12 +3539,13 @@ wrap_lines (EEditorSelection *selection,
 
                /* Create a wrapper DIV and put the processed content into it */
                element = webkit_dom_document_create_element (document, "DIV", NULL);
-               element_add_class (WEBKIT_DOM_ELEMENT (element), "-x-evo-paragraph");
+               element_add_class (element, "-x-evo-paragraph");
                webkit_dom_node_append_child (
                        WEBKIT_DOM_NODE (element),
                        WEBKIT_DOM_NODE (start_node),
                        NULL);
 
+               webkit_dom_node_normalize (WEBKIT_DOM_NODE (element));
                /* Get HTML code of the processed content */
                html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT (element));
 
@@ -3446,8 +3553,8 @@ wrap_lines (EEditorSelection *selection,
                e_editor_selection_insert_html (selection, html);
 
                g_free (html);
-
        } else {
+               webkit_dom_node_normalize (paragraph_clone);
                /* Replace paragraph with wrapped one */
                webkit_dom_node_replace_child (
                        webkit_dom_node_get_parent_node (paragraph),
@@ -3457,85 +3564,33 @@ wrap_lines (EEditorSelection *selection,
        }
 }
 
-static gboolean
-check_if_previously_wrapped (WebKitDOMDocument *document)
-{
-       WebKitDOMNode *sibling;
-
-       sibling = WEBKIT_DOM_NODE (
-                       webkit_dom_document_get_element_by_id (
-                               document, "-x-evo-caret-position"));
-
-       while (sibling) {
-               if (WEBKIT_DOM_IS_ELEMENT (sibling) &&
-                   element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-wrap-br"))
-                       return TRUE;
-
-               sibling = webkit_dom_node_get_next_sibling (sibling);
-       }
-
-       return FALSE;
-}
-
 /**
  * e_editor_selection_wrap_lines:
  * @selection: an #EEditorSelection
- * @while_typing: If true this function is capable to wrap while typing
- * @event: GdkEventKey of pressed key - can be NULL
  *
  * Wraps all lines in current selection to be 71 characters long.
  */
 void
-e_editor_selection_wrap_lines (EEditorSelection *selection,
-                              gboolean while_typing,
-                              GdkEventKey *event)
+e_editor_selection_wrap_lines (EEditorSelection *selection)
 {
        EEditorWidget *editor_widget;
        WebKitDOMRange *range;
        WebKitDOMDocument *document;
-       WebKitDOMDOMWindow *window;
-       WebKitDOMDOMSelection *window_selection;
        WebKitDOMElement *active_paragraph;
-       gboolean adding = FALSE;
-       gboolean backspace_pressed = FALSE;
-       gboolean return_pressed = FALSE;
-       gboolean return_pressed_in_text = FALSE;
-       gboolean delete_pressed = FALSE;
-       gboolean jump_to_previous_line = FALSE;
-       gboolean previously_wrapped = FALSE;
 
        g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
 
        editor_widget = e_editor_selection_ref_editor_widget (selection);
        g_return_if_fail (editor_widget != NULL);
 
-       if (event != NULL) {
-               if ((event->keyval == GDK_KEY_Return) ||
-                   (event->keyval == GDK_KEY_Linefeed) ||
-                   (event->keyval == GDK_KEY_KP_Enter)) {
-
-                       return_pressed = TRUE;
-               }
-
-               if (event->keyval == GDK_KEY_Delete)
-                       delete_pressed = TRUE;
-
-               if (return_pressed || (event->keyval == GDK_KEY_space))
-                       adding = TRUE;
-
-               if (event->keyval == GDK_KEY_BackSpace)
-                       backspace_pressed = TRUE;
-       }
-
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
        g_object_unref (editor_widget);
-       window = webkit_dom_document_get_default_view (document);
 
-       if (while_typing) {
+       e_editor_selection_save_caret_position (selection);
+       if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
                WebKitDOMNode *end_container;
                WebKitDOMNode *parent;
                WebKitDOMNode *paragraph;
-               gulong start_offset;
                gchar *text_content;
 
                /* We need to save caret position and restore it after
@@ -3545,20 +3600,7 @@ e_editor_selection_wrap_lines (EEditorSelection *selection,
                if (!range)
                        return;
 
-               e_editor_selection_save_caret_position (selection);
-
-               start_offset = webkit_dom_range_get_start_offset (range, NULL);
-               /* Extend the range to include entire nodes */
-               webkit_dom_range_select_node_contents (
-                               range,
-                               webkit_dom_range_get_common_ancestor_container (range, NULL),
-                               NULL);
-
-               window_selection = webkit_dom_dom_window_get_selection (window);
-
-               end_container = webkit_dom_range_get_end_container (range, NULL);
-
-               previously_wrapped = check_if_previously_wrapped (document);
+               end_container = webkit_dom_range_get_common_ancestor_container (range, NULL);
 
                /* Wrap only text surrounded in DIV and P tags */
                parent = webkit_dom_node_get_parent_node(end_container);
@@ -3571,7 +3613,12 @@ e_editor_selection_wrap_lines (EEditorSelection *selection,
                        if (element_has_class (parent_div, "-x-evo-paragraph")) {
                                paragraph = WEBKIT_DOM_NODE (parent_div);
                        } else {
-                               WebKitDOMNode *position = WEBKIT_DOM_NODE 
(webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position"));
+                               WebKitDOMNode *position;
+
+                               position = WEBKIT_DOM_NODE (
+                                               webkit_dom_document_get_element_by_id (
+                                                       document,
+                                                       "-x-evo-caret-position"));
                                if (!position)
                                        return;
 
@@ -3582,7 +3629,12 @@ e_editor_selection_wrap_lines (EEditorSelection *selection,
                                        if (WEBKIT_DOM_IS_TEXT (paragraph)) {
                                                WebKitDOMRange *new_range = webkit_dom_document_create_range 
(document);
                                                WebKitDOMNode *container = WEBKIT_DOM_NODE 
(webkit_dom_document_create_element (document, "DIV", NULL));
-                                               element_add_class (WEBKIT_DOM_ELEMENT (container), 
"-x-evo-paragraph");
+                                               element_add_class (
+                                                       WEBKIT_DOM_ELEMENT (container),
+                                                       "-x-evo-paragraph");
+                                               webkit_dom_element_set_attribute (
+                                                       WEBKIT_DOM_ELEMENT (container),
+                                                       "style", "width: 70ch; word-wrap: normal;", NULL);
                                                webkit_dom_range_select_node (new_range, paragraph, NULL);
                                                webkit_dom_range_surround_contents (new_range, container, 
NULL);
                                                /* We have to move caret position inside this container */
@@ -3600,6 +3652,7 @@ e_editor_selection_wrap_lines (EEditorSelection *selection,
                if (!paragraph)
                        return;
 
+               webkit_dom_element_remove_attribute (WEBKIT_DOM_ELEMENT (paragraph), "style");
                webkit_dom_html_element_set_id (
                        WEBKIT_DOM_HTML_ELEMENT (paragraph),
                        "-x-evo-active-paragraph");
@@ -3631,139 +3684,51 @@ e_editor_selection_wrap_lines (EEditorSelection *selection,
                }
                g_free (text_content);
 
-               if (previously_wrapped) {
-                       /* If we are on the beginning of line we need to remember it */
-                       if (!adding && start_offset > selection->priv->word_wrap_length)
-                               jump_to_previous_line = TRUE;
-
-                       if (return_pressed)
-                               return_pressed_in_text = TRUE;
-
-               } else {
-                       WebKitDOMElement *caret_position;
-                       gboolean parent_is_body = FALSE;
-
-                       caret_position =
-                               webkit_dom_document_get_element_by_id (
-                                       document, "-x-evo-caret-position");
-
-                       webkit_dom_dom_selection_select_all_children (
-                               window_selection,
-                               paragraph,
-                               NULL);
-
-                       if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE 
(caret_position))))
-                               parent_is_body = TRUE;
-
-                       if (backspace_pressed && parent_is_body) {
-                               WebKitDOMElement *prev_sibling;
-
-                               prev_sibling = webkit_dom_element_get_previous_element_sibling 
(caret_position);
-
-                               move_caret_into_element (document, prev_sibling);
-                               e_editor_selection_clear_caret_position_marker (selection);
-                               webkit_dom_dom_selection_modify (window_selection, "move", "forward", 
"character");
-                               webkit_dom_element_remove_attribute (WEBKIT_DOM_ELEMENT (paragraph), "id");
-
-                               return;
-                       }
-
-                       /* If there is less than word_wrap_length characters do nothing */
-                       if (g_utf8_strlen (e_editor_selection_get_string (selection), -1) < 
selection->priv->word_wrap_length) {
-                               if (return_pressed) {
-                                       WebKitDOMNode *next_sibling =
-                                               webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE 
(caret_position));
-
-                                       if (WEBKIT_DOM_IS_ELEMENT (next_sibling))
-                                               move_caret_into_element (document, WEBKIT_DOM_ELEMENT 
(next_sibling));
-                                       else
-                                               move_caret_into_element (document, caret_position);
-
-                                       e_editor_selection_clear_caret_position_marker (selection);
-                               } else {
-                                       e_editor_selection_restore_caret_position (selection);
-                               }
-
-                               webkit_dom_element_remove_attribute (WEBKIT_DOM_ELEMENT (paragraph), "id");
-
-                               return;
-                       }
-
-                       if (!adding && start_offset > selection->priv->word_wrap_length)
-                               jump_to_previous_line = TRUE;
-               }
-
-               webkit_dom_dom_selection_select_all_children (
-                       window_selection,
-                       paragraph,
-                       NULL);
-
-               wrap_lines (NULL, paragraph, document, jump_to_previous_line,
-                           FALSE, selection->priv->word_wrap_length, delete_pressed);
+               wrap_lines (NULL, paragraph, document, FALSE, selection->priv->word_wrap_length);
 
        } else {
-               /* When there is nothing selected, we select and wrap everything
-                * that is not containing signature */
                e_editor_selection_save_caret_position (selection);
-               if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
-                       WebKitDOMNodeList *list;
-                       WebKitDOMNode *signature = NULL;
-                       gint ii;
-
-                       window_selection = webkit_dom_dom_window_get_selection (window);
-
-                       /* Check if signature is presented in editor */
-                       list = webkit_dom_document_get_elements_by_class_name (document, 
"-x-evolution-signature");
-                       if (webkit_dom_node_list_get_length (list) > 0)
-                               signature = webkit_dom_node_list_item (list, 0);
-
-                       list = webkit_dom_document_query_selector_all (document, "div.-x-evo-paragraph, 
p.-x-evo-paragraph", NULL);
-                       for (ii = 0; ii < webkit_dom_node_list_get_length (list); ii++) {
-                               WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);
-                               gchar *text_content;
-
-                               /* Select elements that actualy have some text content */
-                               text_content = webkit_dom_node_get_text_content (node);
-                               if (g_utf8_strlen (text_content, -1) == 0) {
-                                       g_free (text_content);
-                                       continue;
-                               }
-                               g_free (text_content);
-
-                               if (signature) {
-                                       if (!webkit_dom_node_contains (node, signature) &&
-                                           !webkit_dom_node_contains (signature, node)) {
-
-                                               wrap_lines (NULL, node, document, jump_to_previous_line,
-                                                           FALSE, selection->priv->word_wrap_length, 
delete_pressed);
-                                       }
-                               } else {
-                                       wrap_lines (NULL, node, document, jump_to_previous_line,
-                                                   FALSE, selection->priv->word_wrap_length, delete_pressed);
-                               }
-                       }
-               } else {
-                       /* If we have selection -> wrap it */
-                       wrap_lines (selection, NULL, document, jump_to_previous_line,
-                                   FALSE, selection->priv->word_wrap_length, delete_pressed);
-               }
+               /* If we have selection -> wrap it */
+               wrap_lines (selection, NULL, document, FALSE, selection->priv->word_wrap_length);
        }
 
        active_paragraph = webkit_dom_document_get_element_by_id (document, "-x-evo-active-paragraph");
        /* We have to move caret on position where it was before modifying the text */
-       if (return_pressed && !return_pressed_in_text) {
-               e_editor_selection_clear_caret_position_marker (selection);
-               move_caret_into_element (document, active_paragraph);
-               webkit_dom_dom_selection_modify (window_selection, "move", "forward", "character");
-       } else {
-               e_editor_selection_restore_caret_position (selection);
-       }
+       e_editor_selection_restore_caret_position (selection);
 
        /* Set paragraph as non-active */
        if (active_paragraph)
                webkit_dom_element_remove_attribute (WEBKIT_DOM_ELEMENT (active_paragraph), "id");
 }
 
+void
+e_editor_selection_wrap_paragraph (EEditorSelection *selection,
+                                   WebKitDOMElement *paragraph)
+{
+       EEditorWidget *editor_widget;
+       WebKitDOMDocument *document;
+       gint level;
+       gint spaces_per_indentation = 4;
+       gint word_wrap_length;
+
+       g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+       g_return_if_fail (WEBKIT_DOM_IS_ELEMENT (paragraph));
+
+       editor_widget = e_editor_selection_ref_editor_widget (selection);
+       g_return_if_fail (editor_widget != NULL);
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
+       g_object_unref (editor_widget);
+
+       word_wrap_length = selection->priv->word_wrap_length;
+
+       level = get_indentation_level (paragraph);
+
+       wrap_lines (
+               NULL, WEBKIT_DOM_NODE (paragraph), document, FALSE,
+               word_wrap_length - spaces_per_indentation * level);
+}
+
 /**
  * e_editor_selection_save:
  * @selection: an #EEditorSelection
diff --git a/e-util/e-editor-selection.h b/e-util/e-editor-selection.h
index 4c97de4..0284a68 100644
--- a/e-util/e-editor-selection.h
+++ b/e-util/e-editor-selection.h
@@ -27,6 +27,7 @@
 
 #include <gtk/gtk.h>
 #include <e-util/e-util-enums.h>
+#include <webkit/webkit.h>
 
 /* Standard GObject macros */
 #define E_TYPE_EDITOR_SELECTION \
@@ -68,6 +69,8 @@ GType         e_editor_selection_get_type     (void) G_GNUC_CONST;
 struct _EEditorWidget *
                e_editor_selection_ref_editor_widget
                                                (EEditorSelection *selection);
+gint           e_editor_selection_get_word_wrap_length
+                                               (EEditorSelection *selection);
 gboolean       e_editor_selection_has_text     (EEditorSelection *selection);
 gchar *                e_editor_selection_get_caret_word
                                                (EEditorSelection *selection);
@@ -160,9 +163,10 @@ void               e_editor_selection_save_caret_position
                                                (EEditorSelection *selection);
 void           e_editor_selection_restore_caret_position
                                                (EEditorSelection *selection);
-void           e_editor_selection_wrap_lines   (EEditorSelection *selection,
-                                                gboolean while_typing,
-                                                GdkEventKey *event);
+void           e_editor_selection_wrap_lines   (EEditorSelection *selection);
+void           e_editor_selection_wrap_paragraph
+                                               (EEditorSelection *selection,
+                                                WebKitDOMElement *paragraph);
 void           e_editor_selection_save         (EEditorSelection *selection);
 void           e_editor_selection_restore      (EEditorSelection *selection);
 void           e_editor_selection_move         (EEditorSelection *selection,
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index ce20b1f..7069c79 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -1044,18 +1044,6 @@ editor_widget_button_release_event (GtkWidget *widget,
 }
 
 static gboolean
-is_something_to_remove (EEditorWidget *widget)
-{
-       WebKitDOMDocument *document;
-       WebKitDOMHTMLElement *body;
-
-       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
-       body = webkit_dom_document_get_body (document);
-
-       return (g_utf8_strlen (webkit_dom_node_get_text_content (WEBKIT_DOM_NODE (body)), -1) > 0);
-}
-
-static gboolean
 editor_widget_key_press_event (GtkWidget *widget,
                                GdkEventKey *event)
 {
@@ -1075,11 +1063,6 @@ editor_widget_key_press_event (GtkWidget *widget,
                editor_widget_set_links_active (editor, TRUE);
        }
 
-       if (event->keyval == GDK_KEY_BackSpace) {
-               if (!is_something_to_remove (editor))
-                       return FALSE;
-       }
-
        if ((event->keyval == GDK_KEY_Return) ||
            (event->keyval == GDK_KEY_KP_Enter)) {
 
@@ -1151,18 +1134,6 @@ editor_widget_key_release_event (GtkWidget *widget,
                editor_widget_set_links_active (editor_widget, FALSE);
        }
 
-       if ((event->keyval == GDK_KEY_space) ||
-           (event->keyval == GDK_KEY_Delete) ||
-           (event->keyval == GDK_KEY_Return) ||
-           (event->keyval == GDK_KEY_Linefeed) ||
-           (event->keyval == GDK_KEY_KP_Enter) ||
-           (event->keyval == GDK_KEY_BackSpace)) {
-
-               EEditorSelection *selection;
-               selection = e_editor_widget_get_selection (editor_widget);
-               if (e_editor_selection_get_block_format (selection) == 
E_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH)
-                       e_editor_selection_wrap_lines (selection, TRUE, event);
-       }
        /* Chain up to parent's key_release_event() method. */
        return GTK_WIDGET_CLASS (e_editor_widget_parent_class)->
                key_release_event (widget, event);
@@ -2116,6 +2087,24 @@ e_editor_widget_get_html_mode (EEditorWidget *widget)
        return widget->priv->html_mode;
 }
 
+static gint
+get_indentation_level (WebKitDOMElement *element)
+{
+       WebKitDOMElement *parent;
+       gint level = 1;
+
+       parent = webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (element));
+       /* Count level of indentation */
+       while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+               if (element_has_class (parent, "-x-evo-indented"))
+                       level++;
+
+               parent = webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (parent));
+       }
+
+       return level;
+}
+
 static void
 process_blockquote (WebKitDOMElement *blockquote)
 {
@@ -2167,24 +2156,10 @@ process_blockquote (WebKitDOMElement *blockquote)
        }
 
        if (element_has_class (blockquote, "-x-evo-indented")) {
-               WebKitDOMElement *parent;
                WebKitDOMNode *child;
-               gint level = 1;
                gchar *spaces;
 
-               webkit_dom_element_remove_attribute (blockquote, "style");
-               element_remove_class (blockquote, "-x-evo-indented");
-
-               parent = webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (blockquote));
-               /* Count level of indentation */
-               while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
-                       if (element_has_class (parent, "-x-evo-indented"))
-                               level++;
-
-                       parent = webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (parent));
-               }
-
-               spaces = g_strnfill (4 * level, ' ');
+               spaces = g_strnfill (4 * get_indentation_level (blockquote), ' ');
 
                child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (blockquote));
                while (child) {
@@ -2199,12 +2174,7 @@ process_blockquote (WebKitDOMElement *blockquote)
                                gchar *indented_text;
 
                                text_content = webkit_dom_text_get_whole_text (WEBKIT_DOM_TEXT (child));
-
-                               /* FIXME Fix properly in wrapping => do not include space on the beginning of 
the line */
-                               if (g_str_has_prefix (text_content, " "))
-                                       indented_text = g_strconcat (spaces + 1, text_content, NULL);
-                               else
-                                       indented_text = g_strconcat (spaces, text_content, NULL);
+                               indented_text = g_strconcat (spaces, text_content, NULL);
 
                                webkit_dom_text_replace_whole_text (
                                        WEBKIT_DOM_TEXT (child),
@@ -2215,13 +2185,16 @@ process_blockquote (WebKitDOMElement *blockquote)
                                g_free (indented_text);
                        }
 
+                       if (!child)
+                               break;
+
                        /* Move to next node */
                        if (webkit_dom_node_has_child_nodes (child))
                                child = webkit_dom_node_get_first_child (child);
                        else if (webkit_dom_node_get_next_sibling (child))
                                child = webkit_dom_node_get_next_sibling (child);
                        else {
-                               if (webkit_dom_node_is_equal_node (child, child))
+                               if (webkit_dom_node_is_equal_node (WEBKIT_DOM_NODE (blockquote), child))
                                        break;
 
                                child = webkit_dom_node_get_parent_node (child);
@@ -2230,6 +2203,8 @@ process_blockquote (WebKitDOMElement *blockquote)
                        }
                }
                g_free (spaces);
+
+               webkit_dom_element_remove_attribute (blockquote, "style");
        }
 }
 
@@ -2836,7 +2811,7 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
                e_color_to_value (visited));
 
        /* See bug #689777 for details */
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "p,pre,code,address {\n"
                "  margin: 0;\n"
@@ -2846,15 +2821,25 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
                "  margin-bottom: 0.2em;\n"
                "}\n");
 
-       g_string_append_printf (
+       g_string_append(
+               stylesheet,
+               "blockquote "
+               "{\n"
+               "  -webkit-margin-before: 0em; "
+               "  -webkit-margin-after: 0em; "
+               "}\n");
+
+       g_string_append (
                stylesheet,
                "blockquote[type=cite] "
                "{\n"
                "  padding: 0.0ex 0ex;\n"
                "  margin: 0ex;\n"
+               "  -webkit-margin-start: 0em; "
+               "  -webkit-margin-end : 0em; "
                "}\n");
 
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
                "{\n"
@@ -2867,14 +2852,14 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
 
        /* Block quote border colors are borrowed from Thunderbird. */
 
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
                "{\n"
                "  border-color: rgb(114,159,207);\n"  /* Sky Blue 1 */
                "}\n");
 
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
@@ -2882,7 +2867,7 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
                "  border-color: rgb(173,127,168);\n"  /* Plum 1 */
                "}\n");
 
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
@@ -2891,7 +2876,7 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
                "  border-color: rgb(138,226,52);\n"  /* Chameleon 1 */
                "}\n");
 
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
@@ -2901,7 +2886,7 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
                "  border-color: rgb(252,175,62);\n"  /* Orange 1 */
                "}\n");
 
-       g_string_append_printf (
+       g_string_append (
                stylesheet,
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "
                "blockquote[type=cite]:not(.-x-evo-plaintext-quoted) "



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