[evolution/wip/webkit2] EHTMLEditorView - Improve how the content is processed



commit 3133243f704a1e743bd6212eee9a1f38034c54b6
Author: Tomas Popela <tpopela redhat com>
Date:   Thu Jun 30 15:53:35 2016 +0200

    EHTMLEditorView - Improve how the content is processed
    
    Split the process_elements function to:
     * process_node_to_plain_text_for_exporting
     * process_node_to_plain_text_changing_composer_mode
     * process_node_to_html_changing_composer_mode
     * process_node_to_html_for_exporting
    
    that process the given nodes (usually just BODY) for purposes described by the
    function names - i.e. the first function will process the BODY and will transform
    the lists to their plain text version, fill the indentation or alignment with
    spaces and so on; the process_node_to_html_for_exporting will remove all the
    classes, ids and other attributes from the DOM.
    
    Also in the process_node_to_plain_text_for_exporting correctly process the block
    elements to avoid situations when an extra new line could be added on the end of
    the block or not added at all. Always look if the new line is indeed there, if
    not add it there explicitly. This fixes the bug 767681. Also avoid working with
    the innerHTML of the BODY (that was previously leaked), but instead copy the
    nodes. Also remove images from the BODY if they are presented to avoid unneeded
    line break.
    
    After this change the indented elements will be preserved when switching between
    composer modes.
    
    When removing an image also remove its wrappers and the block where the image
    was, if the block is empty after the image was removed, otherwise an extra line
    will be added to the output.

 .../web-extension/e-composer-dom-functions.c       |    4 +-
 .../web-extension/e-editor-dom-functions.c         | 1240 ++++++++++----------
 .../web-extension/e-editor-dom-functions.h         |    4 +-
 .../web-extension/e-editor-web-extension.c         |    4 +-
 web-extensions/e-dom-utils.c                       |   19 +
 web-extensions/e-dom-utils.h                       |   14 +-
 6 files changed, 639 insertions(+), 646 deletions(-)
---
diff --git a/modules/webkit-editor/web-extension/e-composer-dom-functions.c 
b/modules/webkit-editor/web-extension/e-composer-dom-functions.c
index 5b528d0..6751596 100644
--- a/modules/webkit-editor/web-extension/e-composer-dom-functions.c
+++ b/modules/webkit-editor/web-extension/e-composer-dom-functions.c
@@ -459,7 +459,9 @@ e_composer_dom_insert_signature (EEditorPage *editor_page,
                        WebKitDOMElement *pre_delimiter;
 
                        pre_delimiter = webkit_dom_document_create_element (document, "pre", NULL);
-                       webkit_dom_element_set_inner_html (pre_delimiter, delim, NULL);
+                       /* Always use the HTML delimiter as we are never in anything
+                        * like a strict plain text mode. */
+                       webkit_dom_element_set_inner_html (pre_delimiter, "-- <br>", NULL);
                        webkit_dom_node_append_child (
                                WEBKIT_DOM_NODE (insert_signature_in),
                                WEBKIT_DOM_NODE (pre_delimiter),
diff --git a/modules/webkit-editor/web-extension/e-editor-dom-functions.c 
b/modules/webkit-editor/web-extension/e-editor-dom-functions.c
index 9c4a8da..bd31d75 100644
--- a/modules/webkit-editor/web-extension/e-editor-dom-functions.c
+++ b/modules/webkit-editor/web-extension/e-editor-dom-functions.c
@@ -3672,27 +3672,11 @@ e_editor_dom_remove_node_and_parents_if_empty (WebKitDOMNode *node)
        remove_node (WEBKIT_DOM_NODE (node));
 
        while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
-               WebKitDOMNode *prev_sibling, *next_sibling;
-
-               prev_sibling = webkit_dom_node_get_previous_sibling (parent);
-               next_sibling = webkit_dom_node_get_next_sibling (parent);
-               /* Empty or BR as sibling, but no sibling after it. */
-               if ((!prev_sibling ||
-                    (WEBKIT_DOM_IS_HTML_BR_ELEMENT (prev_sibling) &&
-                     !webkit_dom_node_get_previous_sibling (prev_sibling))) &&
-                   (!next_sibling ||
-                    (WEBKIT_DOM_IS_HTML_BR_ELEMENT (next_sibling) &&
-                     !webkit_dom_node_get_next_sibling (next_sibling)))) {
-                       WebKitDOMNode *tmp;
+               WebKitDOMNode *tmp;
 
-                       tmp = webkit_dom_node_get_parent_node (parent);
-                       remove_node (parent);
-                       parent = tmp;
-               } else {
-                       if (!webkit_dom_node_get_first_child (parent))
-                               remove_node (parent);
-                       return;
-               }
+               tmp = webkit_dom_node_get_parent_node (parent);
+               remove_node_if_empty (parent);
+               parent = tmp;
        }
 }
 
@@ -4973,11 +4957,8 @@ create_and_append_new_block (EEditorPage *editor_page,
 
        g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), NULL);
 
-       if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (block_template))
-               block = e_editor_dom_get_paragraph_element (editor_page, -1, 0);
-       else
-               block = WEBKIT_DOM_ELEMENT (webkit_dom_node_clone_node_with_error (
-                       WEBKIT_DOM_NODE (block_template), FALSE, NULL));
+       block = WEBKIT_DOM_ELEMENT (webkit_dom_node_clone_node_with_error (
+               WEBKIT_DOM_NODE (block_template), FALSE, NULL));
 
        webkit_dom_element_set_inner_html (block, content, NULL);
 
@@ -6618,6 +6599,9 @@ get_indentation_level (WebKitDOMElement *element)
        WebKitDOMElement *parent;
        gint level = 0;
 
+       if (!element)
+               return 0;
+
        if (element_has_class (element, "-x-evo-indented"))
                level++;
 
@@ -6634,8 +6618,64 @@ get_indentation_level (WebKitDOMElement *element)
 }
 
 static void
-process_blockquote (WebKitDOMElement *blockquote,
-                    gboolean replace_indentation_with_spaces)
+process_indented_element (WebKitDOMElement *element)
+{
+       gchar *spaces;
+       WebKitDOMNode *child;
+
+       if (!element)
+               return;
+
+       spaces = g_strnfill (4 * get_indentation_level (element), ' ');
+
+       child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element));
+       while (child) {
+               /* If next sibling is indented blockqoute skip it,
+                * it will be processed afterwards */
+               if (WEBKIT_DOM_IS_ELEMENT (child) &&
+                   element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-indented"))
+                       child = webkit_dom_node_get_next_sibling (child);
+
+               if (WEBKIT_DOM_IS_TEXT (child)) {
+                       gchar *text_content;
+                       gchar *indented_text;
+
+                       text_content = webkit_dom_text_get_whole_text (WEBKIT_DOM_TEXT (child));
+                       indented_text = g_strconcat (spaces, text_content, NULL);
+
+                       webkit_dom_text_replace_whole_text (
+                               WEBKIT_DOM_TEXT (child),
+                               indented_text,
+                               NULL);
+
+                       g_free (text_content);
+                       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 (WEBKIT_DOM_NODE (element), child))
+                               break;
+
+                       child = webkit_dom_node_get_parent_node (child);
+                       if (child)
+                               child = webkit_dom_node_get_next_sibling (child);
+               }
+       }
+       g_free (spaces);
+
+       webkit_dom_element_remove_attribute (element, "style");
+}
+
+static void
+process_quote_nodes (WebKitDOMElement *blockquote)
 {
        WebKitDOMNodeList *list;
        int jj, length;
@@ -6657,58 +6697,6 @@ process_blockquote (WebKitDOMElement *blockquote,
                g_object_unref (quoted_node);
        }
        g_object_unref (list);
-
-       if (element_has_class (blockquote, "-x-evo-indented") && replace_indentation_with_spaces) {
-               WebKitDOMNode *child;
-               gchar *spaces;
-
-               spaces = g_strnfill (4 * get_indentation_level (blockquote), ' ');
-
-               child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (blockquote));
-               while (child) {
-                       /* If next sibling is indented blockqoute skip it,
-                        * it will be processed afterwards */
-                       if (WEBKIT_DOM_IS_ELEMENT (child) &&
-                           element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-indented"))
-                               child = webkit_dom_node_get_next_sibling (child);
-
-                       if (WEBKIT_DOM_IS_TEXT (child)) {
-                               gchar *text_content;
-                               gchar *indented_text;
-
-                               text_content = webkit_dom_text_get_whole_text (WEBKIT_DOM_TEXT (child));
-                               indented_text = g_strconcat (spaces, text_content, NULL);
-
-                               webkit_dom_text_replace_whole_text (
-                                       WEBKIT_DOM_TEXT (child),
-                                       indented_text,
-                                       NULL);
-
-                               g_free (text_content);
-                               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 (WEBKIT_DOM_NODE (blockquote), child))
-                                       break;
-
-                               child = webkit_dom_node_get_parent_node (child);
-                               if (child)
-                                       child = webkit_dom_node_get_next_sibling (child);
-                       }
-               }
-               g_free (spaces);
-
-               webkit_dom_element_remove_attribute (blockquote, "style");
-       }
 }
 
 /* Taken from GtkHTML */
