[evolution/wip/webkit-composer: 258/372] Implement auto-wrapping of text for normal styled paragraphs.



commit 1b15d03d6396ba5dcc133d9fad2bd5a4a42a513f
Author: Tomas Popela <tpopela redhat com>
Date:   Wed May 29 14:38:19 2013 +0200

    Implement auto-wrapping of text for normal styled paragraphs.
    
    Implement auto-wrapping of text for normal styled paragraphs. Also new
    entry in Composer preferences was added to let user change the number of
    characters for wrapping.

 composer/e-composer-private.c                |  121 ++++--
 data/org.gnome.evolution.mail.gschema.xml.in |    5 +
 e-util/e-editor-actions.c                    |    2 +-
 e-util/e-editor-selection.c                  |  603 +++++++++++++++++++++++---
 e-util/e-editor-selection.h                  |    4 +-
 e-util/e-editor-widget.c                     |  158 ++++++-
 e-util/e-editor-widget.h                     |    2 +
 mail/mail-config.ui                          |   52 +++-
 modules/mail/em-composer-prefs.c             |    6 +
 9 files changed, 827 insertions(+), 126 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index d8018c9..014dc43 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -27,6 +27,8 @@
 /* Initial height of the picture gallery. */
 #define GALLERY_INITIAL_HEIGHT 150
 
+#define UNICODE_HIDDEN_SPACE "\xe2\x80\x8b"
+
 static void
 composer_setup_charset_menu (EMsgComposer *composer)
 {
@@ -604,6 +606,13 @@ e_composer_paste_text (EMsgComposer *composer,
        editor_selection = e_editor_widget_get_selection (editor_widget);
        e_editor_selection_insert_text (editor_selection, text);
 
+       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, TRUE, NULL);
+       }
+
        g_free (text);
 
        return TRUE;
@@ -775,8 +784,11 @@ composer_move_caret (EMsgComposer *composer)
        EEditorWidget *editor_widget;
        WebKitDOMDocument *document;
        WebKitDOMDOMWindow *window;
-       WebKitDOMElement *br_bottom;
        WebKitDOMDOMSelection *dom_selection;
+       WebKitDOMElement *input_start;
+       WebKitDOMNodeList *list;
+       WebKitDOMNodeList *blockquotes;
+       WebKitDOMElement *element;
        GSettings *settings;
        gboolean start_bottom;
 
@@ -794,33 +806,74 @@ composer_move_caret (EMsgComposer *composer)
        body = webkit_dom_document_get_body (document);
        new_range = webkit_dom_document_create_range (document);
 
-       if (start_bottom) {
-               WebKitDOMNodeList *blockquotes;
+       /* If we were just changing composer mode we don't want to insert
+        * new div and we want to set caret to the beginning */
+       element = webkit_dom_document_get_element_by_id (document, "-x-evo-changing-mode");
+       if (element) {
+               webkit_dom_node_remove_child (
+                       WEBKIT_DOM_NODE (body),
+                       WEBKIT_DOM_NODE (element),
+                       NULL);
 
-               blockquotes = webkit_dom_document_get_elements_by_tag_name (document, "blockquote");
-               if (webkit_dom_node_list_get_length (blockquotes) != 0) {
-                       /* Move caret between reply and signature. */
-                       new_range = webkit_dom_document_create_range (document);
+               if (webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))) {
                        webkit_dom_range_select_node_contents (new_range,
                                WEBKIT_DOM_NODE (
-                                       webkit_dom_node_get_next_sibling (webkit_dom_node_list_item 
(blockquotes, 0))
-                               ), NULL);
+                                       webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+                               NULL);
                        webkit_dom_range_collapse (new_range, TRUE, NULL);
 
-               } else {
-                       br_bottom = webkit_dom_document_get_element_by_id (document, "-x-evolution-br-reply");
+                       webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+                       webkit_dom_dom_selection_add_range (dom_selection, new_range);
+               }
+               return;
+       }
+
+       list = webkit_dom_document_get_elements_by_class_name (document, "-x-evo-paragraph");
+       blockquotes = webkit_dom_document_get_elements_by_tag_name (document, "blockquote");
 
-                       if (!br_bottom) {
-                               WebKitDOMElement *br;
+       if (webkit_dom_node_list_get_length (list) == 0) {
+               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);
+       }
 
