aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Popela <tpopela@redhat.com>2014-06-25 21:54:38 +0800
committerTomas Popela <tpopela@redhat.com>2014-06-25 22:06:19 +0800
commitd4b8a56865843be13e7fa6b8990f8915024994e0 (patch)
treee4a4c5a7937cd7916106614a45ca92ff43173f05
parent212adecd1a7f716aa6533712c604576cd9c2df4c (diff)
downloadgsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.tar
gsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.tar.gz
gsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.tar.bz2
gsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.tar.lz
gsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.tar.xz
gsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.tar.zst
gsoc2013-evolution-d4b8a56865843be13e7fa6b8990f8915024994e0.zip
EHTMLEditorView - Fix clipboard paste into quoted content
When pasting the text from clipboard into the quoted content in the composer paste it into it and not into the body.
-rw-r--r--e-util/e-html-editor-view.c1293
1 files changed, 665 insertions, 628 deletions
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 0afd7a3f78..80c952e585 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -2653,6 +2653,626 @@ e_html_editor_view_class_init (EHTMLEditorViewClass *class)
}
static gboolean
+is_citation_node (WebKitDOMNode *node)
+{
+ char *value;
+
+ if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node))
+ return FALSE;
+
+ value = webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (node), "type");
+
+ /* citation == <blockquote type='cite'> */
+ if (g_strcmp0 (value, "cite") == 0) {
+ g_free (value);
+ return TRUE;
+ } else {
+ g_free (value);
+ return FALSE;
+ }
+}
+
+static gchar *
+get_quotation_for_level (gint quote_level)
+{
+ gint ii;
+ GString *output = g_string_new ("");
+
+ for (ii = 0; ii < quote_level; ii++) {
+ g_string_append (output, "<span class=\"-x-evo-quote-character\">");
+ g_string_append (output, QUOTE_SYMBOL);
+ g_string_append (output, " ");
+ g_string_append (output, "</span>");
+ }
+
+ return g_string_free (output, FALSE);
+}
+
+static void
+insert_quote_symbols (WebKitDOMHTMLElement *element,
+ gint quote_level,
+ gboolean skip_first,
+ gboolean insert_newline)
+{
+ gchar *text;
+ gint ii;
+ GString *output;
+ gchar *quotation;
+
+ if (!WEBKIT_DOM_IS_HTML_ELEMENT (element))
+ return;
+
+ text = webkit_dom_html_element_get_inner_html (element);
+ output = g_string_new ("");
+ quotation = get_quotation_for_level (quote_level);
+
+ if (g_strcmp0 (text, "\n") == 0) {
+ g_string_append (output, "<span class=\"-x-evo-quoted\">");
+ g_string_append (output, quotation);
+ g_string_append (output, "</span>");
+ g_string_append (output, "\n");
+ } else {
+ gchar **lines;
+
+ lines = g_strsplit (text, "\n", 0);
+
+ for (ii = 0; lines[ii]; ii++) {
+ if (ii == 0 && skip_first) {
+ if (g_strv_length (lines) == 1) {
+ g_strfreev (lines);
+ goto exit;
+ }
+ g_string_append (output, lines[ii]);
+ g_string_append (output, "\n");
+ }
+
+ g_string_append (output, "<span class=\"-x-evo-quoted\">");
+ g_string_append (output, quotation);
+ g_string_append (output, "</span>");
+
+ /* Insert line of text */
+ g_string_append (output, lines[ii]);
+ if ((ii == g_strv_length (lines) - 1) &&
+ !g_str_has_suffix (text, "\n") && !insert_newline) {
+ /* If we are on last line and node's text doesn't
+ * end with \n, don't insert it */
+ break;
+ }
+ g_string_append (output, "\n");
+ }
+
+ g_strfreev (lines);
+ }
+
+ webkit_dom_html_element_set_inner_html (element, output->str, NULL);
+ exit:
+ g_free (quotation);
+ g_free (text);
+ g_string_free (output, TRUE);
+}
+
+static void
+quote_node (WebKitDOMDocument *document,
+ WebKitDOMNode *node,
+ gint quote_level)
+{
+ gboolean skip_first = FALSE;
+ gboolean insert_newline = FALSE;
+ gboolean is_html_node = FALSE;
+ WebKitDOMElement *wrapper;
+ WebKitDOMNode *node_clone, *prev_sibling, *next_sibling;
+
+ /* Don't quote when we are not in citation */
+ if (quote_level == 0)
+ return;
+
+ if (WEBKIT_DOM_IS_COMMENT (node))
+ return;
+
+ if (WEBKIT_DOM_IS_HTML_ELEMENT (node)) {
+ insert_quote_symbols (
+ WEBKIT_DOM_HTML_ELEMENT (node), quote_level, FALSE, FALSE);
+ return;
+ }
+
+ prev_sibling = webkit_dom_node_get_previous_sibling (node);
+ next_sibling = webkit_dom_node_get_next_sibling (node);
+
+ is_html_node =
+ !WEBKIT_DOM_IS_TEXT (prev_sibling) &&
+ !WEBKIT_DOM_IS_COMMENT (prev_sibling) && (
+ WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (prev_sibling) ||
+ element_has_tag (WEBKIT_DOM_ELEMENT (prev_sibling), "b") ||
+ element_has_tag (WEBKIT_DOM_ELEMENT (prev_sibling), "i") ||
+ element_has_tag (WEBKIT_DOM_ELEMENT (prev_sibling), "u"));
+
+ if (prev_sibling && is_html_node)
+ skip_first = TRUE;
+
+ /* Skip the BR between first blockquote and pre */
+ if (quote_level == 1 && next_sibling && WEBKIT_DOM_IS_HTML_PRE_ELEMENT (next_sibling))
+ return;
+
+ if (next_sibling && WEBKIT_DOM_IS_HTMLBR_ELEMENT (next_sibling) &&
+ WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (webkit_dom_node_get_next_sibling (next_sibling))) {
+ insert_newline = TRUE;
+ }
+
+ /* Do temporary wrapper */
+ wrapper = webkit_dom_document_create_element (document, "SPAN", NULL);
+ webkit_dom_element_set_class_name (wrapper, "-x-evo-temp-text-wrapper");
+
+ node_clone = webkit_dom_node_clone_node (node, TRUE);
+
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (wrapper),
+ node_clone,
+ NULL);
+
+ insert_quote_symbols (
+ WEBKIT_DOM_HTML_ELEMENT (wrapper),
+ quote_level,
+ skip_first,
+ insert_newline);
+
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (wrapper),
+ node,
+ NULL);
+}
+
+static void
+insert_quote_symbols_before_node (WebKitDOMDocument *document,
+ WebKitDOMNode *node,
+ gint quote_level,
+ gboolean is_html_node)
+{
+ gchar *quotation;
+ WebKitDOMElement *element;
+
+ quotation = get_quotation_for_level (quote_level);
+ element = webkit_dom_document_create_element (document, "SPAN", NULL);
+ element_add_class (element, "-x-evo-quoted");
+ webkit_dom_html_element_set_inner_html (
+ WEBKIT_DOM_HTML_ELEMENT (element), quotation, NULL);
+
+ if (is_html_node) {
+ WebKitDOMElement *new_br;
+
+ new_br = webkit_dom_document_create_element (document, "br", NULL);
+ element_add_class (new_br, "-x-evo-temp-br");
+
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (new_br),
+ node,
+ NULL);
+ }
+
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ node,
+ NULL);
+
+ if (is_html_node)
+ remove_node (node);
+
+ g_free (quotation);
+}
+
+static gboolean
+element_is_selection_marker (WebKitDOMElement *element)
+{
+ gboolean is_marker = FALSE;
+
+ is_marker =
+ element_has_id (element, "-x-evo-selection-start-marker") ||
+ element_has_id (element, "-x-evo-selection-end-marker");
+
+ return is_marker;
+}
+
+static gboolean
+check_if_suppress_next_node (WebKitDOMNode *node)
+{
+ if (node && WEBKIT_DOM_IS_ELEMENT (node))
+ if (element_is_selection_marker (WEBKIT_DOM_ELEMENT (node)))
+ if (!webkit_dom_node_get_previous_sibling (node))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+quote_plain_text_recursive (WebKitDOMDocument *document,
+ WebKitDOMNode *node,
+ WebKitDOMNode *start_node,
+ gint quote_level)
+{
+ gboolean skip_node = FALSE;
+ gboolean move_next = FALSE;
+ gboolean suppress_next = FALSE;
+ gboolean is_html_node = FALSE;
+ WebKitDOMNode *next_sibling, *prev_sibling;
+
+ node = webkit_dom_node_get_first_child (node);
+
+ while (node) {
+ skip_node = FALSE;
+ move_next = FALSE;
+ is_html_node = FALSE;
+
+ if (WEBKIT_DOM_IS_COMMENT (node))
+ goto next_node;
+
+ prev_sibling = webkit_dom_node_get_previous_sibling (node);
+ next_sibling = webkit_dom_node_get_next_sibling (node);
+
+ if (WEBKIT_DOM_IS_TEXT (node)) {
+ /* Start quoting after we are in blockquote */
+ if (quote_level > 0 && !suppress_next) {
+ /* When quoting text node, we are wrappering it and
+ * afterwards replacing it with that wrapper, thus asking
+ * for next_sibling after quoting will return NULL bacause
+ * that node don't exist anymore */
+ quote_node (document, node, quote_level);
+ node = next_sibling;
+ skip_node = TRUE;
+ } else
+ suppress_next = FALSE;
+
+ goto next_node;
+ }
+
+ if (!(WEBKIT_DOM_IS_ELEMENT (node) || WEBKIT_DOM_IS_HTML_ELEMENT (node)))
+ goto next_node;
+
+ if (element_has_id (WEBKIT_DOM_ELEMENT (node), "-x-evo-caret-position")) {
+ if (quote_level > 0)
+ element_add_class (
+ WEBKIT_DOM_ELEMENT (node), "-x-evo-caret-quoting");
+
+ move_next = TRUE;
+ suppress_next = TRUE;
+ goto next_node;
+ }
+
+ if (element_is_selection_marker (WEBKIT_DOM_ELEMENT (node))) {
+ move_next = TRUE;
+ /* If there is collapsed selection in the beginning of line
+ * we cannot suppress first text that is after the end of
+ * selection */
+ suppress_next = check_if_suppress_next_node (prev_sibling);
+ goto next_node;
+ }
+
+ if (WEBKIT_DOM_IS_HTML_META_ELEMENT (node)) {
+ goto next_node;
+ }
+ if (WEBKIT_DOM_IS_HTML_STYLE_ELEMENT (node)) {
+ move_next = TRUE;
+ goto next_node;
+ }
+ if (WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (node)) {
+ move_next = TRUE;
+ goto next_node;
+ }
+
+ if (webkit_dom_element_get_child_element_count (WEBKIT_DOM_ELEMENT (node)) != 0)
+ goto with_children;
+
+ /* Even in plain text mode we can have some basic html element
+ * like anchor and others. When Forwaring e-mail as Quoted EMFormat
+ * generates header that contatains <b> tags (bold font).
+ * We have to treat these elements separately to avoid
+ * modifications of theirs inner texts */
+ is_html_node =
+ WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node) ||
+ element_has_tag (WEBKIT_DOM_ELEMENT (node), "b") ||
+ element_has_tag (WEBKIT_DOM_ELEMENT (node), "i") ||
+ element_has_tag (WEBKIT_DOM_ELEMENT (node), "u");
+
+ if (is_html_node) {
+ if (!prev_sibling)
+ insert_quote_symbols_before_node (
+ document, node, quote_level, FALSE);
+
+ if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (prev_sibling))
+ insert_quote_symbols_before_node (
+ document, prev_sibling, quote_level, TRUE);
+
+ move_next = TRUE;
+ goto next_node;
+ }
+
+ /* If element doesn't have children, we can quote it */
+ if (is_citation_node (node)) {
+ /* Citation with just text inside */
+ quote_node (document, node, quote_level + 1);
+ /* Set citation as quoted */
+ element_add_class (
+ WEBKIT_DOM_ELEMENT (node),
+ "-x-evo-plaintext-quoted");
+
+ move_next = TRUE;
+ goto next_node;
+ }
+
+ if (!WEBKIT_DOM_IS_HTMLBR_ELEMENT (node))
+ goto not_br;
+
+ if (!prev_sibling) {
+ WebKitDOMNode *parent;
+
+ parent = webkit_dom_node_get_parent_node (node);
+
+ /* BR in the beginning of the citation */
+ if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (parent))
+ insert_quote_symbols_before_node (
+ document, node, quote_level, FALSE);
+ }
+
+ if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
+ WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (next_sibling) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-temp-text-wrapper")) {
+ /* Situation when anchors are alone on line */
+ gchar *text_content;
+
+ text_content = webkit_dom_node_get_text_content (prev_sibling);
+
+ if (g_str_has_suffix (text_content, "\n")) {
+ insert_quote_symbols_before_node (
+ document, node, quote_level, FALSE);
+ remove_node (node);
+ g_free (text_content);
+ node = next_sibling;
+ skip_node = TRUE;
+ goto next_node;
+ }
+ g_free (text_content);
+ }
+
+ if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (prev_sibling)) {
+ gchar *quotation, *content;
+
+ quotation = get_quotation_for_level (quote_level);
+
+ content = g_strconcat (
+ "<span class=\"-x-evo-quoted\">",
+ quotation,
+ "</span><br class=\"-x-evo-temp-br\">",
+ NULL);
+
+ webkit_dom_html_element_set_outer_html (
+ WEBKIT_DOM_HTML_ELEMENT (node),
+ content,
+ NULL);
+
+ g_free (content);
+ g_free (quotation);
+
+ node = next_sibling;
+ skip_node = TRUE;
+ goto next_node;
+ }
+
+ if (!prev_sibling && !next_sibling) {
+ WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
+
+ if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (parent)) {
+ insert_quote_symbols_before_node (
+ document, node, quote_level, FALSE);
+ }
+ }
+
+ if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-temp-text-wrapper")) {
+ gchar *text_content;
+
+ text_content = webkit_dom_node_get_text_content (prev_sibling);
+ if (g_strcmp0 (text_content, "") == 0)
+ insert_quote_symbols_before_node (
+ document, node, quote_level, FALSE);
+
+ g_free (text_content);
+ }
+
+ if (is_citation_node (prev_sibling)) {
+ insert_quote_symbols_before_node (
+ document, node, quote_level, FALSE);
+ }
+ not_br:
+ if (g_strcmp0 (webkit_dom_node_get_text_content (node), "") == 0) {
+ move_next = TRUE;
+ goto next_node;
+ }
+
+ quote_node (document, node, quote_level);
+
+ move_next = TRUE;
+ goto next_node;
+
+ with_children:
+ if (is_citation_node (node)) {
+ /* Go deeper and increase level */
+ quote_plain_text_recursive (
+ document, node, start_node, quote_level + 1);
+ /* set citation as quoted */
+ element_add_class (
+ WEBKIT_DOM_ELEMENT (node),
+ "-x-evo-plaintext-quoted");
+ move_next = TRUE;
+ } else {
+ quote_plain_text_recursive (
+ document, node, start_node, quote_level);
+ move_next = TRUE;
+ }
+ next_node:
+ if (!skip_node) {
+ /* Move to next node */
+ if (!move_next && webkit_dom_node_has_child_nodes (node)) {
+ node = webkit_dom_node_get_first_child (node);
+ } else if (webkit_dom_node_get_next_sibling (node)) {
+ node = webkit_dom_node_get_next_sibling (node);
+ } else {
+ return;
+ }
+ }
+ }
+}
+
+WebKitDOMElement *
+e_html_editor_view_quote_plain_text_element (EHTMLEditorView *view,
+ WebKitDOMElement *element)
+{
+ WebKitDOMDocument *document;
+ WebKitDOMNode *element_clone;
+ WebKitDOMNodeList *list;
+ gint ii, length, level;
+
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+
+ element_clone = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (element), TRUE);
+ level = get_citation_level (WEBKIT_DOM_NODE (element), TRUE);
+
+ /* Remove old quote characters if the exists */
+ list = webkit_dom_element_query_selector_all (
+ WEBKIT_DOM_ELEMENT (element_clone), "span.-x-evo-quoted", NULL);
+ length = webkit_dom_node_list_get_length (list);
+ for (ii = 0; ii < length; ii++)
+ remove_node (webkit_dom_node_list_item (list, ii));
+
+ quote_plain_text_recursive (
+ document, element_clone, element_clone, level);
+
+ /* Replace old element with one, that is quoted */
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ element_clone,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ return WEBKIT_DOM_ELEMENT (element_clone);
+}
+
+/**
+ * e_html_editor_view_quote_plain_text:
+ * @view: an #EHTMLEditorView
+ *
+ * Quote text inside citation blockquotes in plain text mode.
+ *
+ * As this function is cloning and replacing all citation blockquotes keep on
+ * mind that any pointers to nodes inside these blockquotes will be invalidated.
+ */
+WebKitDOMElement *
+e_html_editor_view_quote_plain_text (EHTMLEditorView *view)
+{
+ WebKitDOMDocument *document;
+ WebKitDOMHTMLElement *body;
+ WebKitDOMNode *body_clone;
+ WebKitDOMNamedNodeMap *attributes;
+ WebKitDOMNodeList *list;
+ WebKitDOMElement *element;
+ gint ii, length;
+ gulong attributes_length;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+
+ /* Check if the document is already quoted */
+ element = webkit_dom_document_query_selector (
+ document, ".-x-evo-plaintext-quoted", NULL);
+ if (element)
+ return NULL;
+
+ body = webkit_dom_document_get_body (document);
+ body_clone = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (body), TRUE);
+
+ /* Clean unwanted spaces before and after blockquotes */
+ list = webkit_dom_element_query_selector_all (
+ WEBKIT_DOM_ELEMENT (body_clone), "blockquote[type|=cite]", NULL);
+ length = webkit_dom_node_list_get_length (list);
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMNode *blockquote = webkit_dom_node_list_item (list, ii);
+ WebKitDOMNode *prev_sibling = webkit_dom_node_get_previous_sibling (blockquote);
+ WebKitDOMNode *next_sibling = webkit_dom_node_get_next_sibling (blockquote);
+
+ if (prev_sibling && WEBKIT_DOM_IS_HTMLBR_ELEMENT (prev_sibling))
+ remove_node (prev_sibling);
+
+ if (next_sibling && WEBKIT_DOM_IS_HTMLBR_ELEMENT (next_sibling))
+ remove_node (next_sibling);
+
+ if (webkit_dom_node_has_child_nodes (blockquote)) {
+ WebKitDOMNode *child = webkit_dom_node_get_first_child (blockquote);
+ if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (child))
+ remove_node (child);
+ }
+ }
+
+ quote_plain_text_recursive (document, body_clone, body_clone, 0);
+
+ /* Copy attributes */
+ attributes = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (body));
+ attributes_length = webkit_dom_named_node_map_get_length (attributes);
+ for (ii = 0; ii < attributes_length; ii++) {
+ gchar *name, *value;
+ WebKitDOMNode *node = webkit_dom_named_node_map_item (attributes, ii);
+
+ name = webkit_dom_node_get_local_name (node);
+ value = webkit_dom_node_get_node_value (node);
+
+ webkit_dom_element_set_attribute (
+ WEBKIT_DOM_ELEMENT (body_clone), name, value, NULL);
+
+ g_free (name);
+ g_free (value);
+ }
+
+ /* Replace old BODY with one, that is quoted */
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (body)),
+ body_clone,
+ WEBKIT_DOM_NODE (body),
+ NULL);
+
+ return WEBKIT_DOM_ELEMENT (body_clone);
+}
+
+/**
+ * e_html_editor_view_dequote_plain_text:
+ * @view: an #EHTMLEditorView
+ *
+ * Dequote already quoted plain text in editor.
+ * Editor have to be quoted with e_html_editor_view_quote_plain_text otherwise
+ * it's not working.
+ */
+void
+e_html_editor_view_dequote_plain_text (EHTMLEditorView *view)
+{
+ WebKitDOMDocument *document;
+ WebKitDOMNodeList *paragraphs;
+ gint length, ii;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+
+ paragraphs = webkit_dom_document_query_selector_all (
+ document, "blockquote.-x-evo-plaintext-quoted", NULL);
+ length = webkit_dom_node_list_get_length (paragraphs);
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMElement *element;
+
+ element = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (paragraphs, ii));
+
+ if (is_citation_node (WEBKIT_DOM_NODE (element))) {
+ element_remove_class (element, "-x-evo-plaintext-quoted");
+ remove_quoting_from_element (element);
+ }
+ }
+}
+
+static gboolean
create_anchor_for_link (const GMatchInfo *info,
GString *res,
gpointer data)
@@ -2695,7 +3315,6 @@ create_anchor_for_link (const GMatchInfo *info,
if (address_surrounded)
g_string_append (res, "&gt;");
- g_warning ("%s", res->str);
g_free (match);
return FALSE;
@@ -3255,9 +3874,11 @@ static void
html_editor_view_insert_converted_html_into_selection (EHTMLEditorView *view,
WebKitDOMDocument *document_convertor)
{
+ EHTMLEditorSelection *selection = e_html_editor_view_get_selection (view);
gchar *inner_text, *inner_html;
+ gint citation_level;
WebKitDOMDocument *document;
- WebKitDOMElement *element;
+ WebKitDOMElement *caret, *element;
WebKitDOMHTMLElement *convertor_body;
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
@@ -3271,20 +3892,56 @@ html_editor_view_insert_converted_html_into_selection (EHTMLEditorView *view,
inner_html = webkit_dom_html_element_get_inner_html (
WEBKIT_DOM_HTML_ELEMENT (element));
- parse_html_into_paragraphs (
- view, document, element, inner_html, FALSE);
-
+ parse_html_into_paragraphs (view, document, element, inner_html, FALSE);
g_free (inner_html);
+ caret = e_html_editor_selection_save_caret_position (selection);
+ citation_level = get_citation_level (WEBKIT_DOM_NODE (caret), FALSE);
+ /* Pasting into citation */
+ if (citation_level > 0) {
+ WebKitDOMNode *parent;
+
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (caret));
+ /* Pasting into empty line in citation */
+ if (is_citation_node (parent)) {
+ quote_plain_text_recursive (
+ document,
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (element),
+ citation_level);
+
+ webkit_dom_node_insert_before (
+ parent,
+ WEBKIT_DOM_NODE (element),
+ webkit_dom_node_get_next_sibling (
+ WEBKIT_DOM_NODE (caret)),
+ NULL);
+
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (caret),
+ NULL);
+
+ remove_node (
+ webkit_dom_node_get_next_sibling (
+ WEBKIT_DOM_NODE (element)));
+
+ e_html_editor_selection_restore_caret_position (selection);
+
+ goto out;
+ }
+ }
+
+ e_html_editor_selection_clear_caret_position_marker (selection);
+
inner_html = webkit_dom_html_element_get_inner_html (
WEBKIT_DOM_HTML_ELEMENT (element));
-
e_html_editor_view_exec_command (
view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, inner_html);
-
+ g_free (inner_html);
+ out:
e_html_editor_view_force_spell_check (view);
- g_free (inner_html);
g_free (inner_text);
}
@@ -3627,626 +4284,6 @@ e_html_editor_view_set_changed (EHTMLEditorView *view,
g_object_notify (G_OBJECT (view), "changed");
}
-static gboolean
-is_citation_node (WebKitDOMNode *node)
-{
- char *value;
-
- if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node))
- return FALSE;
-
- value = webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (node), "type");
-
- /* citation == <blockquote type='cite'> */
- if (g_strcmp0 (value, "cite") == 0) {
- g_free (value);
- return TRUE;
- } else {
- g_free (value);
- return FALSE;
- }
-}
-
-static gchar *
-get_quotation_for_level (gint quote_level)
-{
- gint ii;
- GString *output = g_string_new ("");
-
- for (ii = 0; ii < quote_level; ii++) {
- g_string_append (output, "<span class=\"-x-evo-quote-character\">");
- g_string_append (output, QUOTE_SYMBOL);
- g_string_append (output, " ");
- g_string_append (output, "</span>");
- }
-
- return g_string_free (output, FALSE);
-}
-
-static void
-insert_quote_symbols (WebKitDOMHTMLElement *element,
- gint quote_level,
- gboolean skip_first,
- gboolean insert_newline)
-{
- gchar *text;
- gint ii;
- GString *output;
- gchar *quotation;
-
- if (!WEBKIT_DOM_IS_HTML_ELEMENT (element))
- return;
-
- text = webkit_dom_html_element_get_inner_html (element);
- output = g_string_new ("");
- quotation = get_quotation_for_level (quote_level);
-
- if (g_strcmp0 (text, "\n") == 0) {
- g_string_append (output, "<span class=\"-x-evo-quoted\">");
- g_string_append (output, quotation);
- g_string_append (output, "</span>");
- g_string_append (output, "\n");
- } else {
- gchar **lines;
-
- lines = g_strsplit (text, "\n", 0);
-
- for (ii = 0; lines[ii]; ii++) {
- if (ii == 0 && skip_first) {
- if (g_strv_length (lines) == 1) {
- g_strfreev (lines);
- goto exit;
- }
- g_string_append (output, lines[ii]);
- g_string_append (output, "\n");
- }
-
- g_string_append (output, "<span class=\"-x-evo-quoted\">");
- g_string_append (output, quotation);
- g_string_append (output, "</span>");
-
- /* Insert line of text */
- g_string_append (output, lines[ii]);
- if ((ii == g_strv_length (lines) - 1) &&
- !g_str_has_suffix (text, "\n") && !insert_newline) {
- /* If we are on last line and node's text doesn't
- * end with \n, don't insert it */
- break;
- }
- g_string_append (output, "\n");
- }
-
- g_strfreev (lines);
- }
-
- webkit_dom_html_element_set_inner_html (element, output->str, NULL);
- exit:
- g_free (quotation);
- g_free (text);
- g_string_free (output, TRUE);
-}
-
-static void
-quote_node (WebKitDOMDocument *document,
- WebKitDOMNode *node,
- gint quote_level)
-{
- gboolean skip_first = FALSE;
- gboolean insert_newline = FALSE;
- gboolean is_html_node = FALSE;
- WebKitDOMElement *wrapper;
- WebKitDOMNode *node_clone, *prev_sibling, *next_sibling;
-
- /* Don't quote when we are not in citation */
- if (quote_level == 0)
- return;
-
- if (WEBKIT_DOM_IS_COMMENT (node))
- return;
-
- if (WEBKIT_DOM_IS_HTML_ELEMENT (node)) {
- insert_quote_symbols (
- WEBKIT_DOM_HTML_ELEMENT (node), quote_level, FALSE, FALSE);
- return;
- }
-
- prev_sibling = webkit_dom_node_get_previous_sibling (node);
- next_sibling = webkit_dom_node_get_next_sibling (node);
-
- is_html_node =
- !WEBKIT_DOM_IS_TEXT (prev_sibling) &&
- !WEBKIT_DOM_IS_COMMENT (prev_sibling) && (
- WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (prev_sibling) ||
- element_has_tag (WEBKIT_DOM_ELEMENT (prev_sibling), "b") ||
- element_has_tag (WEBKIT_DOM_ELEMENT (prev_sibling), "i") ||
- element_has_tag (WEBKIT_DOM_ELEMENT (prev_sibling), "u"));
-
- if (prev_sibling && is_html_node)
- skip_first = TRUE;
-
- /* Skip the BR between first blockquote and pre */
- if (quote_level == 1 && next_sibling && WEBKIT_DOM_IS_HTML_PRE_ELEMENT (next_sibling))
- return;
-
- if (next_sibling && WEBKIT_DOM_IS_HTMLBR_ELEMENT (next_sibling) &&
- WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (webkit_dom_node_get_next_sibling (next_sibling))) {
- insert_newline = TRUE;
- }
-
- /* Do temporary wrapper */
- wrapper = webkit_dom_document_create_element (document, "SPAN", NULL);
- webkit_dom_element_set_class_name (wrapper, "-x-evo-temp-text-wrapper");
-
- node_clone = webkit_dom_node_clone_node (node, TRUE);
-
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (wrapper),
- node_clone,
- NULL);
-
- insert_quote_symbols (
- WEBKIT_DOM_HTML_ELEMENT (wrapper),
- quote_level,
- skip_first,
- insert_newline);
-
- webkit_dom_node_replace_child (
- webkit_dom_node_get_parent_node (node),
- WEBKIT_DOM_NODE (wrapper),
- node,
- NULL);
-}
-
-static void
-insert_quote_symbols_before_node (WebKitDOMDocument *document,
- WebKitDOMNode *node,
- gint quote_level,
- gboolean is_html_node)
-{
- gchar *quotation;
- WebKitDOMElement *element;
-
- quotation = get_quotation_for_level (quote_level);
- element = webkit_dom_document_create_element (document, "SPAN", NULL);
- element_add_class (element, "-x-evo-quoted");
- webkit_dom_html_element_set_inner_html (
- WEBKIT_DOM_HTML_ELEMENT (element), quotation, NULL);
-
- if (is_html_node) {
- WebKitDOMElement *new_br;
-
- new_br = webkit_dom_document_create_element (document, "br", NULL);
- element_add_class (new_br, "-x-evo-temp-br");
-
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (node),
- WEBKIT_DOM_NODE (new_br),
- node,
- NULL);
- }
-
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (node),
- WEBKIT_DOM_NODE (element),
- node,
- NULL);
-
- if (is_html_node)
- remove_node (node);
-
- g_free (quotation);
-}
-
-static gboolean
-element_is_selection_marker (WebKitDOMElement *element)
-{
- gboolean is_marker = FALSE;
-
- is_marker =
- element_has_id (element, "-x-evo-selection-start-marker") ||
- element_has_id (element, "-x-evo-selection-end-marker");
-
- return is_marker;
-}
-
-static gboolean
-check_if_suppress_next_node (WebKitDOMNode *node)
-{
- if (node && WEBKIT_DOM_IS_ELEMENT (node))
- if (element_is_selection_marker (WEBKIT_DOM_ELEMENT (node)))
- if (!webkit_dom_node_get_previous_sibling (node))
- return FALSE;
-
- return TRUE;
-}
-
-static void
-quote_plain_text_recursive (WebKitDOMDocument *document,
- WebKitDOMNode *node,
- WebKitDOMNode *start_node,
- gint quote_level)
-{
- gboolean skip_node = FALSE;
- gboolean move_next = FALSE;
- gboolean suppress_next = FALSE;
- gboolean is_html_node = FALSE;
- WebKitDOMNode *next_sibling, *prev_sibling;
-
- node = webkit_dom_node_get_first_child (node);
-
- while (node) {
- skip_node = FALSE;
- move_next = FALSE;
- is_html_node = FALSE;
-
- if (WEBKIT_DOM_IS_COMMENT (node))
- goto next_node;
-
- prev_sibling = webkit_dom_node_get_previous_sibling (node);
- next_sibling = webkit_dom_node_get_next_sibling (node);
-
- if (WEBKIT_DOM_IS_TEXT (node)) {
- /* Start quoting after we are in blockquote */
- if (quote_level > 0 && !suppress_next) {
- /* When quoting text node, we are wrappering it and
- * afterwards replacing it with that wrapper, thus asking
- * for next_sibling after quoting will return NULL bacause
- * that node don't exist anymore */
- quote_node (document, node, quote_level);
- node = next_sibling;
- skip_node = TRUE;
- } else
- suppress_next = FALSE;
-
- goto next_node;
- }
-
- if (!(WEBKIT_DOM_IS_ELEMENT (node) || WEBKIT_DOM_IS_HTML_ELEMENT (node)))
- goto next_node;
-
- if (element_has_id (WEBKIT_DOM_ELEMENT (node), "-x-evo-caret-position")) {
- if (quote_level > 0)
- element_add_class (
- WEBKIT_DOM_ELEMENT (node), "-x-evo-caret-quoting");
-
- move_next = TRUE;
- suppress_next = TRUE;
- goto next_node;
- }
-
- if (element_is_selection_marker (WEBKIT_DOM_ELEMENT (node))) {
- move_next = TRUE;
- /* If there is collapsed selection in the beginning of line
- * we cannot suppress first text that is after the end of
- * selection */
- suppress_next = check_if_suppress_next_node (prev_sibling);
- goto next_node;
- }
-
- if (WEBKIT_DOM_IS_HTML_META_ELEMENT (node)) {
- goto next_node;
- }
- if (WEBKIT_DOM_IS_HTML_STYLE_ELEMENT (node)) {
- move_next = TRUE;
- goto next_node;
- }
- if (WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (node)) {
- move_next = TRUE;
- goto next_node;
- }
-
- if (webkit_dom_element_get_child_element_count (WEBKIT_DOM_ELEMENT (node)) != 0)
- goto with_children;
-
- /* Even in plain text mode we can have some basic html element
- * like anchor and others. When Forwaring e-mail as Quoted EMFormat
- * generates header that contatains <b> tags (bold font).
- * We have to treat these elements separately to avoid
- * modifications of theirs inner texts */
- is_html_node =
- WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node) ||
- element_has_tag (WEBKIT_DOM_ELEMENT (node), "b") ||
- element_has_tag (WEBKIT_DOM_ELEMENT (node), "i") ||
- element_has_tag (WEBKIT_DOM_ELEMENT (node), "u");
-
- if (is_html_node) {
- if (!prev_sibling)
- insert_quote_symbols_before_node (
- document, node, quote_level, FALSE);
-
- if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (prev_sibling))
- insert_quote_symbols_before_node (
- document, prev_sibling, quote_level, TRUE);
-
- move_next = TRUE;
- goto next_node;
- }
-
- /* If element doesn't have children, we can quote it */
- if (is_citation_node (node)) {
- /* Citation with just text inside */
- quote_node (document, node, quote_level + 1);
- /* Set citation as quoted */
- element_add_class (
- WEBKIT_DOM_ELEMENT (node),
- "-x-evo-plaintext-quoted");
-
- move_next = TRUE;
- goto next_node;
- }
-
- if (!WEBKIT_DOM_IS_HTMLBR_ELEMENT (node))
- goto not_br;
-
- if (!prev_sibling) {
- WebKitDOMNode *parent;
-
- parent = webkit_dom_node_get_parent_node (node);
-
- /* BR in the beginning of the citation */
- if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (parent))
- insert_quote_symbols_before_node (
- document, node, quote_level, FALSE);
- }
-
- if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
- WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (next_sibling) &&
- element_has_class (WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-temp-text-wrapper")) {
- /* Situation when anchors are alone on line */
- gchar *text_content;
-
- text_content = webkit_dom_node_get_text_content (prev_sibling);
-
- if (g_str_has_suffix (text_content, "\n")) {
- insert_quote_symbols_before_node (
- document, node, quote_level, FALSE);
- remove_node (node);
- g_free (text_content);
- node = next_sibling;
- skip_node = TRUE;
- goto next_node;
- }
- g_free (text_content);
- }
-
- if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (prev_sibling)) {
- gchar *quotation, *content;
-
- quotation = get_quotation_for_level (quote_level);
-
- content = g_strconcat (
- "<span class=\"-x-evo-quoted\">",
- quotation,
- "</span><br class=\"-x-evo-temp-br\">",
- NULL);
-
- webkit_dom_html_element_set_outer_html (
- WEBKIT_DOM_HTML_ELEMENT (node),
- content,
- NULL);
-
- g_free (content);
- g_free (quotation);
-
- node = next_sibling;
- skip_node = TRUE;
- goto next_node;
- }
-
- if (!prev_sibling && !next_sibling) {
- WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
-
- if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (parent)) {
- insert_quote_symbols_before_node (
- document, node, quote_level, FALSE);
- }
- }
-
- if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
- element_has_class (WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-temp-text-wrapper")) {
- gchar *text_content;
-
- text_content = webkit_dom_node_get_text_content (prev_sibling);
- if (g_strcmp0 (text_content, "") == 0)
- insert_quote_symbols_before_node (
- document, node, quote_level, FALSE);
-
- g_free (text_content);
- }
-
- if (is_citation_node (prev_sibling)) {
- insert_quote_symbols_before_node (
- document, node, quote_level, FALSE);
- }
- not_br:
- if (g_strcmp0 (webkit_dom_node_get_text_content (node), "") == 0) {
- move_next = TRUE;
- goto next_node;
- }
-
- quote_node (document, node, quote_level);
-
- move_next = TRUE;
- goto next_node;
-
- with_children:
- if (is_citation_node (node)) {
- /* Go deeper and increase level */
- quote_plain_text_recursive (
- document, node, start_node, quote_level + 1);
- /* set citation as quoted */
- element_add_class (
- WEBKIT_DOM_ELEMENT (node),
- "-x-evo-plaintext-quoted");
- move_next = TRUE;
- } else {
- quote_plain_text_recursive (
- document, node, start_node, quote_level);
- move_next = TRUE;
- }
- next_node:
- if (!skip_node) {
- /* Move to next node */
- if (!move_next && webkit_dom_node_has_child_nodes (node)) {
- node = webkit_dom_node_get_first_child (node);
- } else if (webkit_dom_node_get_next_sibling (node)) {
- node = webkit_dom_node_get_next_sibling (node);
- } else {
- return;
- }
- }
- }
-}
-
-WebKitDOMElement *
-e_html_editor_view_quote_plain_text_element (EHTMLEditorView *view,
- WebKitDOMElement *element)
-{
- WebKitDOMDocument *document;
- WebKitDOMNode *element_clone;
- WebKitDOMNodeList *list;
- gint ii, length, level;
-
- document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
-
- element_clone = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (element), TRUE);
- level = get_citation_level (WEBKIT_DOM_NODE (element), TRUE);
-
- /* Remove old quote characters if the exists */
- list = webkit_dom_element_query_selector_all (
- WEBKIT_DOM_ELEMENT (element_clone), "span.-x-evo-quoted", NULL);
- length = webkit_dom_node_list_get_length (list);
- for (ii = 0; ii < length; ii++)
- remove_node (webkit_dom_node_list_item (list, ii));
-
- quote_plain_text_recursive (
- document, element_clone, element_clone, level);
-
- /* Replace old element with one, that is quoted */
- webkit_dom_node_replace_child (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
- element_clone,
- WEBKIT_DOM_NODE (element),
- NULL);
-
- return WEBKIT_DOM_ELEMENT (element_clone);
-}
-
-/**
- * e_html_editor_view_quote_plain_text:
- * @view: an #EHTMLEditorView
- *
- * Quote text inside citation blockquotes in plain text mode.
- *
- * As this function is cloning and replacing all citation blockquotes keep on
- * mind that any pointers to nodes inside these blockquotes will be invalidated.
- */
-WebKitDOMElement *
-e_html_editor_view_quote_plain_text (EHTMLEditorView *view)
-{
- WebKitDOMDocument *document;
- WebKitDOMHTMLElement *body;
- WebKitDOMNode *body_clone;
- WebKitDOMNamedNodeMap *attributes;
- WebKitDOMNodeList *list;
- WebKitDOMElement *element;
- gint ii, length;
- gulong attributes_length;
-
- document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
-
- /* Check if the document is already quoted */
- element = webkit_dom_document_query_selector (
- document, ".-x-evo-plaintext-quoted", NULL);
- if (element)
- return NULL;
-
- body = webkit_dom_document_get_body (document);
- body_clone = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (body), TRUE);
-
- /* Clean unwanted spaces before and after blockquotes */
- list = webkit_dom_element_query_selector_all (
- WEBKIT_DOM_ELEMENT (body_clone), "blockquote[type|=cite]", NULL);
- length = webkit_dom_node_list_get_length (list);
- for (ii = 0; ii < length; ii++) {
- WebKitDOMNode *blockquote = webkit_dom_node_list_item (list, ii);
- WebKitDOMNode *prev_sibling = webkit_dom_node_get_previous_sibling (blockquote);
- WebKitDOMNode *next_sibling = webkit_dom_node_get_next_sibling (blockquote);
-
- if (prev_sibling && WEBKIT_DOM_IS_HTMLBR_ELEMENT (prev_sibling))
- remove_node (prev_sibling);
-
- if (next_sibling && WEBKIT_DOM_IS_HTMLBR_ELEMENT (next_sibling))
- remove_node (next_sibling);
-
- if (webkit_dom_node_has_child_nodes (blockquote)) {
- WebKitDOMNode *child = webkit_dom_node_get_first_child (blockquote);
- if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (child))
- remove_node (child);
- }
- }
-
- quote_plain_text_recursive (document, body_clone, body_clone, 0);
-
- /* Copy attributes */
- attributes = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (body));
- attributes_length = webkit_dom_named_node_map_get_length (attributes);
- for (ii = 0; ii < attributes_length; ii++) {
- gchar *name, *value;
- WebKitDOMNode *node = webkit_dom_named_node_map_item (attributes, ii);
-
- name = webkit_dom_node_get_local_name (node);
- value = webkit_dom_node_get_node_value (node);
-
- webkit_dom_element_set_attribute (
- WEBKIT_DOM_ELEMENT (body_clone), name, value, NULL);
-
- g_free (name);
- g_free (value);
- }
-
- /* Replace old BODY with one, that is quoted */
- webkit_dom_node_replace_child (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (body)),
- body_clone,
- WEBKIT_DOM_NODE (body),
- NULL);
-
- return WEBKIT_DOM_ELEMENT (body_clone);
-}
-
-/**
- * e_html_editor_view_dequote_plain_text:
- * @view: an #EHTMLEditorView
- *
- * Dequote already quoted plain text in editor.
- * Editor have to be quoted with e_html_editor_view_quote_plain_text otherwise
- * it's not working.
- */
-void
-e_html_editor_view_dequote_plain_text (EHTMLEditorView *view)
-{
- WebKitDOMDocument *document;
- WebKitDOMNodeList *paragraphs;
- gint length, ii;
-
- document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
-
- paragraphs = webkit_dom_document_query_selector_all (
- document, "blockquote.-x-evo-plaintext-quoted", NULL);
- length = webkit_dom_node_list_get_length (paragraphs);
- for (ii = 0; ii < length; ii++) {
- WebKitDOMElement *element;
-
- element = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (paragraphs, ii));
-
- if (is_citation_node (WEBKIT_DOM_NODE (element))) {
- element_remove_class (element, "-x-evo-plaintext-quoted");
- remove_quoting_from_element (element);
- }
- }
-}
-
/**
* e_html_editor_view_get_html_mode:
* @view: an #EHTMLEditorView