@@ -7035,6 +7023,7 @@ remove_evolution_attributes (WebKitDOMElement *element)
        webkit_dom_element_remove_attribute (element, "data-new-message");
        webkit_dom_element_remove_attribute (element, "data-user-wrapped");
        webkit_dom_element_remove_attribute (element, "data-evo-plain-text");
+       webkit_dom_element_remove_attribute (element, "data-plain-text-style");
        webkit_dom_element_remove_attribute (element, "data-style");
        webkit_dom_element_remove_attribute (element, "spellcheck");
 }
@@ -7177,79 +7166,82 @@ e_editor_dom_convert_element_from_html_to_plain_text (EEditorPage *editor_page,
 }
 
 static void
-process_elements (EEditorPage *editor_page,
-                  WebKitDOMNode *node,
-                  gboolean changing_mode,
-                  gboolean to_plain_text,
-                  GString *buffer)
-{
-       WebKitDOMNodeList *nodes;
-       gulong ii, length;
-       gchar *content = NULL;
-       gboolean skip_nl = FALSE;
-       gboolean html_mode;
+process_node_to_plain_text_changing_composer_mode (EEditorPage *editor_page,
+                                                   WebKitDOMNode *source)
+{
+       WebKitDOMElement *element;
+       WebKitDOMNamedNodeMap *attributes;
+       gint length, ii;
 
        g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
 
-       if (to_plain_text && !buffer)
-               return;
+       attributes = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (source));
+       length = webkit_dom_named_node_map_get_length (attributes);
+       for (ii = 0; ii < length; ii++) {
+               gchar *name = NULL;
+               WebKitDOMNode *attribute;
 
-       html_mode = e_editor_page_get_html_mode (editor_page);
+               attribute = webkit_dom_named_node_map_item (attributes, ii);
 
-       if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (node)) {
-               if (changing_mode && to_plain_text) {
-                       WebKitDOMNamedNodeMap *attributes;
-                       gulong attributes_length;
-
-                       /* Copy attributes */
-                       g_string_append (buffer, "<html><head></head><body ");
-                       attributes = webkit_dom_element_get_attributes (
-                               WEBKIT_DOM_ELEMENT (node));
-                       attributes_length =
-                               webkit_dom_named_node_map_get_length (attributes);
-
-                       for (ii = 0; ii < attributes_length; ii++) {
-                               gchar *name;
-                               WebKitDOMNode *node =
-                                       webkit_dom_named_node_map_item (
-                                               attributes, ii);
-
-                               name = webkit_dom_node_get_local_name (node);
-                               if (g_strcmp0 (name, "bgcolor") != 0 &&
-                                   g_strcmp0 (name, "text") != 0 &&
-                                   g_strcmp0 (name, "vlink") != 0 &&
-                                   g_strcmp0 (name, "link") != 0) {
-                                       gchar *value;
-
-                                       value = webkit_dom_node_get_node_value (node);
-
-                                       g_string_append (buffer, name);
-                                       g_string_append (buffer, "=\"");
-                                       g_string_append (buffer, value);
-                                       g_string_append (buffer, "\" ");
-
-                                       g_free (value);
-                               }
-                               g_free (name);
-                               g_object_unref (node);
-                       }
-                       g_string_append (buffer, ">");
-                       g_object_unref (attributes);
+               name = webkit_dom_node_get_local_name (attribute);
+
+               if (g_strcmp0 (name, "bgcolor") == 0 ||
+                   g_strcmp0 (name, "text") == 0 ||
+                   g_strcmp0 (name, "vlink") == 0 ||
+                   g_strcmp0 (name, "link") == 0) {
+
+                       webkit_dom_element_remove_attribute_node (
+                               WEBKIT_DOM_ELEMENT (source),
+                               WEBKIT_DOM_ATTR (attribute),
+                               NULL);
+                       length--;
                }
-               if (!to_plain_text)
-                       remove_evolution_attributes (WEBKIT_DOM_ELEMENT (node));
+               g_free (name);
+               g_object_unref (attribute);
        }
+       g_object_unref (attributes);
 
-       nodes = webkit_dom_node_get_child_nodes (node);
-       length = webkit_dom_node_list_get_length (nodes);
+       /* Signature */
+       element = webkit_dom_element_query_selector (
+               WEBKIT_DOM_ELEMENT (source), "div.-x-evo-signature-wrapper", NULL);
+       if (element) {
+               WebKitDOMNode *first_child;
 
-       for (ii = 0; ii < length; ii++) {
+               first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element));
+
+               convert_element_from_html_to_plain_text (
+                       editor_page, WEBKIT_DOM_ELEMENT (first_child), NULL, NULL);
+       }
+}
+
+/* This function is different than the others there as this needs to go through
+ * the DOM node by node and generate the plain text of their content. For some
+ * it will just take the text content, but for example the lists are not that
+ * easy. */
+static void
+process_node_to_plain_text_for_exporting (EEditorPage *editor_page,
+                                          WebKitDOMNode *source,
+                                          GString *buffer)
+{
+       WebKitDOMNodeList *nodes = NULL;
+       gboolean html_mode;
+       gchar *content = NULL;
+       gint ii, nodes_length;
+
+       html_mode = e_editor_page_get_html_mode (editor_page);
+
+       nodes = webkit_dom_node_get_child_nodes (source);
+       nodes_length = webkit_dom_node_list_get_length (nodes);
+
+       for (ii = 0; ii < nodes_length; ii++) {
                WebKitDOMNode *child;
                gboolean skip_node = FALSE;
 
                child = webkit_dom_node_list_item (nodes, ii);
 
                if (WEBKIT_DOM_IS_TEXT (child)) {
+                       gchar *class;
+                       const gchar *css_align = NULL;
                        GRegex *regex;
 
                        content = webkit_dom_node_get_text_content (child);
@@ -7260,270 +7252,111 @@ process_elements (EEditorPage *editor_page,
                                tmp = g_regex_replace (
                                        regex, content, -1, 0, "", 0, NULL);
                                g_free (content);
-                               if (changing_mode) {
-                                       webkit_dom_node_set_text_content (child, tmp, NULL);
-                                       g_free (tmp);
-                                       content = webkit_dom_node_get_text_content (child);
-                               } else
-                                       content = tmp;
+                               content = tmp;
                                g_regex_unref (regex);
                        }
 
-                       if (to_plain_text && !changing_mode) {
-                               gchar *class;
-                               const gchar *css_align = NULL;
+                       class = webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (source));
+                       if (class && (css_align = strstr (class, "-x-evo-align-"))) {
+                               gchar *content_with_align;
+                               gint word_wrap_length = e_editor_page_get_word_wrap_length (editor_page);
 
-                               class = webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (node));
-                               if (class && (css_align = strstr (class, "-x-evo-align-"))) {
+                               if (!g_str_has_prefix (css_align + 13, "left")) {
                                        gchar *align;
-                                       gchar *content_with_align;
                                        gint length;
-                                       gint word_wrap_length = e_editor_page_get_word_wrap_length 
(editor_page);
 
-                                       if (!g_str_has_prefix (css_align + 13, "left")) {
-                                               if (g_str_has_prefix (css_align + 13, "center"))
-                                                       length = (word_wrap_length - g_utf8_strlen (content, 
-1)) / 2;
-                                               else
-                                                       length = word_wrap_length - g_utf8_strlen (content, 
-1);
+                                       if (g_str_has_prefix (css_align + 13, "center"))
+                                               length = (word_wrap_length - g_utf8_strlen (content, -1)) / 2;
+                                       else
+                                               length = word_wrap_length - g_utf8_strlen (content, -1);
 
-                                               if (length < 0)
-                                                       length = 0;
+                                       if (length < 0)
+                                               length = 0;
 
-                                               if (g_str_has_suffix (content, " ")) {
-                                                       char *tmp;
+                                       if (g_str_has_suffix (content, " ")) {
+                                               char *tmp;
 
-                                                       length++;
-                                                       align = g_strnfill (length, ' ');
+                                               length++;
+                                               align = g_strnfill (length, ' ');
 
-                                                       tmp = g_strndup (content, g_utf8_strlen (content, -1) 
-1);
+                                               tmp = g_strndup (content, g_utf8_strlen (content, -1) -1);
 
-                                                       content_with_align = g_strconcat (
-                                                               align, tmp, NULL);
-                                                       g_free (tmp);
-                                               } else {
-                                                       align = g_strnfill (length, ' ');
-
-                                                       content_with_align = g_strconcat (
-                                                               align, content, NULL);
-                                               }
+                                               content_with_align = g_strconcat (
+                                                       align, tmp, NULL);
+                                               g_free (tmp);
+                                       } else {
+                                               align = g_strnfill (length, ' ');
 
-                                               g_free (content);
-                                               g_free (align);
-                                               content = content_with_align;
+                                               content_with_align = g_strconcat (
+                                                       align, content, NULL);
                                        }
-                               }
 
-                               g_free (class);
+                                       g_free (content);
+                                       g_free (align);
+                                       content = content_with_align;
+                               }
                        }
 
-                       if (to_plain_text || changing_mode)
-                               g_string_append (buffer, content);
+                       g_free (class);
 
-                       g_free (content);
+                       g_string_append (buffer, content);
 
                        goto next;
                }
 
-               if (WEBKIT_DOM_IS_COMMENT (child) || !WEBKIT_DOM_IS_ELEMENT (child))
+               if (!WEBKIT_DOM_IS_ELEMENT (child))
                        goto next;
 
                if (element_has_class (WEBKIT_DOM_ELEMENT (child), "Apple-tab-span")) {
-                       if (!changing_mode) {
-                               if (to_plain_text) {
-                                       content = webkit_dom_node_get_text_content (child);
-                                       g_string_append (buffer, content);
-                                       g_free (content);
-                               } else
-                                       element_remove_class (
-                                               WEBKIT_DOM_ELEMENT (child),
-                                               "Applet-tab-span");
-                       }
+                       content = webkit_dom_node_get_text_content (child);
+                       g_string_append (buffer, content);
+                       g_free (content);
                        skip_node = TRUE;
                        goto next;
                }
 
-               /* Leave blockquotes as they are */
-               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (child)) {
-                       if (changing_mode && to_plain_text) {
-                               content = webkit_dom_element_get_outer_html (
-                                       WEBKIT_DOM_ELEMENT (child));
-                               g_string_append (buffer, content);
-                               g_free (content);
-                               skip_node = TRUE;
-                               goto next;
-                       } else {
-                               process_blockquote (WEBKIT_DOM_ELEMENT (child), FALSE);
-                               if (!to_plain_text)
-                                       remove_base_attributes (WEBKIT_DOM_ELEMENT (child));
-                       }
-               }
-
-               if (!to_plain_text && !changing_mode) {
-                       gchar *class;
-                       const gchar *css_align;
-
-                       class = webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (child));
-                       if (class && (css_align = strstr (class, "-x-evo-align-"))) {
-                               if (!g_str_has_prefix (css_align + 13, "left")) {
-                                       if (WEBKIT_DOM_IS_HTML_LI_ELEMENT (child))
-                                               webkit_dom_element_set_attribute (
-                                                       WEBKIT_DOM_ELEMENT (child),
-                                                       "style",
-                                                       g_str_has_prefix (css_align + 13, "center") ?
-                                                               "list-style-position: inside; text-align: 
center" :
-                                                               "list-style-position: inside; text-align: 
right",
-                                                       NULL);
-                                       else
-                                               webkit_dom_element_set_attribute (
-                                                       WEBKIT_DOM_ELEMENT (child),
-                                                       "style",
-                                                       g_str_has_prefix (css_align + 13, "center") ?
-                                                               "text-align: center" :
-                                                               "text-align: right",
-                                                       NULL);
-                               }
-                       }
-                       element_remove_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-align-left");
-                       element_remove_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-align-center");
-                       element_remove_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-align-right");
-                       g_free (class);
-               }
+               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (child))
+                       process_quote_nodes (WEBKIT_DOM_ELEMENT (child));
 
                if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (child) &&
