diff options
Diffstat (limited to 'e-util/e-html-editor-view.c')
-rw-r--r-- | e-util/e-html-editor-view.c | 418 |
1 files changed, 341 insertions, 77 deletions
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c index 25b9bee34e..8467f12f70 100644 --- a/e-util/e-html-editor-view.c +++ b/e-util/e-html-editor-view.c @@ -83,6 +83,7 @@ struct _EHTMLEditorViewPrivate { GSettings *aliasing_settings; gboolean convertor_insert; + gboolean had_selection_before_key_press; WebKitWebView *convertor_web_view; @@ -404,6 +405,104 @@ e_html_editor_view_force_spell_check (EHTMLEditorView *view) refresh_spell_check (view, TRUE); } +static gint +get_citation_level (WebKitDOMNode *node, + gboolean set_plaintext_quoted) +{ + WebKitDOMNode *parent = node; + gint level = 0; + + while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) { + if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent) && + webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (parent), "type")) { + level++; + + if (set_plaintext_quoted) { + element_add_class ( + WEBKIT_DOM_ELEMENT (parent), + "-x-evo-plaintext-quoted"); + } + } + + parent = webkit_dom_node_get_parent_node (parent); + } + + return level; +} + +static WebKitDOMElement * +insert_new_line_into_citation (EHTMLEditorView *view, + const gchar *html_to_insert) +{ + gboolean html_mode, ret_val; + EHTMLEditorSelection *selection; + WebKitDOMDocument *document; + WebKitDOMElement *element, *paragraph = NULL; + WebKitDOMNode *caret; + + html_mode = e_html_editor_view_get_html_mode (view); + selection = e_html_editor_view_get_selection (view); + + ret_val = e_html_editor_view_exec_command ( + view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT, NULL); + + if (!ret_val) + return NULL; + + document = webkit_web_view_get_dom_document ( + WEBKIT_WEB_VIEW (view)); + + element = webkit_dom_document_query_selector ( + document, "body>br", NULL); + + if (!element) + return NULL; + + if (!html_mode) { + WebKitDOMNode *next_sibling; + + next_sibling = webkit_dom_node_get_next_sibling ( + WEBKIT_DOM_NODE (element)); + + if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling)) { + e_html_editor_view_quote_plain_text_element ( + view, WEBKIT_DOM_ELEMENT (next_sibling)); + + e_html_editor_view_force_spell_check (view); + } + } + + caret = e_html_editor_selection_get_caret_position_node (document); + + paragraph = e_html_editor_selection_get_paragraph_element ( + selection, document, -1, 0); + + if (html_to_insert && *html_to_insert) + webkit_dom_html_element_set_inner_html ( + WEBKIT_DOM_HTML_ELEMENT (paragraph), + html_to_insert, + NULL); + else + webkit_dom_html_element_set_inner_text ( + WEBKIT_DOM_HTML_ELEMENT (paragraph), + UNICODE_ZERO_WIDTH_SPACE, + NULL); + + webkit_dom_node_append_child (WEBKIT_DOM_NODE (paragraph), caret, NULL); + + webkit_dom_node_insert_before ( + webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)), + WEBKIT_DOM_NODE (paragraph), + WEBKIT_DOM_NODE (element), + NULL); + + remove_node (WEBKIT_DOM_NODE (element)); + + e_html_editor_selection_restore_caret_position (selection); + + return paragraph; +} + static void body_input_event_cb (WebKitDOMElement *element, WebKitDOMEvent *event, @@ -501,6 +600,128 @@ body_input_event_cb (WebKitDOMElement *element, e_html_editor_view_get_selection (view)); } } + + /* Writing into quoted content */ + if (!view->priv->html_mode && !view->priv->had_selection_before_key_press) { + gint citation_level, length, word_wrap_length; + EHTMLEditorSelection *selection; + WebKitDOMElement *element; + WebKitDOMDocument *document; + WebKitDOMNode *parent; + + document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); + + selection = e_html_editor_view_get_selection (view); + word_wrap_length = e_html_editor_selection_get_word_wrap_length (selection); + + element = webkit_dom_document_query_selector ( + document, "span#-x-evo-selection-start-marker", NULL); + if (element) + return; + + e_html_editor_selection_save (selection); + element = webkit_dom_document_query_selector ( + document, "span#-x-evo-selection-start-marker", NULL); + + /* If the selection was not saved, move it into the first child of body */ + if (!element) { + WebKitDOMHTMLElement *body; + + body = webkit_dom_document_get_body (document); + element = webkit_dom_document_create_element ( + document, "SPAN", NULL); + webkit_dom_element_set_id ( + element, "-x-evo-selection-end-marker"); + webkit_dom_node_insert_before ( + webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)), + WEBKIT_DOM_NODE (element), + webkit_dom_node_get_first_child ( + webkit_dom_node_get_first_child ( + WEBKIT_DOM_NODE (body))), + NULL); + element = webkit_dom_document_create_element ( + document, "SPAN", NULL); + webkit_dom_element_set_id ( + element, "-x-evo-selection-start-marker"); + webkit_dom_node_insert_before ( + webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)), + WEBKIT_DOM_NODE (element), + webkit_dom_node_get_first_child ( + webkit_dom_node_get_first_child ( + WEBKIT_DOM_NODE (body))), + NULL); + } + + /* We have to process elements only inside normal block */ + parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)); + if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (parent)) { + e_html_editor_selection_restore (selection); + return; + } + + citation_level = get_citation_level (WEBKIT_DOM_NODE (element), FALSE); + length = word_wrap_length - 2 * citation_level; + + if (element && citation_level > 0) { + WebKitDOMElement *block; + gboolean remove_quoting = FALSE; + + block = webkit_dom_node_get_parent_element ( + WEBKIT_DOM_NODE (element)); + if (webkit_dom_element_query_selector ( + WEBKIT_DOM_ELEMENT (block), ".-x-evo-quoted", NULL)) { + WebKitDOMNode *prev_sibling; + WebKitDOMElement *selection_end_marker; + + selection_end_marker = webkit_dom_document_query_selector ( + document, "span#-x-evo-selection-end-marker", NULL); + prev_sibling = webkit_dom_node_get_previous_sibling ( + WEBKIT_DOM_NODE (selection_end_marker)); + + if (WEBKIT_DOM_IS_ELEMENT (prev_sibling)) + remove_quoting = element_has_class ( + WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-quoted"); + } + + if (element_has_class (block, "-x-evo-temp-text-wrapper")) + block = webkit_dom_node_get_parent_element ( + WEBKIT_DOM_NODE (block)); + + /* Wrap and quote the line */ + if (!remove_quoting) { + remove_quoting_from_element (block); + + block = e_html_editor_selection_wrap_paragraph_length ( + selection, block, length); + webkit_dom_node_normalize (WEBKIT_DOM_NODE (block)); + block = e_html_editor_view_quote_plain_text_element (view, block); + element = webkit_dom_document_query_selector ( + document, "span#-x-evo-selection-start-marker", NULL); + if (!element) { + WebKitDOMElement *marker; + + marker = webkit_dom_document_create_element ( + document, "SPAN", NULL); + webkit_dom_element_set_id ( + marker, "-x-evo-selection-start-marker"); + webkit_dom_node_append_child ( + WEBKIT_DOM_NODE (block), + WEBKIT_DOM_NODE (marker), + NULL); + marker = webkit_dom_document_create_element ( + document, "SPAN", NULL); + webkit_dom_element_set_id ( + marker, "-x-evo-selection-end-marker"); + webkit_dom_node_append_child ( + WEBKIT_DOM_NODE (block), + WEBKIT_DOM_NODE (marker), + NULL); + } + } + e_html_editor_view_force_spell_check (view); + } + e_html_editor_selection_restore (selection); + } } static void @@ -1713,56 +1934,6 @@ html_editor_view_button_release_event (GtkWidget *widget, } static gboolean -insert_new_line_into_citation (EHTMLEditorView *view) -{ - EHTMLEditorSelection *selection; - gboolean html_mode, ret_val; - - html_mode = e_html_editor_view_get_html_mode (view); - selection = e_html_editor_view_get_selection (view); - - ret_val = e_html_editor_view_exec_command ( - view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT, NULL); - - if (ret_val && !html_mode) { - WebKitDOMElement *element; - WebKitDOMDocument *document; - WebKitDOMNode *next_sibling; - - document = webkit_web_view_get_dom_document ( - WEBKIT_WEB_VIEW (view)); - - element = webkit_dom_document_query_selector ( - document, "body>br", NULL); - - next_sibling = webkit_dom_node_get_next_sibling ( - WEBKIT_DOM_NODE (element)); - - if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling)) { - /* Quote content */ - next_sibling = WEBKIT_DOM_NODE ( - e_html_editor_view_quote_plain_text_element ( - view, WEBKIT_DOM_ELEMENT (next_sibling))); - /* Renew spellcheck */ - e_html_editor_view_force_spell_check (view); - /* Insert caret node on right position */ - webkit_dom_node_insert_before ( - webkit_dom_node_get_parent_node ( - WEBKIT_DOM_NODE (element)), - e_html_editor_selection_get_caret_position_node ( - document), - WEBKIT_DOM_NODE (element), - NULL); - /* Restore caret position */ - e_html_editor_selection_restore_caret_position ( - selection); - } - } - - return ret_val; -} - -static gboolean prevent_from_deleting_last_element_in_body (EHTMLEditorView *view) { gboolean ret_val = FALSE; @@ -1793,6 +1964,101 @@ prevent_from_deleting_last_element_in_body (EHTMLEditorView *view) } static gboolean +change_quoted_block_to_normal (EHTMLEditorView *view) +{ + gint citation_level, success = FALSE; + WebKitDOMDocument *document; + WebKitDOMElement *selection_start_marker, *selection_end_marker, *block; + + document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); + + selection_start_marker = webkit_dom_document_query_selector ( + document, "span#-x-evo-selection-start-marker", NULL); + selection_end_marker = webkit_dom_document_query_selector ( + document, "span#-x-evo-selection-end-marker", NULL); + + if (!selection_start_marker || !selection_end_marker) + return FALSE; + + block = webkit_dom_node_get_parent_element ( + WEBKIT_DOM_NODE (selection_start_marker)); + + citation_level = get_citation_level ( + WEBKIT_DOM_NODE (selection_start_marker), FALSE); + + if (selection_start_marker && citation_level > 0) { + if (element_has_class (block, "-x-evo-temp-text-wrapper")) + block = webkit_dom_node_get_parent_element ( + WEBKIT_DOM_NODE (block)); + + if (webkit_dom_element_query_selector ( + WEBKIT_DOM_ELEMENT (block), ".-x-evo-quoted", NULL)) { + + WebKitDOMNode *prev_sibling; + + webkit_dom_node_normalize (WEBKIT_DOM_NODE (block)); + + prev_sibling = webkit_dom_node_get_previous_sibling ( + WEBKIT_DOM_NODE (selection_end_marker)); + + if (WEBKIT_DOM_IS_ELEMENT (prev_sibling)) + success = element_has_class ( + WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-quoted"); + } + + if (view->priv->html_mode) + success = WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT ( + webkit_dom_node_get_parent_element ( + WEBKIT_DOM_NODE (block))); + + if (success) { + gchar *inner_html; + WebKitDOMElement *paragraph; + + inner_html = webkit_dom_html_element_get_inner_html ( + WEBKIT_DOM_HTML_ELEMENT (block)); + webkit_dom_element_set_id ( + WEBKIT_DOM_ELEMENT (block), "-x-evo-to-remove"); + + paragraph = insert_new_line_into_citation (view, inner_html); + g_free (inner_html); + + if (view->priv->html_mode) { + webkit_dom_node_insert_before ( + WEBKIT_DOM_NODE (paragraph), + WEBKIT_DOM_NODE (selection_start_marker), + webkit_dom_node_get_first_child ( + WEBKIT_DOM_NODE (paragraph)), + NULL); + webkit_dom_node_insert_before ( + WEBKIT_DOM_NODE (paragraph), + WEBKIT_DOM_NODE (selection_end_marker), + webkit_dom_node_get_first_child ( + WEBKIT_DOM_NODE (paragraph)), + NULL); + + } + + remove_quoting_from_element (paragraph); + remove_wrapping_from_element (paragraph); + + if (block) + remove_node (WEBKIT_DOM_NODE (block)); + block = webkit_dom_document_get_element_by_id ( + document, "-x-evo-to-remove"); + if (block) + remove_node (WEBKIT_DOM_NODE (block)); + remove_node_if_empty ( + webkit_dom_node_get_next_sibling ( + WEBKIT_DOM_NODE (paragraph))); + e_html_editor_view_force_spell_check (view); + } + } + + return success; +} + +static gboolean html_editor_view_key_press_event (GtkWidget *widget, GdkEventKey *event) { @@ -1816,14 +2082,27 @@ html_editor_view_key_press_event (GtkWidget *widget, * not break the citation automatically, so we need to use * the special command to do it. */ if (e_html_editor_selection_is_citation (selection)) - return insert_new_line_into_citation (view); + return (insert_new_line_into_citation (view, "")) ? TRUE : FALSE; } - /* BackSpace in indented block decrease indent level by one */ if (event->keyval == GDK_KEY_BackSpace) { EHTMLEditorSelection *selection; selection = e_html_editor_view_get_selection (view); + + /* BackSpace pressed in the beginning of quoted content changes + * format to normal and inserts text into body */ + if (g_strcmp0 (e_html_editor_selection_get_string (selection), "") == 0) { + e_html_editor_selection_save (selection); + if (change_quoted_block_to_normal (view)) { + e_html_editor_selection_restore (selection); + return TRUE; + } + e_html_editor_selection_restore (selection); + } else + view->priv->had_selection_before_key_press = TRUE; + + /* BackSpace in indented block decrease indent level by one */ if (e_html_editor_selection_is_indented (selection)) { WebKitDOMElement *caret; @@ -1942,6 +2221,8 @@ html_editor_view_key_release_event (GtkWidget *widget, range = html_editor_view_get_dom_range (view); selection = e_html_editor_view_get_selection (view); + view->priv->had_selection_before_key_press = FALSE; + document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget)); if (view->priv->magic_smileys && view->priv->html_mode) @@ -3001,6 +3282,7 @@ e_html_editor_view_init (EHTMLEditorView *view) g_free (comma_separated); + view->priv->had_selection_before_key_press = FALSE; view->priv->convertor_insert = FALSE; view->priv->convertor_web_view = @@ -3662,31 +3944,6 @@ quote_plain_text_recursive (WebKitDOMDocument *document, } } -static gint -get_citation_level (WebKitDOMNode *node, - gboolean set_plaintext_quoted) -{ - WebKitDOMNode *parent = node; - gint level = 0; - - while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) { - if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent) && - webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (parent), "type")) { - level++; - - if (set_plaintext_quoted) { - element_add_class ( - WEBKIT_DOM_ELEMENT (parent), - "-x-evo-plaintext-quoted"); - } - } - - parent = webkit_dom_node_get_parent_node (parent); - } - - return level; -} - WebKitDOMElement * e_html_editor_view_quote_plain_text_element (EHTMLEditorView *view, WebKitDOMElement *element) @@ -5955,6 +6212,13 @@ e_html_editor_view_update_fonts (EHTMLEditorView *view) " color: #737373 !important;\n" "}\n"); + g_string_append ( + stylesheet, + ".-x-evo-quoted " + "{\n" + " -webkit-user-select: none;\n" + "}\n"); + g_string_append_printf ( stylesheet, ".-x-evo-quote-character " |