-                               br = webkit_dom_document_create_element (document, "BR", NULL);
-                               webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (br), 
"-x-evolution-br-reply");
-                               webkit_dom_node_append_child (WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (br), 
NULL);
-                               br_bottom = webkit_dom_document_get_element_by_id (document, 
"-x-evolution-br-reply");
+       if (start_bottom) {
+               if (webkit_dom_node_list_get_length (blockquotes) != 0) {
+                       if (webkit_dom_node_list_get_length (list) == 0) {
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (body),
+                                       WEBKIT_DOM_NODE (element),
+                                       webkit_dom_node_get_next_sibling (
+                                               webkit_dom_node_list_item (blockquotes, 0)),
+                                       NULL);
                        }
+                       input_start = webkit_dom_document_get_element_by_id (document, "-x-evo-input-start");
 
-                       webkit_dom_range_select_node_contents (new_range, WEBKIT_DOM_NODE (br_bottom), NULL);
+                       /* Move caret between reply and signature. */
+                       if (input_start)
+                               webkit_dom_range_select_node_contents (new_range, WEBKIT_DOM_NODE 
(input_start), NULL);
                        webkit_dom_range_collapse (new_range, FALSE, NULL);
+               } else {
+                       if (webkit_dom_node_list_get_length (list) == 0) {
+                               if (webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)))
+                                       webkit_dom_node_insert_before (
+                                               WEBKIT_DOM_NODE (body),
+                                               WEBKIT_DOM_NODE (element),
+                                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
+                                               NULL);
+                               else
+                                       webkit_dom_node_append_child (
+                                               WEBKIT_DOM_NODE (body),
+                                               WEBKIT_DOM_NODE (element),
+                                               NULL);
+                       }
+
+                       webkit_dom_range_select_node_contents (new_range,
+                                       WEBKIT_DOM_NODE (
+                                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+                                       NULL);
+                       webkit_dom_range_collapse (new_range, TRUE, NULL);
                }
 
                g_signal_connect (
@@ -828,18 +881,29 @@ composer_move_caret (EMsgComposer *composer)
                        G_CALLBACK (composer_size_allocate_cb), NULL);
        } else {
                /* Move caret on the beginning of message */
-               if (!webkit_dom_document_get_element_by_id (document, "-x-evolution-br-reply")) {
-                       WebKitDOMElement *br;
-
-                       br = webkit_dom_document_create_element (document, "BR", NULL);
-                       webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (br), 
"-x-evolution-br-reply");
-                       webkit_dom_node_insert_before (WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (br), 
webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)), NULL);
+               if (webkit_dom_node_list_get_length (list) == 0) {
+                       webkit_dom_node_insert_before (
+                               WEBKIT_DOM_NODE (body),
+                               WEBKIT_DOM_NODE (element),
+                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
+                               NULL);
+
+                       if (webkit_dom_node_list_get_length (blockquotes) != 0) {
+                               WebKitDOMElement *br = webkit_dom_document_create_element (document, "BR", 
NULL);
+
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (body),
+                                       WEBKIT_DOM_NODE (br),
+                                       webkit_dom_node_get_next_sibling (
+                                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+                                       NULL);
+                       }
                }
 
                webkit_dom_range_select_node_contents (new_range,
                        WEBKIT_DOM_NODE (
-                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))
-                       ), NULL);
+                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+                       NULL);
                webkit_dom_range_collapse (new_range, TRUE, NULL);
        }
 
@@ -959,10 +1023,6 @@ insert:
        editor_widget = e_editor_get_editor_widget (editor);
        selection = e_editor_widget_get_selection (editor_widget);
 
-       /* This prevents our command before/after callbacks from
-        * screwing around with the signature as we insert it. */
-       composer->priv->in_signature_insert = TRUE;
-
        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);
@@ -1020,7 +1080,6 @@ insert:
        }
 
        composer_move_caret (composer);
-       composer->priv->in_signature_insert = FALSE;
 
 exit:
        g_object_unref (composer);
diff --git a/data/org.gnome.evolution.mail.gschema.xml.in b/data/org.gnome.evolution.mail.gschema.xml.in
index d97fff2..4d1331e 100644
--- a/data/org.gnome.evolution.mail.gschema.xml.in
+++ b/data/org.gnome.evolution.mail.gschema.xml.in
@@ -160,6 +160,11 @@
       <_summary>Enable developer mode</_summary>
       <_description>Enables some hidden actions and tools aimed for development and debugging.</_description>
     </key>
+    <key name="composer-word-wrap-length" type="i">
+      <default>71</default>
+      <_summary>Number of characters for wrapping</_summary>
+      <_description>Will autowrap lines after given number of characters.</_description>
+    </key>
     <key name="drag-and-drop-save-file-format" type="s">
       <default>'mbox'</default>
       <_summary>Save file format for drag-and-drop operation</_summary>
diff --git a/e-util/e-editor-actions.c b/e-util/e-editor-actions.c
index 3ff1023..df2c3d4 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);
+       e_editor_selection_wrap_lines (editor->priv->selection, FALSE, NULL);
 }
 
 static void
diff --git a/e-util/e-editor-selection.c b/e-util/e-editor-selection.c
index 811a1d6..f9ec0c8 100644
--- a/e-util/e-editor-selection.c
+++ b/e-util/e-editor-selection.c
@@ -39,8 +39,6 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_EDITOR_SELECTION, EEditorSelectionPrivate))
 