-                   element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-indented")) {
-                       if (!to_plain_text && !changing_mode) {
-                               process_blockquote (WEBKIT_DOM_ELEMENT (child), FALSE);
-                               element_remove_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-indented");
-                       } else
-                               process_blockquote (WEBKIT_DOM_ELEMENT (child), TRUE);
-
-               }
+                   element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-indented"))
+                       process_indented_element (WEBKIT_DOM_ELEMENT (child));
 
                if (node_is_list (child)) {
-                       if (to_plain_text) {
-                               if (changing_mode) {
-                                       content = webkit_dom_element_get_outer_html (
-                                               WEBKIT_DOM_ELEMENT (child));
-                                       g_string_append (buffer, content);
-                                       g_free (content);
-                               } else {
-                                       process_list_to_plain_text (editor_page, WEBKIT_DOM_ELEMENT (child), 
1, buffer);
-                               }
-                               skip_node = TRUE;
-                               goto next;
-                       }
+                       process_list_to_plain_text (editor_page, WEBKIT_DOM_ELEMENT (child), 1, buffer);
+                       skip_node = TRUE;
+                       goto next;
                }
 
                if (element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-resizable-wrapper") &&
                    !element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-smiley-wrapper")) {
-                       WebKitDOMNode *image =
-                               webkit_dom_node_get_first_child (child);
-
-                       if (!to_plain_text && WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (image)) {
-                               remove_evolution_attributes (
-                                       WEBKIT_DOM_ELEMENT (image));
-
-                               webkit_dom_node_replace_child (
-                                       node, image, child, NULL);
-                       }
-
                        skip_node = TRUE;
                        goto next;
                }
 
-               /* Leave paragraphs as they are */
-               if (webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (child), "data-evo-paragraph")) {
-                       if (changing_mode && to_plain_text) {
-                               content = webkit_dom_element_get_outer_html (
-                                       WEBKIT_DOM_ELEMENT (child));
-                               g_string_append (buffer, content);
-                               g_free (content);
-                               skip_node = TRUE;
-                               goto next;
-                       }
-                       if (!to_plain_text) {
-                               remove_base_attributes (WEBKIT_DOM_ELEMENT (child));
-                               remove_evolution_attributes (WEBKIT_DOM_ELEMENT (child));
-                       }
-               }
-
                /* Signature */
                if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (child) &&
                    element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-signature-wrapper")) {
                        WebKitDOMNode *first_child;
+                       gchar *id;
 
                        first_child = webkit_dom_node_get_first_child (child);
 
                        skip_node = TRUE;
                        /* Don't generate any text if the signature is set to None. */
-                       if (!changing_mode) {
-                               gchar *id;
-
-                               id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (first_child));
-                               if (g_strcmp0 (id, "none") == 0) {
-                                       g_free (id);
-
-                                       remove_node (child);
-                                       goto next;
-                               }
+                       id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (first_child));
+                       if (g_strcmp0 (id, "none") == 0) {
                                g_free (id);
-                       }
 
-                       if (!to_plain_text) {
-                               remove_base_attributes (
-                                       WEBKIT_DOM_ELEMENT (child));
-                               remove_base_attributes (
-                                       WEBKIT_DOM_ELEMENT (first_child));
-                               remove_evolution_attributes (
-                                       WEBKIT_DOM_ELEMENT (first_child));
-                               if (!changing_mode)
-                                       skip_node = FALSE;
-                       } else if (changing_mode) {
-                               content = webkit_dom_element_get_outer_html (
-                                       WEBKIT_DOM_ELEMENT (child));
-                               g_string_append (buffer, content);
-                               g_free (content);
-                       } else {
-                               g_string_append (buffer, "\n");
+                               remove_node (child);
+                               goto next;
+                       }
+                       g_free (id);
 
-                               if (html_mode) {
-                                       convert_element_from_html_to_plain_text (
-                                               editor_page, WEBKIT_DOM_ELEMENT (first_child), NULL, NULL);
-                               } else {
-                                       WebKitDOMNode *signature_node;
-
-                                       signature_node = webkit_dom_node_get_last_child (first_child);
-                                       if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (signature_node)) {
-                                               WebKitDOMNode *last_child;
-
-                                               /* Remove a line break on the end of the last
-                                                * PRE element. It is not showed by the WebKit,
-                                                * but it is still there are will be added to
-                                                * the output. */
-                                               last_child = webkit_dom_node_get_last_child (signature_node);
-                                               if (WEBKIT_DOM_IS_CHARACTER_DATA (last_child)) {
-                                                       WebKitDOMCharacterData *data;
-                                                       glong length;
-
-                                                       data = WEBKIT_DOM_CHARACTER_DATA (last_child);
-                                                       length = webkit_dom_character_data_get_length (data);
-                                                       if (length > 0) {
-                                                               gchar *last_char;
-
-                                                               last_char = 
webkit_dom_character_data_substring_data (
-                                                                               data, length - 1, 1, NULL);
-
-                                                               if (last_char && *last_char == '\n')
-                                                                       webkit_dom_character_data_delete_data 
(
-                                                                                       data, length -1, 1, 
NULL);
-
-                                                               g_free (last_char);
-                                                       }
-                                               }
-                                       }
-                               }
+                       if (html_mode) {
+                               convert_element_from_html_to_plain_text (
+                                       editor_page, WEBKIT_DOM_ELEMENT (first_child), NULL, NULL);
                                skip_node = FALSE;
-                               skip_nl = TRUE;
                        }
 
                        goto next;
@@ -7531,136 +7364,248 @@ process_elements (EEditorPage *editor_page,
 
                /* Replace smileys with their text representation */
                if (element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-smiley-wrapper")) {
-                       if (to_plain_text && !changing_mode) {
-                               WebKitDOMNode *text_version;
+                       WebKitDOMNode *text_version;
 
-                               text_version = webkit_dom_node_get_last_child (child);
-                               content = webkit_dom_html_element_get_inner_text (
-                                       WEBKIT_DOM_HTML_ELEMENT (text_version));
-                               g_string_append (buffer, content);
-                               g_free (content);
-                               skip_node = TRUE;
-                               goto next;
-                       }
-                       if (!to_plain_text) {
-                               WebKitDOMElement *img;
+                       text_version = webkit_dom_node_get_last_child (child);
+                       content = webkit_dom_html_element_get_inner_text (
+                               WEBKIT_DOM_HTML_ELEMENT (text_version));
+                       g_string_append (buffer, content);
+                       g_free (content);
+                       skip_node = TRUE;
+                       goto next;
+               }
 
-                               img = WEBKIT_DOM_ELEMENT (
-                                       webkit_dom_node_get_first_child (child)),
+               if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (child)) {
+                       g_string_append (buffer, "\n");
+                       goto next;
+               }
 
-                               remove_evolution_attributes (img);
-                               remove_base_attributes (img);
+               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (child)) {
+                       content = webkit_dom_html_element_get_inner_text (
+                               WEBKIT_DOM_HTML_ELEMENT (child));
+                       g_string_append (buffer, content);
+                       g_free (content);
+                       skip_node = TRUE;
+               }
+ next:
+               if (!skip_node && webkit_dom_node_has_child_nodes (child))
+                       process_node_to_plain_text_for_exporting (editor_page, child, buffer);
+               g_object_unref (child);
+       }
+       g_object_unref (nodes);
 
-                               webkit_dom_node_insert_before (
-                                       webkit_dom_node_get_parent_node (child),
-                                       WEBKIT_DOM_NODE (img),
-                                       child,
+       if (!g_str_has_suffix (buffer->str, "\n") &&
+            (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (source) ||
+             WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT (source) ||
+             WEBKIT_DOM_IS_HTML_PRE_ELEMENT (source) ||
+             WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (source)))
+               g_string_append (buffer, "\n");
+
+       if (g_str_has_suffix (buffer->str, "\n") &&
+           WEBKIT_DOM_IS_HTML_BODY_ELEMENT (source))
+               g_string_truncate (buffer, buffer->len - 1);
+}
+
+static void
+process_node_to_html_changing_composer_mode (EEditorPage *editor_page,
+                                             WebKitDOMNode *source)
+{
+}
+
+static void
+process_node_to_html_for_exporting (EEditorPage *editor_page,
+                                    WebKitDOMNode *source)
+{
+       WebKitDOMNodeList *list = NULL;
+       WebKitDOMHTMLCollection *collection;
+       WebKitDOMElement *element;
+       WebKitDOMDocument *document;
+       gint ii, length;
+
+       document = webkit_dom_node_get_owner_document (source);
+
+       remove_evolution_attributes (WEBKIT_DOM_ELEMENT (source));
+
+       /* Aligned elements */
+       list = webkit_dom_element_query_selector_all (WEBKIT_DOM_ELEMENT (source), 
"[class^=\"-x-evo-align\"]", NULL);
+       length = webkit_dom_node_list_get_length (list);
+
+       for (ii = 0; ii < length; ii++) {
+               gchar *class = NULL;
+               const gchar *align_type;
+               WebKitDOMNode *node;
+
+               node = webkit_dom_node_list_item (list, ii);
+               class = webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (node));
+               align_type = class + 13;
+               if (!g_str_has_prefix (align_type, "left")) {
+                       if (WEBKIT_DOM_IS_HTML_LI_ELEMENT (node))
+                               webkit_dom_element_set_attribute (
+                                       WEBKIT_DOM_ELEMENT (node),
+                                       "style",
+                                       g_str_has_prefix (align_type, "center") ?
+                                               "list-style-position: inside; text-align: center" :
+                                               "list-style-position: inside; text-align: right",
+                                       NULL);
+                       else
+                               webkit_dom_element_set_attribute (
+                                       WEBKIT_DOM_ELEMENT (node),
+                                       "style",
+                                       g_str_has_prefix (align_type + 13, "center") ?
+                                               "text-align: center" :
+                                               "text-align: right",
                                        NULL);
-                               remove_node (child);
-                               skip_node = TRUE;
-                               goto next;
-                       }
                }
+               element_remove_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-align-left");
+               element_remove_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-align-center");
+               element_remove_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-align-right");
+               g_free (class);
+               g_object_unref (node);
+       }
+       g_object_unref (list);
 
-               /* Leave PRE elements untouched */
-               if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (child)) {
-                       if (!to_plain_text) {
-                               remove_evolution_attributes (WEBKIT_DOM_ELEMENT (child));
-                       } else if (changing_mode) {
-                               content = webkit_dom_element_get_outer_html (
-                                       WEBKIT_DOM_ELEMENT (child));
-                               g_string_append (buffer, content);
-                               g_free (content);
-                               skip_node = TRUE;
-                       }
-               }
+       /* Indented elements */
+       list = webkit_dom_element_query_selector_all (
+                       WEBKIT_DOM_ELEMENT (source), ".-x-evo-indented", NULL);
+       length = webkit_dom_node_list_get_length (list);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node;
 