-#define WORD_WRAP_LENGTH 71
-
 #define UNICODE_HIDDEN_SPACE "\xe2\x80\x8b"
 
 /**
@@ -62,6 +60,8 @@ struct _EEditorSelectionPrivate {
        gchar *font_family;
 
        gulong selection_offset;
+
+       gint word_wrap_length;
 };
 
 enum {
@@ -792,7 +792,14 @@ e_editor_selection_class_init (EEditorSelectionClass *class)
 static void
 e_editor_selection_init (EEditorSelection *selection)
 {
+       GSettings *g_settings;
+
        selection->priv = E_EDITOR_SELECTION_GET_PRIVATE (selection);
+
+       g_settings = g_settings_new ("org.gnome.evolution.mail");
+       selection->priv->word_wrap_length = g_settings_get_int (g_settings, "composer-word-wrap-length");
+       g_object_unref (g_settings);
+
 }
 
 /**
@@ -2222,15 +2229,136 @@ e_editor_selection_insert_image (EEditorSelection *selection,
        g_object_unref (editor_widget);
 }
 
+static void
+clear_caret_position_marker (EEditorSelection *selection)
+{
+       EEditorWidget *widget;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *element;
+
+       g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+       widget = e_editor_selection_ref_editor_widget (selection);
+       g_return_if_fail (widget != NULL);
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+
+       element = webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position");
+
+       if (element) {
+               webkit_dom_node_remove_child (
+                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                       WEBKIT_DOM_NODE (element),
+                       NULL);
+       }
+
+       g_object_unref (widget);
+}
+
+static void
+save_caret_position (EEditorSelection *selection)
+{
+       EEditorWidget *widget;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *element;
+       WebKitDOMNode *split_node;
+       WebKitDOMNode *start_offset_node;
+       WebKitDOMRange *range;
+       gulong start_offset;
+
+       g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+       widget = e_editor_selection_ref_editor_widget (selection);
+       g_return_if_fail (widget != NULL);
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+       clear_caret_position_marker (selection);
+
+       range = editor_selection_get_current_range (selection);
+
+       start_offset = webkit_dom_range_get_start_offset (range, NULL);
+       start_offset_node = webkit_dom_range_get_end_container (range, NULL);
+
+       element = webkit_dom_document_create_element (document, "SPAN", NULL);
+       webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-caret-position");
+       webkit_dom_html_element_set_inner_html (WEBKIT_DOM_HTML_ELEMENT (element), "*", NULL);
+
+       if (WEBKIT_DOM_IS_TEXT (start_offset_node)) {
+               WebKitDOMText *split_text;
+
+               split_text = webkit_dom_text_split_text (
+                               WEBKIT_DOM_TEXT (start_offset_node),
+                               start_offset, NULL);
+               split_node = WEBKIT_DOM_NODE (split_text);
+       } else {
+               split_node = start_offset_node;
+       }
+
+       webkit_dom_node_insert_before (
+               webkit_dom_node_get_parent_node (start_offset_node),
+               WEBKIT_DOM_NODE (element),
+               split_node,
+               NULL);
+
+       g_object_unref (widget);
+}
+
+static void
+restore_caret_position (EEditorSelection *selection)
+{
+       EEditorWidget *widget;
+       WebKitDOMDocument *document;
+       WebKitDOMDOMWindow *window;
+       WebKitDOMDOMSelection *window_selection;
+       WebKitDOMElement *element;
+
+       g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+       widget = e_editor_selection_ref_editor_widget (selection);
+       g_return_if_fail (widget != NULL);
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+       window = webkit_dom_document_get_default_view (document);
+       window_selection = webkit_dom_dom_window_get_selection (window);
+       element = webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position");
+
+       if (element) {
+               WebKitDOMRange *new_range;
+
+               window = webkit_dom_document_get_default_view (document);
+               window_selection = webkit_dom_dom_window_get_selection (window);
+               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);
+               webkit_dom_dom_selection_remove_all_ranges (window_selection);
+               webkit_dom_dom_selection_add_range (window_selection, new_range);
+
+               webkit_dom_node_remove_child (
+                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                       WEBKIT_DOM_NODE (element),
+                       NULL);
+       }
+
+       g_object_unref (widget);
+}
+
 static gint
 find_where_to_break_line (WebKitDOMNode *node,
-                          gint max_len)
+                          gint max_len,
+                         gint word_wrap_length)
 {
        gchar *str, *text_start;
        gunichar uc;
-       gint pos, last_space;
+       gint pos;
+       gint last_space = 0;
+       gint length;
+       gint ret_val = 0;
+       gchar* position;
 
-       text_start = webkit_dom_text_get_whole_text ((WebKitDOMText *) node);
+       text_start =  webkit_dom_character_data_get_data (WEBKIT_DOM_CHARACTER_DATA (node));
+       length = g_utf8_strlen (text_start, -1);
 
        pos = 0;
        last_space = 0;
@@ -2247,9 +2375,21 @@ find_where_to_break_line (WebKitDOMNode *node,
                }
 
                /* If last_space is zero then the word is longer than
-                * WORD_WRAP_LENGTH characters, so continue untill we find
+                * word_wrap_length characters, so continue untill we find
                 * a space */
                if ((pos > max_len) && (last_space > 0)) {
+                       if (last_space > word_wrap_length) {
+                               g_free (text_start);
+                               return last_space;
+                       }
+                       if (last_space > max_len) {
+                               if (g_unichar_isspace (g_utf8_get_char (text_start)))
+                                       ret_val = 1;
+
+                               g_free (text_start);
+
+                               return ret_val;
+                       }
                        g_free (text_start);
                        return last_space;
                }
@@ -2262,57 +2402,124 @@ find_where_to_break_line (WebKitDOMNode *node,
                str = g_utf8_next_char (str);
        } while (*str);
 
+       position = g_utf8_offset_to_pointer (text_start, max_len);
+
+       if (g_unichar_isspace (g_utf8_get_char (position))) {
+               ret_val = max_len + 1;
+       } else {
+               if (last_space < max_len) {
+                       ret_val = last_space;
+               } else {
+                       if (length > word_wrap_length)
+                               ret_val = last_space;
+                       else
+                               ret_val = 0;
+               }
+       }
+
        g_free (text_start);
-       return max_len;
+
+       return ret_val;
 }
 
-/**
- * e_editor_selection_wrap_lines:
- * @selection: an #EEditorSelection
- *
- * Wraps all lines in current selection to be 71 characters long.
- */
-void
-e_editor_selection_wrap_lines (EEditorSelection *selection)
+static void
+wrap_lines (EEditorSelection *selection,
+           WebKitWebView *web_view,
+           gboolean jump_to_previous_line,
+           gboolean remove_all_br,
+           gint word_wrap_length)
 {
-       EEditorWidget *editor_widget;
-       WebKitWebView *web_view;
-       WebKitDOMRange *range;
+       WebKitDOMDocumentFragment *fragment;
        WebKitDOMNode *node, *start_node;
        WebKitDOMDocument *document;
        WebKitDOMElement *element;
-       WebKitDOMDocumentFragment *fragment;
-       gint len;
+       WebKitDOMNodeList *wrap_br;
+       gint len, ii, br_count;
        gchar *html;
+       gulong length_left;
 
-       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);
-
-       web_view = WEBKIT_WEB_VIEW (editor_widget);
+       document = webkit_web_view_get_dom_document (web_view);
 