-               if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (child)) {
-                       if (to_plain_text) {
-                               if (element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-wrap-br")) {
-                                       g_string_append (buffer, changing_mode ? "<br>" : "\n");
-                                       goto next;
-                               }
+               node = webkit_dom_node_list_item (list, ii);
+               element_remove_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-indented");
+               remove_evolution_attributes (WEBKIT_DOM_ELEMENT (node));
 
-                               /* Insert new line when we hit the BR element that is
-                                * not the last element in the block */
-                               if (!webkit_dom_node_is_same_node (
-                                       child, webkit_dom_node_get_last_child (node))) {
-                                       g_string_append (buffer, changing_mode ? "<br>" : "\n");
-                               } else {
-                                       /* In citations in the empty lines the BR element
-                                        * is on the end and we have to put NL there */
-                                       WebKitDOMNode *parent;
+               g_object_unref (node);
+       }
+       g_object_unref (list);
 
-                                       parent = webkit_dom_node_get_parent_node (child);
-                                       if (webkit_dom_node_get_next_sibling (parent)) {
-                                               parent = webkit_dom_node_get_parent_node (parent);
+       /* Tab characters */
+       list = webkit_dom_element_query_selector_all (
+               WEBKIT_DOM_ELEMENT (source), ".Apple-tab-span", NULL);
+       length = webkit_dom_node_list_get_length (list);
+       for (ii = 0; ii < length; ii++) {
+               gchar *text_content;
+               WebKitDOMNode *node;
 
-                                               if (e_editor_dom_node_is_citation_node (parent))
-                                                       g_string_append (buffer, changing_mode ? "<br>" : 
"\n");
-                                       }
-                               }
-                       }
+               node = webkit_dom_node_list_item (list, ii);
+               text_content = webkit_dom_node_get_text_content (node);
+               webkit_dom_node_insert_before (
+                       webkit_dom_node_get_parent_node (node),
+                       WEBKIT_DOM_NODE (webkit_dom_document_create_text_node (document, text_content)),
+                       node,
+                       NULL);
+
+               remove_node (node);
+               g_object_unref (node);
+       }
+       g_object_unref (list);
+
+       list = webkit_dom_element_query_selector_all (
+                       WEBKIT_DOM_ELEMENT (source), ".-x-evo-quoted", NULL);
+       length = webkit_dom_node_list_get_length (list);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *quoted_node;
+               gchar *text_content;
+
+               quoted_node = webkit_dom_node_list_item (list, ii);
+               text_content = webkit_dom_node_get_text_content (quoted_node);
+               webkit_dom_element_set_outer_html (
+                       WEBKIT_DOM_ELEMENT (quoted_node), text_content, NULL);
+
+               g_free (text_content);
+               g_object_unref (quoted_node);
+       }
+       g_object_unref (list);
+
+       /* Images */
+       list = webkit_dom_element_query_selector_all (
+               WEBKIT_DOM_ELEMENT (source), ".-x-evo-resizable-wrapper:not(.-x-evo-smiley-wrapper)", NULL);
+       length = webkit_dom_node_list_get_length (list);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node, *image;
+
+               node = webkit_dom_node_list_item (list, ii);
+               image = webkit_dom_node_get_first_child (node);
+
+               if (WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (image)) {
+                       remove_evolution_attributes (
+                               WEBKIT_DOM_ELEMENT (image));
+
+                       webkit_dom_node_replace_child (
+                               webkit_dom_node_get_parent_node (node), image, node, NULL);
                }
 
-               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (child)) {
-                       if (changing_mode && to_plain_text) {
-                               content = webkit_dom_element_get_outer_html (
-                                       WEBKIT_DOM_ELEMENT (child));
-                               g_string_append (buffer, content);
-                               g_free (content);
-                               skip_node = TRUE;
-                       }
-                       if (!changing_mode) {
-                               if (to_plain_text) {
-                                       content = webkit_dom_html_element_get_inner_text (
-                                               WEBKIT_DOM_HTML_ELEMENT (child));
-                                       g_string_append (buffer, content);
-                                       g_free (content);
-                                       skip_node = TRUE;
-                               } else
-                                       remove_base_attributes (WEBKIT_DOM_ELEMENT (child));
-                       }
+               g_object_unref (node);
+       }
+       g_object_unref (list);
+
+       /* Signature */
+       element = webkit_dom_element_query_selector (
+               WEBKIT_DOM_ELEMENT (source), "div.-x-evo-signature-wrapper", NULL);
+       if (element) {
+               WebKitDOMNode *first_child;
+               gchar *id;
+
+               /* Don't generate any text if the signature is set to None. */
+               first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element));
+               id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (first_child));
+               if (g_strcmp0 (id, "none") == 0) {
+                       remove_node (WEBKIT_DOM_NODE (element));
+               } else {
+                       remove_base_attributes (element);
+                       remove_base_attributes (WEBKIT_DOM_ELEMENT (first_child));
+                       remove_evolution_attributes (WEBKIT_DOM_ELEMENT (first_child));
                }
- next:
-               if (webkit_dom_node_has_child_nodes (child) && !skip_node)
-                       process_elements (
-                               editor_page, child, changing_mode, to_plain_text, buffer);
-               g_object_unref (child);
+               g_free (id);
        }
 
-       if (to_plain_text && (
-           WEBKIT_DOM_IS_HTML_DIV_ELEMENT (node) ||
-           WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT (node) ||
-           WEBKIT_DOM_IS_HTML_PRE_ELEMENT (node) ||
-           WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node))) {
+       /* Smileys */
+       list = webkit_dom_element_query_selector_all (
+               WEBKIT_DOM_ELEMENT (source), "-x-evo-smiley-wrapper", NULL);
+       length = webkit_dom_node_list_get_length (list);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node;
+               WebKitDOMElement *img;
 
-               gboolean add_br = TRUE;
-               WebKitDOMNode *next_sibling = webkit_dom_node_get_next_sibling (node);
-               WebKitDOMNode *last_child = webkit_dom_node_get_last_child (node);
+               node = webkit_dom_node_list_item (list, ii);
+               img = WEBKIT_DOM_ELEMENT (webkit_dom_node_get_first_child (node));
 
-               if (last_child && WEBKIT_DOM_IS_HTML_BR_ELEMENT (last_child))
-                       if (webkit_dom_node_get_previous_sibling (last_child))
-                               add_br = FALSE;
+               remove_evolution_attributes (img);
+               remove_base_attributes (img);
 
-               /* If we don't have next sibling (last element in body) or next element is
-                * signature we are not adding the BR element */
-               if (!next_sibling)
-                       add_br = FALSE;
-               else if (next_sibling && WEBKIT_DOM_IS_HTML_DIV_ELEMENT (next_sibling)) {
-                       if (webkit_dom_element_query_selector (
-                               WEBKIT_DOM_ELEMENT (next_sibling),
-                               "span.-x-evo-signature", NULL)) {
+               webkit_dom_node_replace_child (
+                       webkit_dom_node_get_parent_node (node),
+                       WEBKIT_DOM_NODE (img),
+                       node,
+                       NULL);
 
-                               add_br = FALSE;
-                       }
-               }
+               g_object_unref (node);
+       }
+       g_object_unref (list);
+
+       collection = webkit_dom_element_get_elements_by_tag_name_as_html_collection (
+               WEBKIT_DOM_ELEMENT (source), "pre");
+       length = webkit_dom_html_collection_get_length (collection);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node;
 
-               if (add_br && !skip_nl)
-                       g_string_append (buffer, changing_mode ? "<br>" : "\n");
+               node = webkit_dom_html_collection_item (collection, ii);
+               remove_evolution_attributes (WEBKIT_DOM_ELEMENT (node));
+               g_object_unref (node);
        }
+       g_object_unref (collection);
 
-       g_object_unref (nodes);
+       list = webkit_dom_element_query_selector_all (
+               WEBKIT_DOM_ELEMENT (source), ".-x-evo-paragraph", NULL);
+       length = webkit_dom_node_list_get_length (list);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node;
+
+               node = webkit_dom_node_list_item (list, ii);
+               element_remove_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-paragraph");
+               g_object_unref (node);
+       }
+       g_object_unref (list);
 }
 
 static void
@@ -7709,7 +7654,6 @@ remove_images_in_element (WebKitDOMElement *element)
                remove_node (node);
                g_object_unref (node);
        }
-
        g_object_unref (images);
 }
 
@@ -7946,38 +7890,207 @@ e_editor_dom_process_content_for_draft (EEditorPage *editor_page,
        return content;
 }
 
-static gchar *
-process_content_for_mode_change (EEditorPage *editor_page)
+static void
+toggle_indented_elements (EEditorPage *editor_page)
+{
+       gboolean html_mode;
+       gint ii, length;
+       WebKitDOMDocument *document;
+       WebKitDOMNodeList *list;
+
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+       document = e_editor_page_get_document (editor_page);
+       html_mode = e_editor_page_get_html_mode (editor_page);
+       list = webkit_dom_document_query_selector_all (document, ".-x-evo-indented", NULL);
+       length = webkit_dom_node_list_get_length (list);
+
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);
+
+               if (html_mode)
+                       dom_element_swap_attributes (WEBKIT_DOM_ELEMENT (node), "style", 
"data-plain-text-style");
+               else
+                       dom_element_swap_attributes (WEBKIT_DOM_ELEMENT (node), "data-plain-text-style", 
"style");
+               g_object_unref (node);
+       }
+       g_object_unref (list);
+}
+
+static void
+toggle_tables (EEditorPage *editor_page)
+{
+       gboolean html_mode;
+       gint ii, length;
+       WebKitDOMDocument *document;
+       WebKitDOMNodeList *list;
+
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+       document = e_editor_page_get_document (editor_page);
+       html_mode = e_editor_page_get_html_mode (editor_page);
+       list = webkit_dom_document_query_selector_all (document, "table", NULL);
+       length = webkit_dom_node_list_get_length (list);
+
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *table = webkit_dom_node_list_item (list, ii);
+
+               if (html_mode) {
+                       element_remove_class (WEBKIT_DOM_ELEMENT (table), "-x-evo-plaintext-table");
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-width", "width");
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-cellspacing", 
"cellspacing");
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-cellpadding", 
"cellpadding");
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-border", "border");
+               } else {
+                       element_add_class (WEBKIT_DOM_ELEMENT (table), "-x-evo-plaintext-table");
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "width", "data-width");
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "cellspacing", 
"data-cellspacing");
+                       webkit_dom_element_set_attribute (WEBKIT_DOM_ELEMENT (table), "cellspacing", "0", 
NULL);
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "cellpadding", 
"data-cellpadding");
+                       webkit_dom_element_set_attribute (WEBKIT_DOM_ELEMENT (table), "cellpadding", "0", 
NULL);
+                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "border", "data-border");
+                       webkit_dom_element_set_attribute (WEBKIT_DOM_ELEMENT (table), "border", "0", NULL);
+               }
+               g_object_unref (table);
+       }
+       g_object_unref (list);
+}
+
+static void
+toggle_unordered_lists (EEditorPage *editor_page)
+{
+       gboolean html_mode;
+       gint ii, length;
+       WebKitDOMDocument *document;
+       WebKitDOMNodeList *list;
+
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+       document = e_editor_page_get_document (editor_page);
+       html_mode = e_editor_page_get_html_mode (editor_page);
+       list = webkit_dom_document_query_selector_all (document, "ul", NULL);
+       length = webkit_dom_node_list_get_length (list);
+
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);
+
+               if (html_mode) {
+                       webkit_dom_element_remove_attribute (
+                               WEBKIT_DOM_ELEMENT (node), "data-evo-plain-text");
+               } else {
+                       webkit_dom_element_set_attribute (
+                               WEBKIT_DOM_ELEMENT (node), "data-evo-plain-text", "", NULL);
+               }
+               g_object_unref (node);
+       }
+       g_object_unref (list);
+}
+
+static void
+process_content_to_html_changing_composer_mode (EEditorPage *editor_page)
 {
        WebKitDOMDocument *document;
        WebKitDOMNode *body;
-       GString *plain_text;
+       WebKitDOMElement *blockquote;
 
-       g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), NULL);
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
 
        document = e_editor_page_get_document (editor_page);
        body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
 
-       plain_text = g_string_sized_new (1024);
+       blockquote = webkit_dom_document_query_selector (
+               document, "blockquote[type|=cite]", NULL);
+
+       if (blockquote)
+               dom_dequote_plain_text (document);
+
+       toggle_paragraphs_style (editor_page);
+       toggle_smileys (editor_page);
+       toggle_tables (editor_page);
+       toggle_unordered_lists (editor_page);
+       remove_images (document);
+       e_editor_dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (body));
+
+       process_node_to_html_changing_composer_mode (editor_page, body);
+}
+
+static void
+wrap_paragraphs_in_quoted_content (EEditorPage *editor_page)
+{
+       WebKitDOMDocument *document;
+       WebKitDOMNodeList *paragraphs;
+       gint ii, length;
+
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+       document = e_editor_page_get_document (editor_page);
+       paragraphs = webkit_dom_document_query_selector_all (
+               document, "blockquote[type=cite] > [data-evo-paragraph]", NULL);
+
+       length = webkit_dom_node_list_get_length (paragraphs);
+       for (ii = 0; ii < length; ii++) {
+               WebKitDOMNode *paragraph;
+
+               paragraph = webkit_dom_node_list_item (paragraphs, ii);
+
+               e_editor_dom_wrap_paragraph (editor_page, WEBKIT_DOM_ELEMENT (paragraph));
+
+               g_object_unref (paragraph);
+       }
+       g_object_unref (paragraphs);
+}
+
+static void
+process_content_to_plain_text_changing_composer_mode (EEditorPage *editor_page)
+{
+       WebKitDOMDocument *document;
+       WebKitDOMNode *body, *head, *node;
+       WebKitDOMElement *blockquote;
+
+       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
+
+       document = e_editor_page_get_document (editor_page);
+       body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
+       head = WEBKIT_DOM_NODE (webkit_dom_document_get_head (document));
+
+       while ((node = webkit_dom_node_get_last_child (head)))
+               remove_node (node);
+
+       e_editor_dom_selection_save (editor_page);
 
        webkit_dom_element_remove_attribute (
                WEBKIT_DOM_ELEMENT (body), "data-user-colors");
 
-       process_elements (editor_page, body, TRUE, TRUE, plain_text);
+       blockquote = webkit_dom_document_query_selector (
+               document, "blockquote[type|=cite]", NULL);
 
-       g_string_append (plain_text, "</body></html>");
+       if (blockquote) {
+               wrap_paragraphs_in_quoted_content (editor_page);
+               quote_plain_text_elements_after_wrapping_in_document (editor_page);
+       }
 
-       return g_string_free (plain_text, FALSE);
+       toggle_paragraphs_style (editor_page);
+       toggle_smileys (editor_page);
+       toggle_tables (editor_page);
+       toggle_indented_elements (editor_page);
+       toggle_unordered_lists (editor_page);
+       remove_images (document);
+       remove_background_images_in_element (WEBKIT_DOM_ELEMENT (body));
+
+       process_node_to_plain_text_changing_composer_mode (editor_page, body);
+
+       e_editor_dom_selection_restore (editor_page);
+       e_editor_dom_force_spell_check_in_viewport (editor_page);
 }
 
 gchar *
-e_editor_dom_process_content_for_plain_text (EEditorPage *editor_page)
+e_editor_dom_process_content_to_plain_text_for_exporting (EEditorPage *editor_page)
 {
        EContentEditorContentFlags flags;
        WebKitDOMDocument *document;
        WebKitDOMNode *body, *source;
        WebKitDOMNodeList *paragraphs;
-       gboolean wrap = FALSE, quote = FALSE, clean = FALSE;
+       gboolean wrap = FALSE, quote = FALSE;
        gboolean converted, is_from_new_message, is_message_draft;
        gint length, ii;
        GString *plain_text;
@@ -8009,21 +8122,16 @@ e_editor_dom_process_content_for_plain_text (EEditorPage *editor_page)
                        remove_background_images_in_element (
                                WEBKIT_DOM_ELEMENT (source));
                } else {
-                       gchar *inner_html;
                        WebKitDOMElement *div;
+                       WebKitDOMNode *child;
 
-                       inner_html = webkit_dom_element_get_inner_html (
-                               WEBKIT_DOM_ELEMENT (body));
-
-                       div = webkit_dom_document_create_element (
-                               document, "div", NULL);
-
-                       webkit_dom_element_set_inner_html (div, inner_html, NULL);
-
-                       webkit_dom_node_append_child (
-                               WEBKIT_DOM_NODE (body),
-                               WEBKIT_DOM_NODE (div),
-                               NULL);
+                       div = webkit_dom_document_create_element (document, "div", NULL);
+                       while ((child = webkit_dom_node_get_first_child (source))) {
+                               webkit_dom_node_append_child (
+                                       WEBKIT_DOM_NODE (div),
+                                       child,
+                                       NULL);
+                       }
 
                        paragraphs = webkit_dom_element_query_selector_all (
                                div, "#-x-evo-input-start", NULL);
@@ -8039,14 +8147,12 @@ e_editor_dom_process_content_for_plain_text (EEditorPage *editor_page)
                        }
                        g_object_unref (paragraphs);
 