-       /* When there is nothing selected, we select the whole document */
-       if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
-               EEditorWidgetCommand command;
-               command = E_EDITOR_WIDGET_COMMAND_SELECT_ALL;
-               e_editor_widget_exec_command (editor_widget, command, NULL);
+       fragment = webkit_dom_range_clone_contents (
+                       editor_selection_get_current_range (selection),
+                       NULL);
+
+       /* Select all BR elements or just ours that are used for wrapping.
+        * We are not removing user BR elements when this function is activated
+        * from Format->Wrap Lines action */
+       wrap_br = webkit_dom_document_fragment_query_selector_all (
+                       fragment,
+                       (remove_all_br) ? "br" : "br.-x-evo-wrap-br",
+                       NULL);
+
+       /* And remove them */
+       br_count = webkit_dom_node_list_get_length (wrap_br);
+       for (ii = br_count; ii > 0; ii--) {
+               WebKitDOMNode *br = webkit_dom_node_list_item (wrap_br, ii);
+               webkit_dom_node_remove_child (
+                               webkit_dom_node_get_parent_node (br), br, NULL);
        }
 
-       document = webkit_web_view_get_dom_document (web_view);
-       range = editor_selection_get_current_range (selection);
-
-       /* Copy the selection from DOM, wrap the lines and then paste it back
-        * using the DOM command which will overwrite the selection, and
-        * record it as an undoable action */
-       fragment = webkit_dom_range_clone_contents (range, NULL);
        node = WEBKIT_DOM_NODE (fragment);
 
        start_node = node;
        len = 0;
        while (node) {
-               /* Find nearest text node */
-               if (webkit_dom_node_get_node_type (node) != 3) {
+               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 (WEBKIT_DOM_IS_HTML_ELEMENT (next_sibling) &&
+                                       (g_strcmp0 (webkit_dom_html_element_get_id (WEBKIT_DOM_HTML_ELEMENT 
(next_sibling)),
+                                                   "-x-evo-caret-position")) == 0) {
+
+                                       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);
+                               }
+                       }
+
+                       /* If there is temporary hidden space we remove it */
+                       if (strstr (webkit_dom_node_get_text_content (node), UNICODE_HIDDEN_SPACE))
+                               webkit_dom_character_data_delete_data (
+                                       WEBKIT_DOM_CHARACTER_DATA (node), 0, 1, NULL);
+               } else {
+                       /* If element is ANCHOR we wrap it separately */
+                       if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
+                               glong anchor_length;
+
+                               anchor_length = g_utf8_strlen (webkit_dom_node_get_text_content (node), -1);
+                               if (len + anchor_length > word_wrap_length) {
+                                       element = webkit_dom_document_create_element (
+                                                       document, "BR", NULL);
+                                       webkit_dom_element_set_class_name (element, "-x-evo-wrap-br");
+                                       webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (node),
+                                                       WEBKIT_DOM_NODE (element),
+                                                       node,
+                                                       NULL);
+                                       len = anchor_length;
+                               } else
+                                       len += anchor_length;
+
+                               node = webkit_dom_node_get_next_sibling (node);
+                               continue;
+                       }
+                       /* When we are not removing user-entered BR elements (lines wrapped by user),
+                        * we need to skip those elements */
+                       if (!remove_all_br && g_strcmp0 (webkit_dom_node_get_local_name (node), "br") == 0) {
+                               if (!g_strcmp0 (webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT 
(node)), "-x-evo-wrap-br") == 0) {
+                                       len = 0;
+                                       node = webkit_dom_node_get_next_sibling (node);
+                                       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)) {
@@ -2331,47 +2538,76 @@ e_editor_selection_wrap_lines (EEditorSelection *selection)
                }
 
                /* If length of this node + what we already have is still less
-                * then 71 characters, then just join it and continue to next
+                * then word_wrap_length characters, then just join it and continue to next
                 * node */
-               if ((webkit_dom_character_data_get_length (
-                       (WebKitDOMCharacterData *) node) + len) < WORD_WRAP_LENGTH) {
-
-                       len += webkit_dom_character_data_get_length (
-                               (WebKitDOMCharacterData *) node);
+               length_left = webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (node));
 