+                       remove_images_in_element (div);
+
                        convert_element_from_html_to_plain_text (
                                editor_page, div, &wrap, &quote);
 
-                       g_object_unref (source);
-
                        source = WEBKIT_DOM_NODE (div);
-
-                       clean = TRUE;
                }
        }
 
@@ -8080,7 +8186,7 @@ e_editor_dom_process_content_for_plain_text (EEditorPage *editor_page)
        g_object_unref (paragraphs);
 
        paragraphs = webkit_dom_element_query_selector_all (
-               WEBKIT_DOM_ELEMENT (source), "span[id^=\"-x-evo-selection-\"]", NULL);
+               WEBKIT_DOM_ELEMENT (source), "#-x-evo-selection-start-marker, #-x-evo-selection-end-marker", 
NULL);
 
        length = webkit_dom_node_list_get_length (paragraphs);
        for (ii = 0; ii < length; ii++) {
@@ -8104,12 +8210,7 @@ e_editor_dom_process_content_for_plain_text (EEditorPage *editor_page)
                        quote_plain_text_recursive (document, source, source, 0);
        }
 
-       process_elements (editor_page, source, FALSE, TRUE, plain_text);
-
-       if (clean)
-               remove_node (source);
-       else
-               g_object_unref (source);
+       process_node_to_plain_text_for_exporting (editor_page, source, plain_text);
 
        e_editor_dom_selection_restore (editor_page);
 
@@ -8171,7 +8272,7 @@ e_editor_dom_restore_images (EEditorPage *editor_page,
 }
 
 gchar *
-e_editor_dom_process_content_for_html (EEditorPage *editor_page)
+e_editor_dom_process_content_to_html_for_exporting (EEditorPage *editor_page)
 {
        WebKitDOMDocument *document;
        WebKitDOMElement *element;
@@ -8254,7 +8355,7 @@ e_editor_dom_process_content_for_html (EEditorPage *editor_page)
        }
        g_object_unref (list);
 
-       process_elements (editor_page, node, FALSE, FALSE, NULL);
+       process_node_to_html_for_exporting (editor_page, node);
 
        html_content = webkit_dom_element_get_outer_html (
                WEBKIT_DOM_ELEMENT (document_clone));
@@ -8306,32 +8407,6 @@ e_editor_dom_convert_when_changing_composer_mode (EEditorPage *editor_page)
 }
 
 static void
-wrap_paragraphs_in_quoted_content (EEditorPage *editor_page)
-{
-       WebKitDOMDocument *document;
-       WebKitDOMNodeList *paragraphs;
-       gint ii, length;
-
-       g_return_if_fail (E_IS_EDITOR_PAGE (editor_page));
-
-       document = e_editor_page_get_document (editor_page);
-       paragraphs = webkit_dom_document_query_selector_all (
-               document, "blockquote[type=cite] > [data-evo-paragraph]", NULL);
-
-       length = webkit_dom_node_list_get_length (paragraphs);
-       for (ii = 0; ii < length; ii++) {
-               WebKitDOMNode *paragraph;
-
-               paragraph = webkit_dom_node_list_item (paragraphs, ii);
-
-               e_editor_dom_wrap_paragraph (editor_page, WEBKIT_DOM_ELEMENT (paragraph));
-
-               g_object_unref (paragraph);
-       }
-       g_object_unref (paragraphs);
-}
-
-static void
 set_base64_to_element_attribute (GHashTable *inline_images,
                                  WebKitDOMElement *element,
                                  const gchar *attribute)
@@ -10403,70 +10478,10 @@ e_editor_dom_check_if_conversion_needed (EEditorPage *editor_page)
        return !html_mode && (contains_forbidden_elements (document) || (convert && !message_from_draft));
 }
 
-static void
-toggle_tables (WebKitDOMDocument *document,
-               gboolean html_mode)
-{
-       WebKitDOMNodeList *list;
-       gint ii, length;
-
-       list = webkit_dom_document_query_selector_all (document, "table", NULL);
-       length = webkit_dom_node_list_get_length (list);
-
-       for (ii = 0; ii < length; ii++) {
-               WebKitDOMNode *table = webkit_dom_node_list_item (list, ii);
-
-               if (html_mode) {
-                       element_remove_class (WEBKIT_DOM_ELEMENT (table), "-x-evo-plaintext-table");
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-width", "width");
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-cellspacing", 
"cellspacing");
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-cellpadding", 
"cellpadding");
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "data-border", "border");
-               } else {
-                       element_add_class (WEBKIT_DOM_ELEMENT (table), "-x-evo-plaintext-table");
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "width", "data-width");
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "cellspacing", 
"data-cellspacing");
-                       webkit_dom_element_set_attribute (WEBKIT_DOM_ELEMENT (table), "cellspacing", "0", 
NULL);
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "cellpadding", 
"data-cellpadding");
-                       webkit_dom_element_set_attribute (WEBKIT_DOM_ELEMENT (table), "cellpadding", "0", 
NULL);
-                       element_rename_attribute (WEBKIT_DOM_ELEMENT (table), "border", "data-border");
-                       webkit_dom_element_set_attribute (WEBKIT_DOM_ELEMENT (table), "border", "0", NULL);
-               }
-               g_object_unref (table);
-       }
-       g_object_unref (list);
-}
-
-static void
-toggle_unordered_lists (WebKitDOMDocument *document,
-                        gboolean html_mode)
-{
-       WebKitDOMNodeList *list;
-       gint ii, length;
-
-       list = webkit_dom_document_query_selector_all (document, "ul", NULL);
-       length = webkit_dom_node_list_get_length (list);
-
-       for (ii = 0; ii < length; ii++) {
-               WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);
-
-               if (html_mode) {
-                       webkit_dom_element_remove_attribute (
-                               WEBKIT_DOM_ELEMENT (node), "data-evo-plain-text");
-               } else {
-                       webkit_dom_element_set_attribute (
-                               WEBKIT_DOM_ELEMENT (node), "data-evo-plain-text", "", NULL);
-               }
-               g_object_unref (node);
-       }
-       g_object_unref (list);
-}
-
 void
 e_editor_dom_process_content_after_mode_change (EEditorPage *editor_page)
 {
        WebKitDOMDocument *document;
-       WebKitDOMElement *blockquote;
        EEditorUndoRedoManager *manager;
        gboolean html_mode;
 
@@ -10475,56 +10490,10 @@ e_editor_dom_process_content_after_mode_change (EEditorPage *editor_page)
        document = e_editor_page_get_document (editor_page);
        html_mode = e_editor_page_get_html_mode (editor_page);
 
-       blockquote = webkit_dom_document_query_selector (
-               document, "blockquote[type|=cite]", NULL);
-
-       if (html_mode) {
-               WebKitDOMHTMLElement *body;
-
-               if (blockquote)
-                       dom_dequote_plain_text (document);
-
-               toggle_paragraphs_style (editor_page);
-               toggle_smileys (editor_page);
-               toggle_tables (document, html_mode);
-               toggle_unordered_lists (document, html_mode);
-
-               body = webkit_dom_document_get_body (document);
-
-               e_editor_dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (body));
-       } else {
-               gchar *plain;
-               WebKitDOMHTMLElement *body;
-
-               e_editor_dom_selection_save (editor_page);
-
-               if (blockquote) {
-                       wrap_paragraphs_in_quoted_content (editor_page);
-                       quote_plain_text_elements_after_wrapping_in_document (editor_page);
-               }
-
-               toggle_paragraphs_style (editor_page);
-               toggle_smileys (editor_page);
-               toggle_tables (document, html_mode);
-               toggle_unordered_lists (document, html_mode);
-               remove_images (document);
-               body = webkit_dom_document_get_body (document);
-               remove_background_images_in_element (WEBKIT_DOM_ELEMENT (body));
-
-               plain = process_content_for_mode_change (editor_page);
-
-               if (*plain) {
-                       webkit_dom_element_set_outer_html (
-                               WEBKIT_DOM_ELEMENT (
-                                       webkit_dom_document_get_document_element (document)),
-                               plain,
-                               NULL);
-                       e_editor_dom_selection_restore (editor_page);
-                       e_editor_dom_force_spell_check_in_viewport (editor_page);
-               }
-
-               g_free (plain);
-       }
+       if (html_mode)
+               process_content_to_html_changing_composer_mode (editor_page);
+       else
+               process_content_to_plain_text_changing_composer_mode (editor_page);
 
        e_editor_dom_set_monospace_font_family_on_body (
                WEBKIT_DOM_ELEMENT (webkit_dom_document_get_body (document)), html_mode);