+               if ((length_left + len) < word_wrap_length) {
+                       len += length_left;
                } else {
-                       gint offset;
-
-                       /* Find where we can line-break the node so that it
-                        * effectively fills the rest of current row */
-                       offset = find_where_to_break_line (node, WORD_WRAP_LENGTH - len);
-
-                       if (offset > 0) {
-                               /* Split the node and append <BR> tag to it */
-                               webkit_dom_text_split_text (
-                                       (WebKitDOMText *) node, len + offset, NULL);
-
-                               element = webkit_dom_document_create_element (
-                                       document, "BR", NULL);
-
-                               /* WebKit throws warning when ref_child is NULL */
-                               if (webkit_dom_node_get_next_sibling (node)) {
-                                       webkit_dom_node_insert_before (
-                                               webkit_dom_node_get_parent_node (node),
-                                               WEBKIT_DOM_NODE (element),
-                                               webkit_dom_node_get_next_sibling (node),
-                                               NULL);
+                       gint offset = 0;
+
+                       /* wrap until we have something */
+                       while ((length_left + len) > word_wrap_length) {
+                               /* Find where we can line-break the node so that it
+                                * effectively fills the rest of current row */
+                               offset = find_where_to_break_line (node, word_wrap_length - len, 
word_wrap_length);
+
+                               element = webkit_dom_document_create_element (document, "BR", NULL);
+                               webkit_dom_element_set_class_name (element, "-x-evo-wrap-br");
+
+                               if (offset > 0 && offset <= word_wrap_length) {
+                                       if (offset != length_left) {
+                                               webkit_dom_text_split_text (
+                                                               WEBKIT_DOM_TEXT (node), offset, NULL);
+                                       }
+                                       if (webkit_dom_node_get_next_sibling (node)) {
+                                               WebKitDOMNode *nd = webkit_dom_node_get_next_sibling (node);
+                                               nd = webkit_dom_node_get_next_sibling (node);
+                                               webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (node),
+                                                       WEBKIT_DOM_NODE (element),
+                                                       nd,
+                                                       NULL);
+                                       } else {
+                                               webkit_dom_node_append_child (
+                                                       webkit_dom_node_get_parent_node (node),
+                                                       WEBKIT_DOM_NODE (element),
+                                                       NULL);
+                                       }
+                               } else if (offset > word_wrap_length) {
+                                       if (offset != length_left) {
+                                               webkit_dom_text_split_text (
+                                                               WEBKIT_DOM_TEXT (node), offset + 1, NULL);
+                                       }
+                                       if (webkit_dom_node_get_next_sibling (node)) {
+                                               WebKitDOMNode *nd = webkit_dom_node_get_next_sibling (node);
+                                               nd = webkit_dom_node_get_next_sibling (node);
+                                               webkit_dom_node_insert_before (
+                                                       webkit_dom_node_get_parent_node (node),
+                                                       WEBKIT_DOM_NODE (element),
+                                                       nd,
+                                                       NULL);
+                                       } else {
+                                               webkit_dom_node_append_child (
+                                                       webkit_dom_node_get_parent_node (node),
+                                                       WEBKIT_DOM_NODE (element),
+                                                       NULL);
+                                       }
+                                       len = 0;
+                                       break;
                                } else {
-                                       webkit_dom_node_append_child (
+                                       webkit_dom_node_insert_before (
                                                webkit_dom_node_get_parent_node (node),
                                                WEBKIT_DOM_NODE (element),
+                                               node,
                                                NULL);
                                }
-
+                               length_left = webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA 
(node));
                                len = 0;
                        }
+                       len += length_left - offset;
                }
-
                /* Skip to next node */
                if (webkit_dom_node_get_next_sibling (node)) {
                        node = webkit_dom_node_get_next_sibling (node);
@@ -2390,17 +2626,240 @@ e_editor_selection_wrap_lines (EEditorSelection *selection)
        /* Create a wrapper DIV and put the processed content into it */
        element = webkit_dom_document_create_element (document, "DIV", NULL);
        webkit_dom_node_append_child (
-               WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (start_node), NULL);
+               WEBKIT_DOM_NODE (element),
+               WEBKIT_DOM_NODE (start_node),
+               NULL);
 
        /* Get HTML code of the processed content */
        html = webkit_dom_html_element_get_inner_html (
-               WEBKIT_DOM_HTML_ELEMENT (element));
+                       WEBKIT_DOM_HTML_ELEMENT (element));
 
        /* Overwrite the current selection be the processed content, so that
         * "UNDO" and "REDO" buttons work as expected */
        e_editor_selection_insert_html (selection, html);
 
        g_free (html);