@@ -11753,12 +11722,23 @@ dom_set_indented_style (EEditorPage *editor_page,
        word_wrap_length = set_word_wrap_length (editor_page, width);
        webkit_dom_element_set_class_name (element, "-x-evo-indented");
 
-       if (e_editor_page_get_html_mode (editor_page) || word_wrap_length == 0)
+       if (e_editor_page_get_html_mode (editor_page) || word_wrap_length == 0) {
+               gchar *plain_text_style;
+
                style = g_strdup_printf ("margin-left: %dch;", SPACES_PER_INDENTATION);
-       else
+
+               plain_text_style = g_strdup_printf (
+                               "margin-left: %dch; word-wrap: normal; width: %dch;",
+                               SPACES_PER_INDENTATION, word_wrap_length);
+
+               webkit_dom_element_set_attribute (
+                               element, "data-plain-text-style", plain_text_style, NULL);
+               g_free (plain_text_style);
+       } else {
                style = g_strdup_printf (
                        "margin-left: %dch; word-wrap: normal; width: %dch;",
                        SPACES_PER_INDENTATION, word_wrap_length);
+       }
 
        webkit_dom_element_set_attribute (element, "style", style, NULL);
        g_free (style);
diff --git a/modules/webkit-editor/web-extension/e-editor-dom-functions.h 
b/modules/webkit-editor/web-extension/e-editor-dom-functions.h
index 29cd7b3..c65cbef 100644
--- a/modules/webkit-editor/web-extension/e-editor-dom-functions.h
+++ b/modules/webkit-editor/web-extension/e-editor-dom-functions.h
@@ -148,11 +148,11 @@ void              e_editor_dom_convert_element_from_html_to_plain_text
 gchar *                e_editor_dom_process_content_for_draft
                                                (EEditorPage *editor_page,
                                                 gboolean only_inner_body);
-gchar *                e_editor_dom_process_content_for_plain_text
+gchar *                e_editor_dom_process_content_to_plain_text_for_exporting
                                                (EEditorPage *editor_page);
 void           e_editor_dom_restore_images     (EEditorPage *editor_page,
                                                 GVariant *inline_images_to_restore);
-gchar *                e_editor_dom_process_content_for_html
+gchar *                e_editor_dom_process_content_to_html_for_exporting
                                                (EEditorPage *editor_page);
 gboolean       e_editor_dom_check_if_conversion_needed
                                                (EEditorPage *editor_page);
diff --git a/modules/webkit-editor/web-extension/e-editor-web-extension.c 
b/modules/webkit-editor/web-extension/e-editor-web-extension.c
index c8d4d1f..fa72c7e 100644
--- a/modules/webkit-editor/web-extension/e-editor-web-extension.c
+++ b/modules/webkit-editor/web-extension/e-editor-web-extension.c
@@ -1807,11 +1807,11 @@ handle_method_call (GDBusConnection *connection,
                } else if ((flags & E_CONTENT_EDITOR_GET_TEXT_HTML) &&
                           (flags & E_CONTENT_EDITOR_GET_PROCESSED) &&
                           !(flags & E_CONTENT_EDITOR_GET_BODY)) {
-                       value = e_editor_dom_process_content_for_html (editor_page);
+                       value = e_editor_dom_process_content_to_html_for_exporting (editor_page);
                } else if ((flags & E_CONTENT_EDITOR_GET_TEXT_PLAIN) &&
                           (flags & E_CONTENT_EDITOR_GET_PROCESSED) &&
                           !(flags & E_CONTENT_EDITOR_GET_BODY)) {
-                       value = e_editor_dom_process_content_for_plain_text (editor_page);
+                       value = e_editor_dom_process_content_to_plain_text_for_exporting (editor_page);
                } else if ((flags & E_CONTENT_EDITOR_GET_TEXT_PLAIN) &&
                           (flags & E_CONTENT_EDITOR_GET_BODY) &&
                           !(flags & E_CONTENT_EDITOR_GET_PROCESSED)) {
diff --git a/web-extensions/e-dom-utils.c b/web-extensions/e-dom-utils.c
index 3820c84..f3577a2 100644
--- a/web-extensions/e-dom-utils.c
+++ b/web-extensions/e-dom-utils.c
@@ -1995,3 +1995,22 @@ e_dom_utils_find_document_with_uri (WebKitDOMDocument *root_document,
 
        return res_document;
 }
+
+void
+dom_element_swap_attributes (WebKitDOMElement *element,
+                             const gchar *from,
+                             const gchar *to)
+{
+       gchar *value_from, *value_to;
+
+       if (!webkit_dom_element_has_attribute (element, from) ||
+           !webkit_dom_element_has_attribute (element, to))
+               return;
+
+       value_from = webkit_dom_element_get_attribute (element, from);
+       value_to = webkit_dom_element_get_attribute (element, to);
+       webkit_dom_element_set_attribute (element, to, (value_from && *value_from) ? value_from : "", NULL);
+       webkit_dom_element_set_attribute (element, from, (value_to && *value_to) ? value_to : "", NULL);
+       g_free (value_from);
+       g_free (value_to);
+}
diff --git a/web-extensions/e-dom-utils.h b/web-extensions/e-dom-utils.h
index 218e323..3ec289d 100644
--- a/web-extensions/e-dom-utils.h
+++ b/web-extensions/e-dom-utils.h
@@ -131,46 +131,38 @@ void              remove_node                     (WebKitDOMNode *node);
 void           remove_node_if_empty            (WebKitDOMNode *node);
 WebKitDOMNode *        split_list_into_two             (WebKitDOMNode *item,
                                                 gint level);
-
 WebKitDOMElement *
                dom_create_selection_marker     (WebKitDOMDocument *document,
                                                 gboolean start);
-
 void           dom_add_selection_markers_into_element_start
                                                (WebKitDOMDocument *document,
                                                 WebKitDOMElement *element,
                                                 WebKitDOMElement **selection_start_marker,
                                                 WebKitDOMElement **selection_end_marker);
-
 void           dom_add_selection_markers_into_element_end
                                                (WebKitDOMDocument *document,
                                                 WebKitDOMElement *element,
                                                 WebKitDOMElement **selection_start_marker,
                                                 WebKitDOMElement **selection_end_marker);
-
 void           dom_remove_selection_markers    (WebKitDOMDocument *document);
-
 gboolean       node_is_list                    (WebKitDOMNode *node);
-
 gboolean       node_is_list_or_item            (WebKitDOMNode *node);
-
 EContentEditorBlockFormat
                dom_get_list_format_from_node   (WebKitDOMNode *node);
-
 void           merge_list_into_list            (WebKitDOMNode *from,
                                                 WebKitDOMNode *to,
                                                 gboolean insert_before);
-
 void           merge_lists_if_possible         (WebKitDOMNode *list);
 WebKitDOMElement *
                get_parent_block_element        (WebKitDOMNode *node);
-
 gchar *                dom_get_node_inner_html         (WebKitDOMNode *node);
-
 WebKitDOMDocument *
                e_dom_utils_find_document_with_uri
                                                (WebKitDOMDocument *root_document,
                                                 const gchar *find_document_uri);
+void           dom_element_swap_attributes     (WebKitDOMElement *element,
+                                                 const gchar *from,
+                                                 const gchar *to);
 
 G_END_DECLS
 


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