+}
+
+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 (sibling && WEBKIT_DOM_IS_ELEMENT (sibling)) {
+                       if (g_strcmp0 (webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (sibling)), 
"-x-evo-wrap-br") == 0) {
+                               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)
+{
+       EEditorWidget *editor_widget;
+       WebKitWebView *web_view;
+       WebKitDOMRange *range;
+       WebKitDOMDocument *document;
+       WebKitDOMDOMWindow *window;
+       WebKitDOMDOMSelection *window_selection;
+       gboolean adding = FALSE;
+       gboolean return_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 (return_pressed || (event->keyval == GDK_KEY_space))
+                       adding = TRUE;
+       }
+
+       web_view = WEBKIT_WEB_VIEW (editor_widget);
+       document = webkit_web_view_get_dom_document (web_view);
+       window = webkit_dom_document_get_default_view (document);
+
+       if (while_typing) {
+               WebKitDOMNode *end_container;
+               WebKitDOMNode *parent;
+               gulong start_offset;
+
+               /* We need to save caret position and restore it after
+                * wrapping the selection, but we need to save it before we
+                * start to modify selection */
+               range = editor_selection_get_current_range (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);
+
+               /* Wrap only text surrounded in DIV and P tags */
+               parent = webkit_dom_node_get_parent_node(end_container);
+               if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (parent) || WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT (parent)) 
{
+                       webkit_dom_element_set_class_name (WEBKIT_DOM_ELEMENT (parent), "-x-evo-paragraph");
+               } else {
+                       /* If Return is pressed we need to select element above caret */
+                       if (return_pressed) {
+                               WebKitDOMNode *position = WEBKIT_DOM_NODE 
(webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position"));
+                               end_container = webkit_dom_node_get_previous_sibling (position);
+                       }
+                       else {
+                               /* When some weird element is selected, return */
+                               clear_caret_position_marker (selection);
+                               return;
+                       }
+               }
+
+               if (previously_wrapped) {
+                       /* Modifying previously wrapped line */
+
+                       /* 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;
+
+                       webkit_dom_dom_selection_select_all_children (
+                               window_selection,
+                               webkit_dom_node_get_parent_node (end_container),
+                               NULL);
+
+                       webkit_dom_range_select_node_contents (
+                               range,
+                               webkit_dom_node_get_parent_node (end_container),
+                               NULL);
+               } else {
+                       if (adding && return_pressed) {
+                               /* If return is pressed end_container is already set
+                                * to parent (DIV or P) */
+                               webkit_dom_dom_selection_select_all_children (
+                                       window_selection,
+                                       end_container,
+                                       NULL);
+                       } else {
+                               webkit_dom_dom_selection_select_all_children (
+                                       window_selection,
+                                       webkit_dom_node_get_parent_node (end_container),
+                                       NULL);
+                       }
+
+                       /* 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) {
+                                       webkit_dom_dom_selection_collapse_to_end (window_selection, NULL);
+                                       clear_caret_position_marker (selection);
+                                       webkit_dom_dom_selection_modify (window_selection, "move", "forward", 
"character");
+                               } else {
+                                       restore_caret_position (selection);
+                               }
+                               return;
+                       }
+
+                       if (return_pressed)
+                               /* If return is pressed end_container is already set
+                                * to parent (DIV or P) */
+                               webkit_dom_range_select_node_contents (
+                                       range,
+                                       end_container,
+                                       NULL);
+                       else
+                               webkit_dom_range_select_node_contents (
+                                       range,
+                                       webkit_dom_node_get_parent_node (end_container),
+                                       NULL);
+
+                       if (!adding && start_offset > selection->priv->word_wrap_length)
+                               jump_to_previous_line = TRUE;
+               }
+
+               wrap_lines (selection, web_view, jump_to_previous_line,
+                           FALSE, selection->priv->word_wrap_length);
+       } else {
+               /* When there is nothing selected, we select and wrap everything
+                * that is not containing signature */
+               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);
+
+                       if (signature) {
+                               list = webkit_dom_document_query_selector_all (document, "div, pre, p", NULL);
+
+                               for (ii = 0; ii < webkit_dom_node_list_get_length (list); ii++) {
+                                       WebKitDOMNode *node;
+                                       node = webkit_dom_node_list_item (list, ii);
+
+                                       /* Select elements that actualy have some text content */
+                                       if (g_utf8_strlen (webkit_dom_node_get_text_content (node), -1) == 0)
+                                               continue;
+
+                                       if (!webkit_dom_node_contains (node, signature)
+                                               && !webkit_dom_node_contains (signature, node)) {
+                                               webkit_dom_dom_selection_select_all_children (
+                                                       window_selection,
+                                                       node,
+                                                       NULL);
+                                               wrap_lines (selection, web_view, jump_to_previous_line,
+                                                           FALSE, selection->priv->word_wrap_length);
+                                       }
+                               }
+                       } else {
+                               /* Select all */
+                               EEditorWidgetCommand command;
+                               command = E_EDITOR_WIDGET_COMMAND_SELECT_ALL;
+                               e_editor_widget_exec_command (editor_widget, command, NULL);
+                               wrap_lines (selection, web_view, jump_to_previous_line,
+                                           FALSE, selection->priv->word_wrap_length);
+                       }
+               }
+       }
+
+       /* We have to move caret on position where it was before modifying the text */
+       if (return_pressed) {
+               clear_caret_position_marker (selection);
+               /* If Return is pressed we need to move the caret again below the text */
+               webkit_dom_dom_selection_modify (window_selection, "move", "forward", "character");
+       } else
+               restore_caret_position (selection);
 
        g_object_unref (editor_widget);
 }
diff --git a/e-util/e-editor-selection.h b/e-util/e-editor-selection.h
index ff4ab30..ae4834a 100644
--- a/e-util/e-editor-selection.h
+++ b/e-util/e-editor-selection.h
@@ -154,7 +154,9 @@ void                e_editor_selection_insert_image (EEditorSelection *selection,
                                                 const gchar *image_uri);
 void           e_editor_selection_insert_text  (EEditorSelection *selection,
                                                 const gchar *plain_text);
-void           e_editor_selection_wrap_lines   (EEditorSelection *selection);
+void           e_editor_selection_wrap_lines   (EEditorSelection *selection,
+                                                gboolean while_typing,
+                                                GdkEventKey *event);
 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 c637fc9..069ad43 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -35,6 +35,16 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_EDITOR_WIDGET, EEditorWidgetPrivate))
 
+#define UNICODE_HIDDEN_SPACE "\xe2\x80\x8b"
+
+#define URL_PATTERN \
+       "((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?" \
+       "[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)" \
+       "[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\?" \
+       "?(?:[\\-\\+=&;% \\ \\w]*)#?(?:[\\.\\!\\/\\\\w]*))?)"
+
+#define URL_PATTERN_SPACE URL_PATTERN "\\s"
+
 /**
  * EEditorWidget:
  *
@@ -304,7 +314,8 @@ static const gchar *emoticons_icon_names[] = {
 
 static void
 editor_widget_check_magic_links (EEditorWidget *widget,
-                                WebKitDOMRange *range)
+                                WebKitDOMRange *range,
+                                gboolean include_space)
 {
        gchar *node_text;
        gchar **urls;
@@ -313,11 +324,6 @@ editor_widget_check_magic_links (EEditorWidget *widget,
        gint start_pos_url, end_pos_url;
        WebKitDOMNode *node;
 
-       const gchar *url_pattern = "((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?"
-                                  "[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)"
-                                  "[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\?"
-                                  "?(?:[\\-\\+=&;% \\ \\w]*)#?(?:[\\.\\!\\/\\\\w]*))?)\\s";
-
        node = webkit_dom_range_get_end_container (range, NULL);
 
        if (!WEBKIT_DOM_IS_TEXT (node))
@@ -327,7 +333,7 @@ editor_widget_check_magic_links (EEditorWidget *widget,
        if (!node_text || !g_utf8_validate (node_text, -1, NULL))
                return;
 
-       regex = g_regex_new (url_pattern, 0, 0, NULL);
+       regex = g_regex_new (include_space ? URL_PATTERN_SPACE : URL_PATTERN, 0, 0, NULL);
 
        if (!regex) {
                g_free (node_text);
@@ -355,7 +361,7 @@ editor_widget_check_magic_links (EEditorWidget *widget,
                url_start = url_end - url_length;
 
                /* Remove space on end */
-               url = g_utf8_substring (urls[0], 0, url_length - 1);
+               url = g_utf8_substring (urls[0], 0, include_space ? url_length - 1 : url_length);
 
                /* Select the link and put it inside <A> */
                document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
@@ -364,7 +370,7 @@ editor_widget_check_magic_links (EEditorWidget *widget,
 
                webkit_dom_dom_selection_set_base_and_extent (
                        selection, webkit_dom_range_get_end_container (range, NULL),
-                       url_end - 1, webkit_dom_range_get_end_container (range, NULL),
+                       include_space ? url_end - 1 : url_end, webkit_dom_range_get_end_container (range, 
NULL),
                        url_start, NULL);
 
                if (g_str_has_prefix (url, "www"))
@@ -900,7 +906,16 @@ editor_widget_key_release_event (GtkWidget *widget,
                editor_widget_check_magic_smileys (editor_widget, range);
        }
 
-       editor_widget_check_magic_links (editor_widget, range);
+       if (event->keyval == GDK_KEY_space) {
+               editor_widget_check_magic_links (editor_widget, range, TRUE);
+       }
+
+       if ((event->keyval == GDK_KEY_Return) ||
+           (event->keyval == GDK_KEY_Linefeed) ||
+           (event->keyval == GDK_KEY_KP_Enter)) {
+
+               editor_widget_check_magic_links (editor_widget, range, FALSE);
+       }
 
        if ((event->keyval == GDK_KEY_Control_L) ||
            (event->keyval == GDK_KEY_Control_R)) {
@@ -908,6 +923,18 @@ 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);
@@ -1429,6 +1456,8 @@ void
 e_editor_widget_set_html_mode (EEditorWidget *widget,
                                gboolean html_mode)
 {
+       gboolean changing = FALSE;
+
        g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
 
        /* If toggling from HTML to plain text mode, ask user first */
@@ -1459,11 +1488,16 @@ e_editor_widget_set_html_mode (EEditorWidget *widget,
                        /* Nothing has changed, but notify anyway */
                        g_object_notify (G_OBJECT (widget), "html-mode");
                        return;
+               } else {
+                       changing = TRUE;
                }
 
                gtk_widget_destroy (dialog);
        }
 
+       if (html_mode)
+               changing = TRUE;
+
        if (html_mode == widget->priv->html_mode)
                return;
 
@@ -1488,6 +1522,13 @@ e_editor_widget_set_html_mode (EEditorWidget *widget,
                        CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED,
                        0);
 
+               if (changing) {
+                       gchar *tmp;
+                       tmp = g_strconcat (html, "<span id=\"-x-evo-changing-mode\"></span>", NULL);
+                       g_free (html);
+                       html = tmp;
+               }
+
                e_editor_widget_set_text_html (widget, html);
 
                g_free (plain_text);
@@ -1497,8 +1538,16 @@ e_editor_widget_set_html_mode (EEditorWidget *widget,
 
                plain = e_editor_widget_get_text_plain (widget);
 
-               if (*plain)
+               if (*plain) {
+                       if (changing) {
+                               gchar *tmp;
+                               tmp = g_strconcat (plain, UNICODE_HIDDEN_SPACE, NULL);
+                               g_free (plain);
+                               plain = tmp;
+                       }
+
                        e_editor_widget_set_text_plain (widget, plain);
+               }
 
                g_free (plain);
        }
@@ -1666,7 +1715,7 @@ process_elements (WebKitDOMNode *node,
        WebKitDOMCSSStyleDeclaration *style;
        gchar *display, *tagname;
        gulong ii, length;
-       GRegex *regex;
+       GRegex *regex, *regex_hidden_space;
 
        document = webkit_dom_node_get_owner_document (node);
        window = webkit_dom_document_get_default_view (document);
@@ -1702,9 +1751,14 @@ process_elements (WebKitDOMNode *node,
                }
        }
 
+       /* Skip signature */
+       if (g_strcmp0 (webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (node)), 
"-x-evolution-signature") == 0)
+               return;
+
        nodes = webkit_dom_node_get_child_nodes (node);
        length = webkit_dom_node_list_get_length (nodes);
        regex = g_regex_new ("\x9", 0, 0, NULL);
+       regex_hidden_space = g_regex_new (UNICODE_HIDDEN_SPACE, 0, 0, NULL);
 
        for (ii = 0; ii < length; ii++) {
                WebKitDOMNode *child;
@@ -1718,12 +1772,19 @@ process_elements (WebKitDOMNode *node,
                        /* Replace tabs with 4 whitespaces, otherwise they got
                         * replaced by single whitespace */
                        content = g_regex_replace (
-                               regex, tmp, -1, 0, "    ",
-                               0, NULL);
+                                       regex, tmp, -1, 0, "    ",
+                                       0, NULL);
+
+                       content = g_regex_replace (
+                                       regex_hidden_space, content, -1, 0, "", 0, NULL);
 
                        g_string_append (buffer, content);
                        g_free (tmp);
                        g_free (content);
+               } else {
+                       if (g_strcmp0 (webkit_dom_node_get_local_name (child), "br") == 0) {
+                               g_string_append (buffer, "\n");
+                       }
                }
 
                if (webkit_dom_node_has_child_nodes (child)) {
@@ -1731,12 +1792,9 @@ process_elements (WebKitDOMNode *node,
                }
        }
 
-       if (g_strcmp0 (display, "block") == 0 && g_strcmp0 (tagname, "BODY") != 0) {
-               g_string_append (buffer, "\n");
-       }
-
        g_free (display);
        g_regex_unref (regex);
+       g_regex_unref (regex_hidden_space);
 }
 
 /**
@@ -1757,7 +1815,7 @@ e_editor_widget_get_text_plain (EEditorWidget *widget)
        GString *plain_text;
 
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
-       body = (WebKitDOMNode *) webkit_dom_document_get_body (document);
+       body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
 
        plain_text = g_string_sized_new (1024);
        process_elements (body, plain_text);
@@ -1787,8 +1845,39 @@ static void
 do_set_text_plain (EEditorWidget *widget,
                    gpointer data)
 {
+       gboolean changing = FALSE;
+       const gchar *ptr;
+       gchar *data_copy = NULL;
+
+       if (strstr (data, UNICODE_HIDDEN_SPACE)) {
+               g_utf8_strncpy (data_copy, data, g_utf8_strlen (data, -1) - 1);
+               ptr = data_copy;
+               changing = TRUE;
+       } else {
+               ptr = data;
+       }
+
        e_editor_widget_exec_command (
-               widget, E_EDITOR_WIDGET_COMMAND_INSERT_TEXT, data);
+               widget, E_EDITOR_WIDGET_COMMAND_INSERT_TEXT, ptr);
+
+       if (changing) {
+               WebKitDOMDocument *document;
+               WebKitDOMNode *body;
+               WebKitDOMElement *element;
+
+               document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+               body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
+
+               element = webkit_dom_document_create_element (document, "SPAN", NULL);
+               webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-changing-mode");
+
+               webkit_dom_node_append_child (
+                       body,
+                       WEBKIT_DOM_NODE (element),
+                       NULL);
+
+               g_free (data_copy);
+       }
 }
 
 /**
@@ -2044,6 +2133,14 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
        pango_font_description_free (vw);
 }
 
+/**
+ * e_editor_widget_get_element_under_mouse_click:
+ * @widget: an #EEditorWidget
+ *
+ * Returns DOM element, that was clicked on.
+ *
+ * Returns: DOM element on that was clicked.
+ */
 WebKitDOMElement *
 e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget)
 {
@@ -2051,3 +2148,24 @@ e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget)
 
        return widget->priv->element_under_mouse;
 }
+
+/**
+ * e_editor_widget_check_magic_links
+ * @widget: an #EEditorWidget
+ * @include_space: If TRUE the pattern for link expects space on end
+ *
+ * Check if actual selection in given editor is link. If so, it is surrounded
+ * with ANCHOR element.
+ */
+void
+e_editor_widget_check_magic_links (EEditorWidget *widget,
+                                  gboolean include_space)
+{
+       WebKitDOMRange *range;
+
+       g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
+
+       range = editor_widget_get_dom_range (widget);
+       editor_widget_check_magic_links (widget, range, include_space);
+}
+
diff --git a/e-util/e-editor-widget.h b/e-util/e-editor-widget.h
index e2831ad..42c598b 100644
--- a/e-util/e-editor-widget.h
+++ b/e-util/e-editor-widget.h
@@ -110,6 +110,8 @@ void                e_editor_widget_update_fonts    (EEditorWidget *widget);
 
 WebKitDOMElement *
                e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget);
+void           e_editor_widget_check_magic_links (EEditorWidget *widget,
+                                                  gboolean while_typing);
 G_END_DECLS
 
 #endif /* E_EDITOR_WIDGET_H */
diff --git a/mail/mail-config.ui b/mail/mail-config.ui
index c26edfd..dfb285e 100644
--- a/mail/mail-config.ui
+++ b/mail/mail-config.ui
@@ -173,6 +173,13 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkAdjustment" id="adjustment7">
+    <property name="upper">200</property>
+    <property name="lower">31</property>
+    <property name="value">71</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">1</property>
+  </object>
   <object class="GtkNotebook" id="composer_toplevel">
     <property name="visible">True</property>
     <property name="can_focus">True</property>
@@ -278,6 +285,49 @@
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkHBox" id="hboxWrapCharactersCount">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="lblWordWrapLength">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Number of characters for word 
w_rapping:</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSpinButton" id="spinWordWrapLength">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="max_length">3</property>
+                            <property name="adjustment">adjustment7</property>
+                            <property name="caps_lock_warning">False</property>
+                            <property name="numeric">True</property>
+                            <property name="update_policy">if-valid</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkHBox" id="hboxComposerCharset">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
@@ -304,7 +354,7 @@
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">False</property>
-                        <property name="position">4</property>
+                        <property name="position">5</property>
                       </packing>
                     </child>
                   </object>
diff --git a/modules/mail/em-composer-prefs.c b/modules/mail/em-composer-prefs.c
index ec4c376..43790c9 100644
--- a/modules/mail/em-composer-prefs.c
+++ b/modules/mail/em-composer-prefs.c
@@ -1081,6 +1081,12 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
                widget, "active",
                G_SETTINGS_BIND_DEFAULT);
 
+       widget = e_builder_get_widget (prefs->builder, "spinWordWrapLength");
+       g_settings_bind (
+               settings, "composer-word-wrap-length",
+               widget, "value",
+               G_SETTINGS_BIND_DEFAULT);
+
        widget = e_builder_get_widget (prefs->builder, "chkOutlookFilenames");
        g_settings_bind (
                settings, "composer-outlook-filenames",



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