[evolution/wip/webkit2] EHTMLEditorView - Improve the undo/redo in composer
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/webkit2] EHTMLEditorView - Improve the undo/redo in composer
- Date: Tue, 1 Mar 2016 19:01:09 +0000 (UTC)
commit ed658ea80cb9768994640c4bc391d2840b33c69f
Author: Tomas Popela <tpopela redhat com>
Date: Tue Mar 1 20:00:39 2016 +0100
EHTMLEditorView - Improve the undo/redo in composer
.../e-html-editor-selection-dom-functions.c | 12 +-
.../composer/e-html-editor-undo-redo-manager.c | 498 +++++--
.../composer/e-html-editor-view-dom-functions.c | 1543 +++++++++++++-------
.../composer/e-html-editor-view-dom-functions.h | 31 +-
.../composer/e-html-editor-web-extension.c | 15 +
.../composer/e-html-editor-web-extension.h | 5 +
6 files changed, 1452 insertions(+), 652 deletions(-)
---
diff --git a/web-extensions/composer/e-html-editor-selection-dom-functions.c
b/web-extensions/composer/e-html-editor-selection-dom-functions.c
index fea1d67..096e9b6 100644
--- a/web-extensions/composer/e-html-editor-selection-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-selection-dom-functions.c
@@ -2904,7 +2904,7 @@ dom_put_node_into_paragraph (WebKitDOMDocument *document,
}
static gint
-get_citation_level (WebKitDOMNode *node)
+selection_get_citation_level (WebKitDOMNode *node)
{
WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
gint level = 0;
@@ -3023,7 +3023,7 @@ dom_selection_wrap (WebKitDOMDocument *document,
after_selection_end = webkit_dom_node_contains (
block, WEBKIT_DOM_NODE (selection_end_marker));
- citation_level = get_citation_level (block);
+ citation_level = selection_get_citation_level (block);
quote = citation_level ? citation_level * 2 : 0;
wrapped_paragraph = dom_wrap_paragraph_length (
@@ -3069,7 +3069,7 @@ dom_wrap_paragraphs_in_document (WebKitDOMDocument *document,
gint word_wrap_length, quote, citation_level;
WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);
- citation_level = get_citation_level (node);
+ citation_level = selection_get_citation_level (node);
quote = citation_level ? citation_level * 2 : 0;
word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
@@ -3101,7 +3101,7 @@ dom_wrap_paragraph (WebKitDOMDocument *document,
g_return_val_if_fail (WEBKIT_DOM_IS_ELEMENT (paragraph), NULL);
indentation_level = get_indentation_level (paragraph);
- citation_level = get_citation_level (WEBKIT_DOM_NODE (paragraph));
+ citation_level = selection_get_citation_level (WEBKIT_DOM_NODE (paragraph));
if (node_is_list_or_item (WEBKIT_DOM_NODE (paragraph))) {
gint list_level = get_list_level (WEBKIT_DOM_NODE (paragraph));
@@ -4999,7 +4999,7 @@ process_block_to_block (WebKitDOMDocument *document,
if (!next_block && !after_selection_end) {
gint citation_level;
- citation_level = get_citation_level (WEBKIT_DOM_NODE (element));
+ citation_level = selection_get_citation_level (WEBKIT_DOM_NODE (element));
if (citation_level > 0) {
next_block = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
@@ -5017,7 +5017,7 @@ process_block_to_block (WebKitDOMDocument *document,
if (format == E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_BLOCKQUOTE)
citation_level = 1;
else
- citation_level = get_citation_level (WEBKIT_DOM_NODE (element));
+ citation_level = selection_get_citation_level (WEBKIT_DOM_NODE (element));
if (citation_level > 0) {
gint quote, word_wrap_length;
diff --git a/web-extensions/composer/e-html-editor-undo-redo-manager.c
b/web-extensions/composer/e-html-editor-undo-redo-manager.c
index d118fd6..dd8dc88 100644
--- a/web-extensions/composer/e-html-editor-undo-redo-manager.c
+++ b/web-extensions/composer/e-html-editor-undo-redo-manager.c
@@ -327,6 +327,70 @@ event_selection_was_collapsed (EHTMLEditorHistoryEvent *ev)
return (ev->before.start.x == ev->before.end.x) && (ev->before.start.y == ev->before.end.y);
}
+static WebKitDOMNode *
+split_node_into_two (WebKitDOMNode *item,
+ gint level)
+{
+ gint current_level = 1;
+ WebKitDOMDocument *document;
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMNode *parent, *prev_parent = NULL, *tmp = NULL;
+
+ document = webkit_dom_node_get_owner_document (item);
+ fragment = webkit_dom_document_create_document_fragment (document);
+
+ tmp = item;
+ parent = webkit_dom_node_get_parent_node (item);
+ while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+ WebKitDOMNode *clone, *first_child, *insert_before = NULL, *sibling;
+
+ first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+ clone = webkit_dom_node_clone_node (parent, FALSE);
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (fragment), clone, first_child, NULL);
+
+ if (first_child)
+ insert_before = webkit_dom_node_get_first_child (first_child);
+
+ while (first_child && (sibling = webkit_dom_node_get_next_sibling (first_child)))
+ webkit_dom_node_insert_before (first_child, sibling, insert_before, NULL);
+
+ while ((sibling = webkit_dom_node_get_next_sibling (tmp)))
+ webkit_dom_node_append_child (clone, sibling, NULL);
+
+ webkit_dom_node_insert_before (
+ clone, tmp, webkit_dom_node_get_first_child (clone), NULL);
+
+ prev_parent = parent;
+ tmp = webkit_dom_node_get_next_sibling (parent);
+ parent = webkit_dom_node_get_parent_node (parent);
+ if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+ first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+ insert_before = webkit_dom_node_get_first_child (first_child);
+ while (first_child && (sibling = webkit_dom_node_get_next_sibling (first_child))) {
+ webkit_dom_node_insert_before (
+ first_child, sibling, insert_before, NULL);
+ }
+ }
+
+ if (current_level >= level && level >= 0)
+ break;
+
+ current_level++;
+ }
+
+ if (prev_parent) {
+ tmp = webkit_dom_node_insert_before (
+ parent,
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+ webkit_dom_node_get_next_sibling (prev_parent),
+ NULL);
+ remove_node_if_empty (prev_parent);
+ }
+
+ return tmp;
+}
+
static void
undo_delete (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
@@ -344,7 +408,7 @@ undo_delete (WebKitDOMDocument *document,
dom_selection = webkit_dom_dom_window_get_selection (dom_window);
g_object_unref (dom_window);
- fragment = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (event->data.fragment), TRUE);
+ fragment = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (event->data.fragment), TRUE);
first_child = webkit_dom_node_get_first_child (fragment);
content = webkit_dom_node_get_text_content (fragment);
@@ -363,60 +427,172 @@ undo_delete (WebKitDOMDocument *document,
single_block = WEBKIT_DOM_IS_TEXT (first_child);
}
- /* Redoing Return key press */
- if (empty) {
- WebKitDOMNode *node, *tmp_node;
+ /* Delete or BackSpace pressed in the beginning of a block or on its end. */
+ if (event->type == HISTORY_DELETE && !single_block &&
+ g_object_get_data (G_OBJECT (event->data.fragment), "-x-evo-fragment")) {
+ WebKitDOMNode *node, *block;
- range = get_range_for_point (document, event->before.start);
+ range = get_range_for_point (document, event->after.start);
webkit_dom_dom_selection_remove_all_ranges (dom_selection);
webkit_dom_dom_selection_add_range (dom_selection, range);
- g_object_unref (dom_selection);
- node = webkit_dom_range_get_start_container (range, NULL);
- g_object_unref (range);
- if (!node)
- return;
-
- tmp_node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (event->data.fragment));
- if (WEBKIT_DOM_IS_HTML_LI_ELEMENT (tmp_node) &&
- WEBKIT_DOM_IS_HTML_BR_ELEMENT (webkit_dom_node_get_last_child (tmp_node)))
- if (return_pressed_in_empty_list_item (document, extension, FALSE))
- return;
+ node = webkit_dom_range_get_end_container (range, NULL);
+ block = get_parent_block_node_from_child (node);
+
+ if (webkit_dom_document_fragment_query_selector (event->data.fragment, ".-x-evo-quoted",
NULL)) {
+ while ((node = webkit_dom_node_get_first_child (fragment))) {
+ if (WEBKIT_DOM_IS_ELEMENT (node) &&
+ webkit_dom_element_query_selector (WEBKIT_DOM_ELEMENT (node),
".-x-evo-quoted", NULL))
+
+ if (get_citation_level (block, FALSE) > 0) {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (block),
+ node,
+ block,
+ NULL);
+ } else {
+ WebKitDOMNode *next_block;
+
+ next_block = webkit_dom_node_get_next_sibling (block);
+ while (next_block && dom_node_is_citation_node (next_block))
+ next_block = webkit_dom_node_get_first_child
(next_block);
+
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (next_block),
+ node,
+ next_block,
+ NULL);
+ }
+ else {
+ if (get_citation_level (block, FALSE) > 0) {
+ WebKitDOMNode *next_node;
+
+ next_node = split_node_into_two (block, -1);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (next_node),
+ node,
+ next_node,
+ NULL);
+ } else
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (block),
+ node,
+ block,
+ NULL);
+ }
+ }
+ } else {
+ while ((node = webkit_dom_node_get_first_child (fragment))) {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (block),
+ node,
+ block,
+ NULL);
+ }
+ }
- if (WEBKIT_DOM_IS_HTML_LI_ELEMENT (webkit_dom_node_get_parent_node (node)))
- element = webkit_dom_node_get_parent_element (node);
- else
- element = get_parent_block_element (node);
+ remove_node (block);
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
- fragment,
- webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element)),
- NULL);
+ restore_selection_to_history_event_state (document, event->before);
- dom_selection_restore (document);
dom_force_spell_check_in_viewport (document, extension);
return;
}
+ /* Redoing Return key press */
+ if (event->type == HISTORY_INPUT && (empty ||
+ g_object_get_data (G_OBJECT (event->data.fragment), "-x-evo-return-key"))) {
+ if (key_press_event_process_return_key (document, extension)) {
+ body_key_up_event_process_return_key (document, extension);
+ dom_force_spell_check_in_viewport (document, extension);
+ return;
+ } else {
+ WebKitDOMElement *element;
+ WebKitDOMNode *next_sibling;
+
+ range = get_range_for_point (document, event->before.start);
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+ g_object_unref (dom_selection);
+
+ dom_selection_save (document);
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
+
+ next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+ if (next_sibling && !(WEBKIT_DOM_IS_HTML_BR_ELEMENT (next_sibling))) {
+ split_node_into_two (WEBKIT_DOM_NODE (element), 1);
+ } else {
+ WebKitDOMNode *block;
+
+ block = get_parent_block_node_from_child (
+ WEBKIT_DOM_NODE (element));
+ dom_remove_selection_markers (document);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (block),
+ fragment,
+ webkit_dom_node_get_next_sibling (block),
+ NULL);
+ }
+ dom_selection_restore (document);
+
+ return;
+ }
+ }
+
+ if (!single_block) {
+ if (WEBKIT_DOM_IS_ELEMENT (first_child) &&
+ !(WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (first_child) ||
+ WEBKIT_DOM_IS_HTML_PRE_ELEMENT (first_child) ||
+ (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (first_child) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (first_child), "-x-evo-paragraph"))))
+ single_block = TRUE;
+ }
+
/* Multi block delete */
if (WEBKIT_DOM_IS_ELEMENT (first_child) && !single_block) {
gboolean delete;
WebKitDOMElement *signature;
- WebKitDOMNode *node, *parent, *last_child;
- WebKitDOMNode *parent_deleted_content;
- WebKitDOMNode *parent_current_block;
- WebKitDOMNode *insert_before;
+ WebKitDOMNode *node, *current_block, *last_child;
+ WebKitDOMNode *next_block, *insert_before;
+ WebKitDOMNode *parent_deleted_content, *parent_current_block;
- range = get_range_for_point (document, event->before.start);
+ range = get_range_for_point (document, event->after.start);
webkit_dom_dom_selection_remove_all_ranges (dom_selection);
webkit_dom_dom_selection_add_range (dom_selection, range);
g_object_unref (range);
dom_selection_save (document);
- element = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-start-marker");
+ if ((element = webkit_dom_document_get_element_by_id (document,
"-x-evo-selection-end-marker"))) {
+ WebKitDOMNode *next_sibling;
+
+ if ((next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element))) &&
+ WEBKIT_DOM_IS_CHARACTER_DATA (next_sibling) &&
+ webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (next_sibling))
== 1) {
+ gchar *data;
+
+ data = webkit_dom_character_data_get_data (WEBKIT_DOM_CHARACTER_DATA
(next_sibling));
+ if (data && *data == ' ') {
+ WebKitDOMElement *hidden_space;
+
+ hidden_space = webkit_dom_document_create_element (document, "span",
NULL);
+ webkit_dom_element_set_attribute (
+ hidden_space, "data-hidden-space", "", NULL);
+ remove_node (next_sibling);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ WEBKIT_DOM_NODE (hidden_space),
+ webkit_dom_node_get_previous_sibling (
+ WEBKIT_DOM_NODE (element)),
+ NULL);
+ }
+ g_free (data);
+ }
+ }
+
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker");
/* Get the last block in deleted content. */
last_child = webkit_dom_node_get_last_child (fragment);
@@ -429,7 +605,7 @@ undo_delete (WebKitDOMDocument *document,
/* FIXME Ugly hack */
/* If the selection ended in signature, the structure will be broken
- * thus we saved the while signature into deleted fragment and we will
+ * thus we saved the whole signature into deleted fragment and we will
* restore the whole signature, but we need to remove the rest of the
* signature that's left after delete to avoid duplications. */
signature = webkit_dom_document_query_selector (document, ".-x-evo-signature-wrapper", NULL);
@@ -442,10 +618,13 @@ undo_delete (WebKitDOMDocument *document,
element_has_class (WEBKIT_DOM_ELEMENT (tmp_node), "-x-evo-signature-wrapper");
}
+ current_block = get_parent_block_node_from_child (WEBKIT_DOM_NODE (element));
+
while (node) {
- WebKitDOMNode *next_sibling;
+ WebKitDOMNode *next_sibling, *parent_node;
next_sibling = webkit_dom_node_get_next_sibling (node);
+ parent_node = webkit_dom_node_get_parent_node (node);
if (!next_sibling && WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
/* Check if the whole element was deleted. If so replace it and
* skip the code down there. */
@@ -462,8 +641,10 @@ undo_delete (WebKitDOMDocument *document,
tmp_element = webkit_dom_document_get_element_by_id (
document, "-x-evo-tmp-block");
- if (tmp_element)
+ if (tmp_element) {
webkit_dom_element_remove_attribute (tmp_element, "id");
+ wrap_and_quote_element (document, extension, tmp_element);
+ }
/* Remove empty blockquotes, if presented. */
tmp_element = webkit_dom_document_query_selector (
@@ -483,7 +664,9 @@ undo_delete (WebKitDOMDocument *document,
return;
}
- }
+ } else if (!next_sibling && !webkit_dom_node_is_same_node (parent_node,
current_block))
+ next_sibling = webkit_dom_node_get_next_sibling (parent_node);
+
if (delete)
remove_node (node);
else
@@ -497,18 +680,18 @@ undo_delete (WebKitDOMDocument *document,
/* All the nodes that are in the first block of the deleted content
* belongs to the current block right after the caret position. */
- parent = get_parent_block_node_from_child (WEBKIT_DOM_NODE (element));
while ((node = webkit_dom_node_get_first_child (first_child)))
- webkit_dom_node_append_child (WEBKIT_DOM_NODE (parent), node, NULL);
+ webkit_dom_node_append_child (current_block, node, NULL);
parent_deleted_content = webkit_dom_node_get_parent_node (first_child);
- parent_current_block = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (parent));
- insert_before = webkit_dom_node_get_next_sibling (parent);
+ parent_current_block = webkit_dom_node_get_parent_node (current_block);
+ insert_before = webkit_dom_node_get_next_sibling (current_block);
/* Remove the first block from deleted content as its content was already
* moved to the right place. */
remove_node (first_child);
+ next_block = webkit_dom_node_get_next_sibling (current_block);
/* Move the deleted content back to the body. Start from the next sibling
* of the first block (if presented) where the delete occurred. */
while (parent_deleted_content) {
@@ -528,18 +711,29 @@ undo_delete (WebKitDOMDocument *document,
remove_node (parent_deleted_content);
parent_deleted_content = tmp;
insert_before = webkit_dom_node_get_next_sibling (parent_current_block);
+
+ if (!insert_before && next_block && WEBKIT_DOM_IS_HTML_BODY_ELEMENT (
+ webkit_dom_node_get_parent_node (parent_current_block)))
+ insert_before = split_node_into_two (next_block, -1);
+
/* Be sure that we don't go above body. */
if (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent_current_block))
parent_current_block = webkit_dom_node_get_parent_node (parent_current_block);
}
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (current_block));
+
+ if (WEBKIT_DOM_IS_ELEMENT (last_child))
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_child));
+
dom_merge_siblings_if_necessarry (document, event->data.fragment);
dom_selection_restore (document);
dom_force_spell_check_in_viewport (document, extension);
} else {
- gboolean empty_text = FALSE;
- WebKitDOMNode *nd;
+ gboolean empty_text = FALSE, was_link = FALSE;
+ WebKitDOMNode *prev_sibling, *next_sibling, *nd;
+ WebKitDOMNode *parent;
element = webkit_dom_document_create_element (document, "span", NULL);
@@ -574,28 +768,85 @@ undo_delete (WebKitDOMDocument *document,
g_free (text);
}
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
if (!nd || empty_text) {
- WebKitDOMNode *parent;
-
- parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
- if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent)) {
+ if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent))
webkit_dom_node_insert_before (
webkit_dom_node_get_parent_node (parent),
WEBKIT_DOM_NODE (element),
parent,
NULL);
- }
}
/* Insert the deleted content back to the body. */
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
- fragment,
- WEBKIT_DOM_NODE (element),
- NULL);
+ if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent)) {
+ if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (first_child)) {
+ WebKitDOMNode *child;
+
+ while ((child = webkit_dom_node_get_first_child (first_child)))
+ webkit_dom_node_append_child (parent, child, NULL);
+
+ remove_node (first_child);
+
+ was_link = TRUE;
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (parent),
+ fragment,
+ webkit_dom_node_get_next_sibling (parent),
+ NULL);
+ } else {
+ if (g_object_get_data (G_OBJECT (event->data.fragment),
"-x-evo-removing-from-anchor") ||
+ !event_selection_was_collapsed (event)) {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ fragment,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ } else {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (parent),
+ fragment,
+ webkit_dom_node_get_next_sibling (parent),
+ NULL);
+ }
+ }
+ } else {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ fragment,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+
+ webkit_dom_node_normalize (parent);
+ prev_sibling = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+ next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+ if (prev_sibling && next_sibling) {
+ WebKitDOMNode *clone_prev, *clone_next;
+
+ clone_prev = webkit_dom_node_clone_node (prev_sibling, FALSE);
+ clone_next = webkit_dom_node_clone_node (next_sibling, FALSE);
+
+ if (webkit_dom_node_is_equal_node (clone_prev, clone_next)) {
+ WebKitDOMNode *child;
+
+ while ((child = webkit_dom_node_get_first_child (next_sibling)))
+ webkit_dom_node_append_child (prev_sibling, child, NULL);
+
+ remove_node (next_sibling);
+ }
+ }
remove_node (WEBKIT_DOM_NODE (element));
+ if (event->type == HISTORY_DELETE && !e_html_editor_web_extension_get_html_mode (extension) &&
+ !webkit_dom_document_fragment_query_selector (event->data.fragment, ".-x-evo-quoted",
NULL)) {
+ WebKitDOMNode *current_block;
+
+ current_block = get_parent_block_node_from_child (parent);
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (current_block));
+ }
+
/* If the selection markers are presented restore the selection,
* otherwise the selection was not collapsed so select the deleted
* content as it was before the delete occurred. */
@@ -607,7 +858,7 @@ undo_delete (WebKitDOMDocument *document,
if (event->type != HISTORY_INPUT) {
if (e_html_editor_web_extension_get_magic_smileys_enabled (extension))
dom_check_magic_smileys (document, extension);
- if (e_html_editor_web_extension_get_magic_links_enabled (extension))
+ if (!was_link && e_html_editor_web_extension_get_magic_links_enabled (extension))
dom_check_magic_links (document, extension, FALSE);
}
dom_force_spell_check_for_current_paragraph (document, extension);
@@ -621,55 +872,97 @@ redo_delete (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
EHTMLEditorHistoryEvent *event)
{
+ EHTMLEditorUndoRedoManager *manager;
+ gboolean delete_key, control_key;
+ glong length = 1;
+ gint ii;
WebKitDOMDocumentFragment *fragment = event->data.fragment;
- WebKitDOMNode *first_child;
-
- first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+ WebKitDOMNode *node;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
restore_selection_to_history_event_state (document, event->before);
- if (webkit_dom_document_fragment_query_selector (fragment, "span#-x-evo-selection-start-marker",
NULL)) {
- gboolean delete = FALSE, control_key = FALSE;
- glong length = 1;
- gint ii;
- WebKitDOMDOMWindow *dom_window;
- WebKitDOMDOMSelection *dom_selection;
+ delete_key = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment),
"-x-evo-delete-key"));
+ control_key = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment),
"-x-evo-control-key"));
- dom_window = webkit_dom_document_get_default_view (document);
- g_object_unref (dom_window);
- dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+ if (!delete_key && key_press_event_process_backspace_key (document, extension))
+ goto out;
+
+ if (key_press_event_process_delete_or_backspace_key (document, extension, ~0, 0, delete_key))
+ goto out;
- control_key = event_selection_was_collapsed (event);
- if (control_key) {
- gchar *text_content;
+ if (control_key) {
+ gchar *text_content;
+
+ text_content = webkit_dom_node_get_text_content (WEBKIT_DOM_NODE (fragment));
+ length = g_utf8_strlen (text_content, -1);
+ control_key = length > 1;
+
+ g_free (text_content);
+ }
- text_content = webkit_dom_node_get_text_content (WEBKIT_DOM_NODE (fragment));
- length = g_utf8_strlen (text_content, -1);
- control_key = length > 1;
+ /* If concatenating two blocks with pressing Delete on the end
+ * of the previous one and the next node contain content that
+ * is wrapped on multiple lines, the last line will by separated
+ * by WebKit to the separate block. To avoid it let's remove
+ * all quoting and wrapping from the next paragraph. */
+ if (delete_key && GPOINTER_TO_INT (g_object_get_data (G_OBJECT (event->data.fragment),
"-x-evo-fragment"))) {
+ WebKitDOMNode *current_block, *next_block, *node;
+ WebKitDOMRange *range;
- g_free (text_content);
+ range = dom_get_current_range (document);
+ node = webkit_dom_range_get_end_container (range, NULL);
+ g_object_unref (range);
+ current_block = get_parent_block_node_from_child (node);
+ if (get_citation_level (current_block, FALSE) > 0 &&
+ (next_block = webkit_dom_node_get_next_sibling (current_block))) {
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (next_block));
+ dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (next_block));
}
+ }
- /* Check if the event was delete or backspace press. */
- delete = WEBKIT_DOM_IS_ELEMENT (first_child);
- delete = delete && element_has_id (WEBKIT_DOM_ELEMENT (first_child),
"-x-evo-selection-start-marker");
- for (ii = 0; ii < length; ii++) {
+ for (ii = 0; ii < length; ii++) {
+ dom_exec_command (
+ document, extension,
+ delete_key ? E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE :
+ E_HTML_EDITOR_VIEW_COMMAND_DELETE,
+ NULL);
+ }
+
+ /* Really don't know why, but when the selection marker nodes were in
+ * anchors then we need to do an extra delete command otherwise we will
+ * end with two blocks split in half. */
+ node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+ while ((node = webkit_dom_node_get_first_child (node))) {
+ if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
dom_exec_command (
document, extension,
- delete ? E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE :
- E_HTML_EDITOR_VIEW_COMMAND_DELETE,
+ E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE,
NULL);
+ break;
}
+ }
- g_object_unref (dom_selection);
- } else {
- if (!dom_delete_character_from_quoted_line_start (document, extension, ~0, 0))
- if (!dom_fix_structure_after_delete_before_quoted_content (document, extension, ~0,
0))
- dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE,
NULL);
-
- dom_disable_quote_marks_select (document);
+ node = webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment));
+ while ((node = webkit_dom_node_get_last_child (node))) {
+ if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
+ dom_exec_command (
+ document, extension,
+ E_HTML_EDITOR_VIEW_COMMAND_FORWARD_DELETE,
+ NULL);
+ break;
+ }
}
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, TRUE);
+ e_html_editor_undo_redo_manager_set_operation_in_progress (manager, FALSE);
+ body_input_event_process (document, extension, NULL);
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+ e_html_editor_undo_redo_manager_set_operation_in_progress (manager, TRUE);
+ e_html_editor_web_extension_set_renew_history_after_coordinates (extension, FALSE);
+ body_key_up_event_process_backspace_or_delete (document, extension, delete_key);
+ e_html_editor_web_extension_set_renew_history_after_coordinates (extension, TRUE);
+ out:
restore_selection_to_history_event_state (document, event->after);
dom_force_spell_check_for_current_paragraph (document, extension);
@@ -1598,7 +1891,6 @@ undo_redo_citation_split (WebKitDOMDocument *document,
in_situ = TRUE;
if (undo) {
- gint citation_level = 1, length, word_wrap_length;
WebKitDOMElement *selection_start, *parent;
WebKitDOMNode *citation_before, *citation_after, *child, *last_child, *tmp;
@@ -1612,6 +1904,15 @@ undo_redo_citation_split (WebKitDOMDocument *document,
parent = get_parent_block_element (WEBKIT_DOM_NODE (selection_start));
+ if (event->data.fragment &&
+ !webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (event->data.fragment))) {
+ remove_node (WEBKIT_DOM_NODE (parent));
+ dom_merge_siblings_if_necessarry (document, NULL);
+ restore_selection_to_history_event_state (document, event->before);
+
+ return;
+ }
+
citation_before = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (parent));
if (!dom_node_is_citation_node (citation_before)) {
dom_selection_restore (document);
@@ -1626,16 +1927,20 @@ undo_redo_citation_split (WebKitDOMDocument *document,
/* Get first block in next citation. */
child = webkit_dom_node_get_first_child (citation_after);
- while (child && dom_node_is_citation_node (child)) {
- citation_level++;
+ while (child && dom_node_is_citation_node (child))
child = webkit_dom_node_get_first_child (child);
- }
/* Get last block in previous citation. */
last_child = webkit_dom_node_get_last_child (citation_before);
while (last_child && dom_node_is_citation_node (last_child))
last_child = webkit_dom_node_get_last_child (last_child);
+ /* Before appending any content to the block, check that the
+ * last node is not BR, if it is, remove it. */
+ tmp = webkit_dom_node_get_last_child (last_child);
+ if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (tmp))
+ remove_node (tmp);
+
if (in_situ) {
webkit_dom_node_append_child (
webkit_dom_node_get_parent_node (last_child),
@@ -1654,14 +1959,7 @@ undo_redo_citation_split (WebKitDOMDocument *document,
while ((tmp = webkit_dom_node_get_first_child (child)))
webkit_dom_node_append_child (last_child, tmp, NULL);
- word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
- length = word_wrap_length - 2 * citation_level;
-
- /* We need to re-wrap and re-quote the block. */
- last_child = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
- document, extension, WEBKIT_DOM_ELEMENT (last_child), length));
- dom_quote_plain_text_element_after_wrapping (
- document, WEBKIT_DOM_ELEMENT (last_child), citation_level);
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_child));
remove_node (child);
}
@@ -1679,6 +1977,8 @@ undo_redo_citation_split (WebKitDOMDocument *document,
if (event->data.fragment != NULL && !in_situ)
undo_delete (document, extension, event);
+ dom_merge_siblings_if_necessarry (document, NULL);
+
restore_selection_to_history_event_state (document, event->before);
dom_force_spell_check_in_viewport (document, extension);
@@ -1923,7 +2223,7 @@ e_html_editor_undo_redo_manager_insert_history_event (EHTMLEditorUndoRedoManager
manager->priv->history_size++;
manager->priv->can_undo = TRUE;
- d (print_history (view));
+ d (print_history (manager));
g_object_notify (G_OBJECT (manager), "can-undo");
}
diff --git a/web-extensions/composer/e-html-editor-view-dom-functions.c
b/web-extensions/composer/e-html-editor-view-dom-functions.c
index 345e954..70ef36a 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.c
@@ -433,7 +433,7 @@ dom_node_is_citation_node (WebKitDOMNode *node)
}
}
-static gint
+gint
get_citation_level (WebKitDOMNode *node,
gboolean set_plaintext_quoted)
{
@@ -577,12 +577,50 @@ get_parent_block_node_from_child (WebKitDOMNode *node)
}
WebKitDOMElement *
+wrap_and_quote_element (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMElement *element)
+{
+ gint citation_level;
+ WebKitDOMElement *tmp_element = element;
+
+ g_return_val_if_fail (WEBKIT_DOM_IS_ELEMENT (element), element);
+
+ if (e_html_editor_web_extension_get_html_mode (extension))
+ return element;
+
+ citation_level = get_citation_level (WEBKIT_DOM_NODE (element), FALSE);
+
+ dom_remove_quoting_from_element (element);
+ dom_remove_wrapping_from_element (element);
+
+ if (element_has_class (element, "-x-evo-paragraph")) {
+ gint word_wrap_length, length;
+
+ word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
+ length = word_wrap_length - 2 * citation_level;
+ tmp_element = dom_wrap_paragraph_length (
+ document, extension, element, length);
+ }
+
+ if (citation_level > 0) {
+
+ webkit_dom_node_normalize (WEBKIT_DOM_NODE (tmp_element));
+ dom_quote_plain_text_element_after_wrapping (
+ document, tmp_element, citation_level);
+ }
+
+ return tmp_element;
+}
+
+WebKitDOMElement *
dom_insert_new_line_into_citation (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *html_to_insert)
{
gboolean html_mode = FALSE, ret_val, avoid_editor_call;
WebKitDOMElement *element, *paragraph = NULL;
+ WebKitDOMNode *last_block;
html_mode = e_html_editor_web_extension_get_html_mode (extension);
@@ -674,37 +712,43 @@ dom_insert_new_line_into_citation (WebKitDOMDocument *document,
return NULL;
}
+ last_block = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+ while (last_block && dom_node_is_citation_node (last_block))
+ last_block = webkit_dom_node_get_last_child (last_block);
+
+ if (last_block) {
+ WebKitDOMNode *last_child;
+
+ if ((last_child = webkit_dom_node_get_last_child (last_block))) {
+ if (WEBKIT_DOM_IS_ELEMENT (last_child) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (last_child), "-x-evo-quoted"))
+ webkit_dom_node_append_child (
+ last_block,
+ WEBKIT_DOM_NODE (
+ webkit_dom_document_create_element (
+ document, "br", NULL)),
+ NULL);
+ }
+ }
+
if (!html_mode) {
- WebKitDOMNode *next_sibling;
+ WebKitDOMNode *sibling;
- next_sibling = webkit_dom_node_get_next_sibling (
- WEBKIT_DOM_NODE (element));
+ sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
- if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling)) {
- gint citation_level, length;
- gint word_wrap_length;
+ if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (sibling)) {
WebKitDOMNode *node;
- node = webkit_dom_node_get_first_child (next_sibling);
+ node = webkit_dom_node_get_first_child (sibling);
while (node && dom_node_is_citation_node (node))
node = webkit_dom_node_get_first_child (node);
- citation_level = get_citation_level (node, FALSE);
- word_wrap_length =
- e_html_editor_web_extension_get_word_wrap_length (extension);
- length = word_wrap_length - 2 * citation_level;
+ /* Rewrap and requote nodes that were created by split. */
+ if (WEBKIT_DOM_IS_ELEMENT (node))
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (node));
- /* Rewrap and requote first block after the newly inserted line */
- if (node && WEBKIT_DOM_IS_ELEMENT (node)) {
- dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (node));
- dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (node));
-
- if (element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-paragraph"))
- node = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
- document, extension, WEBKIT_DOM_ELEMENT (node), length));
- dom_quote_plain_text_element_after_wrapping (
- document, WEBKIT_DOM_ELEMENT (node), citation_level);
- }
+ if (WEBKIT_DOM_IS_ELEMENT (last_block))
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_block));
dom_force_spell_check_in_viewport (document, extension);
}
@@ -2147,6 +2191,10 @@ save_history_for_input (WebKitDOMDocument *document,
remove_node (WEBKIT_DOM_NODE (element_start));
remove_node (WEBKIT_DOM_NODE (element_end));
+ g_object_set_data (
+ G_OBJECT (fragment), "-x-evo-return-key", GINT_TO_POINTER (1));
+
+
webkit_dom_dom_selection_modify (dom_selection, "move", "right", "character");
} else {
webkit_dom_node_append_child (
@@ -2226,19 +2274,17 @@ body_scroll_event_cb (WebKitDOMElement *element,
e_html_editor_web_extension_set_spell_check_on_scroll_event_source_id (extension, id);
}
-static void
-body_input_event_cb (WebKitDOMElement *element,
- WebKitDOMEvent *event,
- EHTMLEditorWebExtension *extension)
+void
+body_input_event_process (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMEvent *event)
{
EHTMLEditorUndoRedoManager *manager;
gboolean do_spell_check = FALSE;
gboolean html_mode;
- WebKitDOMDocument *document;
WebKitDOMNode *node;
WebKitDOMRange *range;
- document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
range = dom_get_current_range (document);
manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
@@ -2496,8 +2542,6 @@ body_input_event_cb (WebKitDOMElement *element,
/* Wrap and quote the line */
if (!remove_quoting && text_length >= word_wrap_length) {
- EHTMLEditorHistoryEvent *ev;
-
dom_remove_quoting_from_element (block);
block = dom_wrap_paragraph_length (document, extension, block, length);
@@ -2513,16 +2557,6 @@ body_input_event_cb (WebKitDOMElement *element,
NULL,
NULL);
- /* The content was wrapped and the coordinates
- * of caret could be changed, so renew them. */
- ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
- dom_selection_get_coordinates (
- document,
- &ev->after.start.x,
- &ev->after.start.y,
- &ev->after.end.x,
- &ev->after.end.y);
-
dom_selection_restore (document);
do_spell_check = TRUE;
goto out;
@@ -2537,6 +2571,18 @@ body_input_event_cb (WebKitDOMElement *element,
g_object_unref (range);
}
+static void
+body_input_event_cb (WebKitDOMElement *element,
+ WebKitDOMEvent *event,
+ EHTMLEditorWebExtension *extension)
+{
+ WebKitDOMDocument *document;
+
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+
+ body_input_event_process (document, extension, event);
+}
+
void
dom_remove_input_event_listener_from_body (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
@@ -2721,238 +2767,216 @@ dom_merge_siblings_if_necessarry (WebKitDOMDocument *document,
}
}
-static void
-body_keyup_event_cb (WebKitDOMElement *element,
- WebKitDOMUIEvent *event,
- EHTMLEditorWebExtension *extension)
+/* This will fix the structure after the situations where some text
+ * inside the quoted content is selected and afterwards deleted with
+ * BackSpace or Delete. */
+void
+body_key_up_event_process_backspace_or_delete (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ gboolean delete)
{
- glong key_code;
- WebKitDOMDocument *document;
-
- document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
- if (!e_html_editor_web_extension_is_composition_in_progress (extension))
- dom_register_input_event_listener_on_body (document, extension);
+ gint level;
+ WebKitDOMElement *selection_start_marker, *selection_end_marker;
+ WebKitDOMElement *tmp_element;
+ WebKitDOMNode *parent, *node;
- if (!dom_selection_is_collapsed (document))
+ if (e_html_editor_web_extension_get_html_mode (extension))
return;
- key_code = webkit_dom_ui_event_get_key_code (event);
- if (key_code == HTML_KEY_CODE_BACKSPACE || key_code == HTML_KEY_CODE_DELETE) {
- /* This will fix the structure after the situations where some text
- * inside the quoted content is selected and afterwards deleted with
- * BackSpace or Delete. */
- gint level;
- WebKitDOMElement *selection_start_marker, *selection_end_marker;
- WebKitDOMElement *tmp_element;
- WebKitDOMNode *parent, *node;
-
- if (e_html_editor_web_extension_get_html_mode (extension))
- return;
-
- dom_disable_quote_marks_select (document);
- /* Remove empty blocks if presented. */
- remove_empty_blocks (document);
-
- dom_selection_save (document);
- selection_start_marker = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-start-marker");
- selection_end_marker = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-end-marker");
-
- /* If we deleted a selection the caret will be inside the quote marks, fix it. */
- parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
- if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quote-character")) {
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (
- webkit_dom_node_get_parent_node (parent)),
- WEBKIT_DOM_NODE (selection_end_marker),
- webkit_dom_node_get_next_sibling (
- webkit_dom_node_get_parent_node (parent)),
- NULL);
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (
- webkit_dom_node_get_parent_node (parent)),
- WEBKIT_DOM_NODE (selection_start_marker),
- webkit_dom_node_get_next_sibling (
- webkit_dom_node_get_parent_node (parent)),
- NULL);
- }
-
- /* Under some circumstances we will end with block inside the citation
- * that has the quote marks removed and we have to reinsert them back. */
- level = get_citation_level (WEBKIT_DOM_NODE (selection_start_marker), FALSE);
- node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
- if (level > 0 && node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
- WebKitDOMNode *prev_sibling;
-
- prev_sibling = webkit_dom_node_get_previous_sibling (
- WEBKIT_DOM_NODE (selection_start_marker));
- if (!prev_sibling ||
- (WEBKIT_DOM_IS_HTML_BR_ELEMENT (prev_sibling) &&
- !webkit_dom_node_get_previous_sibling (prev_sibling))) {
- WebKitDOMElement *block;
-
- block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
- WEBKIT_DOM_NODE (selection_start_marker)));
- if (webkit_dom_element_has_attribute (block, "data-no-quote")) {
- webkit_dom_element_remove_attribute (block, "data-no-quote");
- } else {
- dom_remove_quoting_from_element (block);
- if (element_has_class (block, "-x-evo-paragraph")) {
- gint length, word_wrap_length;
-
- word_wrap_length =
e_html_editor_web_extension_get_word_wrap_length (extension);
- length = word_wrap_length - 2 * (level - 1);
- block = dom_wrap_paragraph_length (
- document, extension, block, length);
- webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
- }
- dom_quote_plain_text_element_after_wrapping (
- document, block, level);
- }
- }
- } else if (level > 0 && node && WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
- EHTMLEditorUndoRedoManager *manager;
- EHTMLEditorHistoryEvent *event;
- WebKitDOMDocumentFragment *fragment;
- WebKitDOMNode *block;
+ dom_disable_quote_marks_select (document);
+ /* Remove empty blocks if presented. */
+ remove_empty_blocks (document);
- manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
- block = get_parent_block_node_from_child (
- WEBKIT_DOM_NODE (selection_start_marker));
+ dom_selection_save (document);
+ selection_start_marker = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ selection_end_marker = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
- dom_remove_selection_markers (document);
+ /* If we deleted a selection the caret will be inside the quote marks, fix it. */
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
+ if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quote-character")) {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (
+ webkit_dom_node_get_parent_node (parent)),
+ WEBKIT_DOM_NODE (selection_end_marker),
+ webkit_dom_node_get_next_sibling (
+ webkit_dom_node_get_parent_node (parent)),
+ NULL);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (
+ webkit_dom_node_get_parent_node (parent)),
+ WEBKIT_DOM_NODE (selection_start_marker),
+ webkit_dom_node_get_next_sibling (
+ webkit_dom_node_get_parent_node (parent)),
+ NULL);
+ }
- event = g_new0 (EHTMLEditorHistoryEvent, 1);
- event->type = HISTORY_AND;
+ /* Under some circumstances we will end with block inside the citation
+ * that has the quote marks removed and we have to reinsert them back. */
+ level = get_citation_level (WEBKIT_DOM_NODE (selection_start_marker), FALSE);
+ node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker));
+ if (level > 0 && node && !WEBKIT_DOM_IS_HTML_BR_ELEMENT (node)) {
+ WebKitDOMElement *block;
- e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+ block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
+ WEBKIT_DOM_NODE (selection_start_marker)));
- event = g_new0 (EHTMLEditorHistoryEvent, 1);
- event->type = HISTORY_CITATION_SPLIT;
+ dom_remove_quoting_from_element (block);
+ if (element_has_class (block, "-x-evo-paragraph")) {
+ gint length, word_wrap_length;
- dom_selection_get_coordinates (
- document,
- &event->before.start.x,
- &event->before.start.y,
- &event->before.end.x,
- &event->before.end.y);
+ word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
+ length = word_wrap_length - 2 * level;
+ block = dom_wrap_paragraph_length (
+ document, extension, block, length);
+ webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
+ }
+ dom_quote_plain_text_element_after_wrapping (
+ document, block, level);
+ } else if (level > 0 && !node) {
+ WebKitDOMNode *prev_sibling;
- fragment = webkit_dom_document_create_document_fragment (document);
+ prev_sibling = webkit_dom_node_get_previous_sibling (
+ WEBKIT_DOM_NODE (selection_start_marker));
+ if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-quoted") &&
+ !webkit_dom_node_get_previous_sibling (prev_sibling))
+ webkit_dom_node_append_child (
+ parent,
+ WEBKIT_DOM_NODE (webkit_dom_document_create_element (document, "br", NULL)),
+ NULL);
+ }
- /* Save the current block as it will be removed few lines after this. */
+ /* Situation where the start of the selection was in the beginning
+ * of the block in quoted content and the end in the beginning of
+ * content that is after the citation or the selection end was in
+ * the end of the quoted content (showed by ^). The correct structure
+ * in these cases is to have empty block after the citation.
+ *
+ * > |xxx
+ * > xxx^
+ * |xxx
+ * */
+ tmp_element = webkit_dom_document_get_element_by_id (document, "-x-evo-tmp-block");
+ if (tmp_element) {
+ dom_remove_wrapping_from_element (tmp_element);
+ dom_remove_quoting_from_element (tmp_element);
+
+ /* Append the BR element if the block is empty, but the
+ * selection is there to be able to move to the block
+ * with caret later. */
+ if (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) &&
+ !webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (fragment),
- webkit_dom_node_clone_node (block, TRUE),
+ WEBKIT_DOM_NODE (tmp_element),
+ WEBKIT_DOM_NODE (webkit_dom_document_create_element (
+ document, "br", NULL)),
NULL);
- event->data.fragment = fragment;
+ webkit_dom_element_remove_attribute (tmp_element, "id");
- /* Remove current block (and all of its parents if they
- * are empty) as it will be replaced by a new block that
- * will be in the body and not in the blockquote. */
- dom_remove_node_and_parents_if_empty (block);
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp_element));
+ while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (parent)))
+ parent = webkit_dom_node_get_parent_node (parent);
- dom_insert_new_line_into_citation (document, extension, "");
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (parent),
+ WEBKIT_DOM_NODE (tmp_element),
+ webkit_dom_node_get_next_sibling (parent),
+ NULL);
+ }
- dom_selection_get_coordinates (
- document,
- &event->after.start.x,
- &event->after.start.y,
- &event->after.end.x,
- &event->after.end.y);
+ dom_merge_siblings_if_necessarry (document, NULL);
- e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+ dom_selection_restore (document);
+ dom_force_spell_check_for_current_paragraph (document, extension);
+}
- return;
- }
-
- /* Situation where the start of the selection was in the beginning
- * of the block in quoted content and the end in the beginning of
- * content that is after the citation or the selection end was in
- * the end of the quoted content (showed by ^). The correct structure
- * in these cases is to have empty block after the citation.
- *
- * > |xxx
- * > xxx^
- * |xxx
- */
- tmp_element = webkit_dom_document_get_element_by_id (document, "-x-evo-tmp-block");
- if (tmp_element) {
- dom_remove_wrapping_from_element (tmp_element);
- dom_remove_quoting_from_element (tmp_element);
-
- /* Append the BR element if the block is empty, but the
- * selection is there to be able to move to the block
- * with caret later. */
- if (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) &&
- !webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)))
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (tmp_element),
- WEBKIT_DOM_NODE (webkit_dom_document_create_element (
- document, "br", NULL)),
- NULL);
+void
+body_key_up_event_process_return_key (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ WebKitDOMElement *selection_start_marker, *selection_end_marker;
+ WebKitDOMNode *parent;
- webkit_dom_element_remove_attribute (tmp_element, "id");
+ /* If the return is pressed in an unordered list in plain text mode
+ * the caret is moved to the "*" character before the newly inserted
+ * item. It looks like it is not enough that the item has BR element
+ * inside, but we have to again use the zero width space character
+ * to fix the situation. */
+ if (e_html_editor_web_extension_get_html_mode (extension))
+ return;
- parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp_element));
- while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node
(parent)))
- parent = webkit_dom_node_get_parent_node (parent);
+ /* FIXME WK2 this is called twice */
+ /* dom_selection_save (document); */
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (parent),
- WEBKIT_DOM_NODE (tmp_element),
- webkit_dom_node_get_next_sibling (parent),
- NULL);
- }
+ dom_selection_save (document);
- dom_merge_siblings_if_necessarry (document, NULL);
- dom_selection_restore (document);
- } else if (key_code == HTML_KEY_CODE_CONTROL)
- dom_set_links_active (document, FALSE);
- else if (key_code == HTML_KEY_CODE_RETURN) {
- WebKitDOMDocument *document;
- WebKitDOMElement *selection_start_marker, *selection_end_marker;
- WebKitDOMNode *parent;
+ selection_start_marker = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ selection_end_marker = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
- /* If the return is pressed in an unordered list in plain text mode
- * the caret is moved to the "*" character before the the newly inserted
- * item. It looks like it is not enough that the item has BR element
- * inside, but we have to again use the zero width space character
- * to fix the situation. */
- if (e_html_editor_web_extension_get_html_mode (extension))
- return;
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
+ if (!WEBKIT_DOM_IS_HTML_LI_ELEMENT (parent) ||
+ !WEBKIT_DOM_IS_HTML_U_LIST_ELEMENT (webkit_dom_node_get_parent_node (parent))) {
+ dom_selection_restore (document);
+ return;
+ }
- /* FIXME WK2 - the below is called twice, the second time two lines below */
- /*dom_selection_save (document);*/
+ if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)) &&
+ (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) ||
+ WEBKIT_DOM_IS_HTML_BR_ELEMENT (webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE
(selection_end_marker)))))
+ webkit_dom_html_element_insert_adjacent_text (
+ WEBKIT_DOM_HTML_ELEMENT (parent),
+ "afterbegin",
+ UNICODE_ZERO_WIDTH_SPACE,
+ NULL);
- document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+ dom_selection_restore (document);
+}
- dom_selection_save (document);
+static void
+body_keyup_event_cb (WebKitDOMElement *element,
+ WebKitDOMUIEvent *event,
+ EHTMLEditorWebExtension *extension)
+{
+ WebKitDOMDocument *document;
+ glong key_code;
- selection_start_marker = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-start-marker");
- selection_end_marker = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-end-marker");
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+ if (!e_html_editor_web_extension_is_composition_in_progress (extension))
+ dom_register_input_event_listener_on_body (document, extension);
- parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (selection_start_marker));
- if (!WEBKIT_DOM_IS_HTML_LI_ELEMENT (parent) ||
- !WEBKIT_DOM_IS_HTML_U_LIST_ELEMENT (webkit_dom_node_get_parent_node (parent))) {
- dom_selection_restore (document);
- return;
- }
+ if (!dom_selection_is_collapsed (document))
+ return;
- if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker)) &&
- (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)) ||
- WEBKIT_DOM_IS_HTML_BR_ELEMENT (webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE
(selection_end_marker)))))
- webkit_dom_html_element_insert_adjacent_text (
- WEBKIT_DOM_HTML_ELEMENT (parent),
- "afterbegin",
- UNICODE_ZERO_WIDTH_SPACE,
- NULL);
+ key_code = webkit_dom_ui_event_get_key_code (event);
+ if (key_code == HTML_KEY_CODE_BACKSPACE || key_code == HTML_KEY_CODE_DELETE) {
+ body_key_up_event_process_backspace_or_delete (document, extension, key_code ==
HTML_KEY_CODE_DELETE);
+
+ /* The content was wrapped and the coordinates
+ * of caret could be changed, so renew them. But
+ * only do that when we are not redoing a history
+ * event, otherwise it would modify the history. */
+ if (e_html_editor_web_extension_get_renew_history_after_coordinates (extension)) {
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
- dom_selection_restore (document);
- }
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ dom_selection_get_coordinates (
+ document,
+ &ev->after.start.x,
+ &ev->after.start.y,
+ &ev->after.end.x,
+ &ev->after.end.y);
+ }
+ } else if (key_code == HTML_KEY_CODE_CONTROL)
+ dom_set_links_active (document, FALSE);
+ else if (key_code == HTML_KEY_CODE_RETURN)
+ body_key_up_event_process_return_key (document, extension);
}
static void
@@ -2981,6 +3005,79 @@ fix_structure_after_pasting_multiline_content (WebKitDOMNode *node)
}
}
+static gboolean
+delete_hidden_space (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ gint citation_level;
+ WebKitDOMElement *selection_start_marker, *selection_end_marker, *block;
+
+ 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_ELEMENT (get_parent_block_node_from_child (
+ 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) {
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
+ WebKitDOMNode *node;
+ WebKitDOMDocumentFragment *fragment;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+
+ node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker));
+ if (!(WEBKIT_DOM_IS_ELEMENT (node) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted")))
+ return FALSE;
+
+ node = webkit_dom_node_get_previous_sibling (node);
+ if (!(WEBKIT_DOM_IS_ELEMENT (node) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-wrap-br")))
+ return FALSE;
+
+ node = webkit_dom_node_get_previous_sibling (node);
+ if (!(WEBKIT_DOM_IS_ELEMENT (node) &&
+ webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (node), "data-hidden-space")))
+ return FALSE;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
+
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x,
&ev->before.end.y);
+
+ remove_node (node);
+
+ wrap_and_quote_element (document, extension, block);
+
+ fragment = webkit_dom_document_create_document_fragment (document);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (
+ webkit_dom_document_create_text_node (document, " ")),
+ NULL);
+ ev->data.fragment = fragment;
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
gboolean
dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
@@ -2988,7 +3085,8 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
EHTMLEditorHistoryEvent *ev = NULL;
gboolean html_mode;
gint citation_level, success = FALSE;
- WebKitDOMElement *selection_start_marker, *selection_end_marker, *block;
+ WebKitDOMElement *selection_start_marker, *selection_end_marker;
+ WebKitDOMNode *block;
EHTMLEditorUndoRedoManager *manager;
manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
@@ -3002,8 +3100,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
if (!selection_start_marker || !selection_end_marker)
return FALSE;
- block = WEBKIT_DOM_ELEMENT (get_parent_block_node_from_child (
- WEBKIT_DOM_NODE (selection_start_marker)));
+ block = get_parent_block_node_from_child (WEBKIT_DOM_NODE (selection_start_marker));
citation_level = get_citation_level (
WEBKIT_DOM_NODE (selection_start_marker), FALSE);
@@ -3014,7 +3111,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
WebKitDOMNode *prev_sibling;
- webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
+ webkit_dom_node_normalize (block);
prev_sibling = webkit_dom_node_get_previous_sibling (
WEBKIT_DOM_NODE (selection_start_marker));
@@ -3040,8 +3137,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
if (html_mode)
success = WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (
- webkit_dom_node_get_parent_element (
- WEBKIT_DOM_NODE (block)));
+ webkit_dom_node_get_parent_element (block));
}
if (!success)
@@ -3052,15 +3148,15 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
ev->type = HISTORY_UNQUOTE;
dom_selection_get_coordinates (document, &ev->before.start.x, &ev->before.start.y,
&ev->before.end.x, &ev->before.end.y);
- ev->data.dom.from = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (block), TRUE);
+ ev->data.dom.from = webkit_dom_node_clone_node (block, TRUE);
}
if (citation_level == 1) {
gchar *inner_html;
- WebKitDOMElement *paragraph;
+ WebKitDOMElement *paragraph, *element;
- inner_html = webkit_dom_element_get_inner_html (block);
- webkit_dom_element_set_id (block, "-x-evo-to-remove");
+ 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 = dom_insert_new_line_into_citation (document, extension, inner_html);
g_free (inner_html);
@@ -3087,11 +3183,10 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
}
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 (block);
+
+ while ((element = webkit_dom_document_get_element_by_id (document, "-x-evo-to-remove")))
+ remove_node (WEBKIT_DOM_NODE (element));
if (paragraph)
remove_node_if_empty (
@@ -3100,47 +3195,41 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
}
if (citation_level > 1) {
- gint length, word_wrap_length;
WebKitDOMNode *parent;
- word_wrap_length = e_html_editor_web_extension_get_word_wrap_length (extension);
- length = word_wrap_length - 2 * (citation_level - 1);
-
if (html_mode) {
webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (block),
+ block,
WEBKIT_DOM_NODE (selection_start_marker),
- webkit_dom_node_get_first_child (
- WEBKIT_DOM_NODE (block)),
+ webkit_dom_node_get_first_child (block),
NULL);
webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (block),
+ block,
WEBKIT_DOM_NODE (selection_end_marker),
- webkit_dom_node_get_first_child (
- WEBKIT_DOM_NODE (block)),
+ webkit_dom_node_get_first_child (block),
NULL);
}
- dom_remove_quoting_from_element (block);
- dom_remove_wrapping_from_element (block);
+ dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (block));
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (block));
- parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (block));
+ parent = webkit_dom_node_get_parent_node (block);
- if (!webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (block))) {
+ if (!webkit_dom_node_get_previous_sibling (block)) {
/* Currect block is in the beginning of citation, just move it
* before the citation where already is */
webkit_dom_node_insert_before (
webkit_dom_node_get_parent_node (parent),
- WEBKIT_DOM_NODE (block),
+ block,
parent,
NULL);
- } else if (!webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (block))) {
+ } else if (!webkit_dom_node_get_next_sibling (block)) {
/* Currect block is at the end of the citation, just move it
* after the citation where already is */
webkit_dom_node_insert_before (
webkit_dom_node_get_parent_node (parent),
- WEBKIT_DOM_NODE (block),
+ block,
webkit_dom_node_get_next_sibling (parent),
NULL);
} else {
@@ -3153,7 +3242,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
/* Move nodes that are after the currect block into the
* new blockquote */
- child = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (block));
+ child = webkit_dom_node_get_next_sibling (block);
while (child) {
WebKitDOMNode *next = webkit_dom_node_get_next_sibling (child);
webkit_dom_node_append_child (clone, child, NULL);
@@ -3168,16 +3257,12 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
webkit_dom_node_insert_before (
webkit_dom_node_get_parent_node (parent),
- WEBKIT_DOM_NODE (block),
+ block,
clone,
NULL);
}
- if (!html_mode) {
- block = dom_wrap_paragraph_length (document, extension, block, length);
- webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
- dom_quote_plain_text_element_after_wrapping (document, block, citation_level - 1);
- }
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (block));
}
if (ev) {
@@ -7517,9 +7602,9 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
gboolean delete_key,
gboolean control_key)
{
- EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorHistoryEvent *ev = NULL;
EHTMLEditorUndoRedoManager *manager;
- WebKitDOMDocumentFragment *fragment;
+ WebKitDOMDocumentFragment *fragment = NULL;
WebKitDOMDOMWindow *dom_window;
WebKitDOMDOMSelection *dom_selection;
WebKitDOMRange *range;
@@ -7550,7 +7635,9 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
if (webkit_dom_range_get_collapsed (range, NULL)) {
+ gboolean removing_from_anchor = FALSE;
WebKitDOMRange *range_clone;
+ WebKitDOMNode *node, *next_block = NULL;
e_html_editor_web_extension_block_selection_changed_callback (extension);
@@ -7576,47 +7663,135 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
NULL);
g_object_unref (tmp_range);
} else {
- if (delete_key) {
- WebKitDOMNode *container, *next_sibling;
+ typedef WebKitDOMNode * (*GetSibling)(WebKitDOMNode *node);
+ WebKitDOMNode *container, *sibling;
+ WebKitDOMElement *selection_marker;
+
+ GetSibling get_sibling = delete_key ?
+ webkit_dom_node_get_next_sibling :
+ webkit_dom_node_get_previous_sibling;
+
+ container = webkit_dom_range_get_end_container (range_clone, NULL);
+ sibling = get_sibling (container);
+
+ selection_marker = webkit_dom_document_get_element_by_id (
+ document,
+ delete_key ?
+ "-x-evo-selection-end-marker" :
+ "-x-evo-selection-start-marker");
- container = webkit_dom_range_get_end_container (range_clone, NULL);
- next_sibling = webkit_dom_node_get_next_sibling (container);
+ if (selection_marker) {
+ WebKitDOMNode *tmp_sibling;
- if (dom_is_selection_position_node (next_sibling)) {
- WebKitDOMNode *next_node;
+ tmp_sibling = get_sibling (WEBKIT_DOM_NODE (selection_marker));
+ if (!tmp_sibling || (WEBKIT_DOM_IS_HTML_BR_ELEMENT (tmp_sibling) &&
+ !element_has_class (WEBKIT_DOM_ELEMENT (tmp_sibling), "-x-evo-wrap-br")))
+ sibling = WEBKIT_DOM_NODE (selection_marker);
+ }
- next_node = webkit_dom_node_get_next_sibling (
- webkit_dom_node_get_next_sibling (next_sibling));
- if (next_node) {
+ if (dom_is_selection_position_node (sibling)) {
+ if ((node = get_sibling (sibling)))
+ node = get_sibling (node);
+ if (node) {
+ if (WEBKIT_DOM_IS_ELEMENT (node) &&
+ webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (node),
"data-hidden-space")) {
+ fragment = webkit_dom_document_create_document_fragment
(document);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (
+ webkit_dom_document_create_text_node
(document, " ")),
+ NULL);
+ } else if (delete_key) {
webkit_dom_range_set_start (
- range_clone, next_node, 0, NULL);
+ range_clone, node, 0, NULL);
webkit_dom_range_set_end (
- range_clone, next_node, 1, NULL);
+ range_clone, node, 1, NULL);
}
} else {
- glong offset;
+ WebKitDOMRange *tmp_range, *actual_range;
+
+ actual_range = webkit_dom_dom_selection_get_range_at (dom_selection,
0, NULL);
+
+ webkit_dom_dom_selection_modify (
+ dom_selection, "move", delete_key ? "right" : "left",
"character");
+
+ tmp_range = webkit_dom_dom_selection_get_range_at (dom_selection, 0,
NULL);
+ if (webkit_dom_range_compare_boundary_points (tmp_range, 2,
actual_range, NULL) != 0) {
+ WebKitDOMNode *actual_block;
+ WebKitDOMNode *tmp_block;
+
+ actual_block = get_parent_block_node_from_child (container);
+
+ tmp_block = delete_key ?
+ webkit_dom_range_get_end_container (tmp_range, NULL) :
+ webkit_dom_range_get_start_container (tmp_range,
NULL);
+ tmp_block = get_parent_block_node_from_child (tmp_block);
+
+ webkit_dom_dom_selection_modify (
+ dom_selection, "move", delete_key ? "left" : "right",
"character");
+
+ if (tmp_block) {
+ fragment =
webkit_dom_document_create_document_fragment (document);
+ if (delete_key) {
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node
(actual_block, TRUE),
+ NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node
(tmp_block, TRUE),
+ NULL);
+ if (delete_key)
+ next_block = tmp_block;
+ } else {
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node
(tmp_block, TRUE),
+ NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node
(actual_block, TRUE),
+ NULL);
+ }
+ g_object_set_data (
+ G_OBJECT (fragment),
+ "-x-evo-fragment",
+ GINT_TO_POINTER (1));
+ }
+ }
+ g_object_unref (tmp_range);
+ g_object_unref (actual_range);
+ }
+ } else {
+ glong offset;
- offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+ offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+ if (delete_key)
webkit_dom_range_set_end (
range_clone, container, offset + 1, NULL);
- }
- } else {
- webkit_dom_range_set_start (
- range_clone,
- webkit_dom_range_get_start_container (range_clone, NULL),
- webkit_dom_range_get_start_offset (range_clone, NULL) - 1,
- NULL);
+ else
+ webkit_dom_range_set_start (
+ range_clone, container, offset - 1, NULL);
+
+ removing_from_anchor = WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (
+ webkit_dom_node_get_parent_node (container));
}
}
- fragment = webkit_dom_range_clone_contents (range_clone, NULL);
- if (!webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment))) {
+
+ if (!fragment)
+ fragment = webkit_dom_range_clone_contents (range_clone, NULL);
+ if (removing_from_anchor)
+ g_object_set_data (G_OBJECT (fragment), "-x-evo-removing-from-anchor",
GINT_TO_POINTER (1));
+ node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+ if (!node) {
g_free (ev);
e_html_editor_web_extension_unblock_selection_changed_callback (extension);
g_object_unref (range);
g_object_unref (range_clone);
g_object_unref (dom_selection);
+ g_warning ("History event was not saved for %s key", delete_key ? "Delete" :
"Backspace");
return;
}
@@ -7631,8 +7806,15 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
webkit_dom_dom_selection_remove_all_ranges (dom_selection);
webkit_dom_dom_selection_add_range (dom_selection, range_clone);
} else {
+ gboolean selection_saved = FALSE;
WebKitDOMRange *tmp_range;
+ if (webkit_dom_document_get_element_by_id (document,
"-x-evo-selection-start-marker"))
+ selection_saved = TRUE;
+
+ if (selection_saved)
+ dom_selection_restore (document);
+
tmp_range = webkit_dom_range_clone_range (range_clone, NULL);
/* Prepare the selection to the right position after
* delete and save it. */
@@ -7647,8 +7829,19 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
webkit_dom_dom_selection_remove_all_ranges (dom_selection);
webkit_dom_dom_selection_add_range (dom_selection, tmp_range);
g_object_unref (tmp_range);
+
+ if (selection_saved)
+ dom_selection_save (document);
}
} else {
+ gboolean selection_saved = FALSE;
+
+ if (webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker"))
+ selection_saved = TRUE;
+
+ if (selection_saved)
+ dom_selection_restore (document);
+
if (delete_key) {
dom_selection_get_coordinates (
document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x,
&ev->after.end.y);
@@ -7661,34 +7854,51 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
ev->after.end.x = ev->after.start.x;
ev->after.end.y = ev->after.start.y;
}
+
+ if (selection_saved)
+ dom_selection_save (document);
}
g_object_unref (range_clone);
if (delete_key) {
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (fragment),
- WEBKIT_DOM_NODE (
- dom_create_selection_marker (document, FALSE)),
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
- NULL);
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (fragment),
- WEBKIT_DOM_NODE (
- dom_create_selection_marker (document, TRUE)),
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
- NULL);
+ if (!WEBKIT_DOM_IS_ELEMENT (node)) {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (
+ dom_create_selection_marker (document, FALSE)),
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+ NULL);
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (
+ dom_create_selection_marker (document, TRUE)),
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+ NULL);
+ }
} else {
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (fragment),
- WEBKIT_DOM_NODE (
- dom_create_selection_marker (document, TRUE)),
- NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (fragment),
- WEBKIT_DOM_NODE (
- dom_create_selection_marker (document, FALSE)),
- NULL);
+ if (!WEBKIT_DOM_IS_ELEMENT (node)) {
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (
+ dom_create_selection_marker (document, TRUE)),
+ NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (
+ dom_create_selection_marker (document, FALSE)),
+ NULL);
+ }
+ }
+
+ /* If concatenating two blocks with pressing Delete on the end
+ * of the previous one and the next node contain content that
+ * is wrapped on multiple lines, the last line will by separated
+ * by WebKit to the separate block. To avoid it let's remove
+ * all quoting and wrapping from the next paragraph. */
+ if (next_block) {
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (next_block));
+ dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (next_block));
}
e_html_editor_web_extension_unblock_selection_changed_callback (extension);
@@ -7810,6 +8020,9 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
g_object_unref (range);
g_object_unref (dom_selection);
+ g_object_set_data (G_OBJECT (fragment), "-x-evo-delete-key", GINT_TO_POINTER (delete_key));
+ g_object_set_data (G_OBJECT (fragment), "-x-evo-control-key", GINT_TO_POINTER (control_key));
+
ev->data.fragment = fragment;
manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
@@ -7820,7 +8033,8 @@ gboolean
dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
guint key_val,
- guint state)
+ guint state,
+ gboolean delete_key)
{
gboolean collapsed = FALSE;
WebKitDOMElement *selection_start_marker, *selection_end_marker;
@@ -7839,15 +8053,15 @@ dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *documen
return FALSE;
if (collapsed) {
- WebKitDOMNode *next_sibling;
+ WebKitDOMNode *next_block;
block = get_parent_block_node_from_child (
WEBKIT_DOM_NODE (selection_start_marker));
- next_sibling = webkit_dom_node_get_next_sibling (block);
+ next_block = webkit_dom_node_get_next_sibling (block);
/* Next block is quoted content */
- if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling))
+ if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_block))
goto restore;
/* Delete was pressed in block without any content */
@@ -7863,11 +8077,27 @@ dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *documen
save_history_for_delete_or_backspace (
document, extension, key_val == GDK_KEY_Delete, (state &
GDK_CONTROL_MASK) != 0);
- /* Remove the empty block and move caret into the beginning of the citation */
+ /* Remove the empty block and move caret to the right place. */
remove_node (block);
- dom_move_caret_into_element (
- document, WEBKIT_DOM_ELEMENT (next_sibling), TRUE);
+ if (delete_key) {
+ /* To the beginning of the next block. */
+ dom_move_caret_into_element (
+ document, WEBKIT_DOM_ELEMENT (next_block), TRUE);
+ } else {
+ WebKitDOMNode *prev_block;
+
+ /* On the end of previous block. */
+ prev_block = webkit_dom_node_get_previous_sibling (next_block);
+ while (prev_block && WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (prev_block))
+ prev_block = webkit_dom_node_get_last_child (prev_block);
+
+ if (prev_block)
+ dom_move_caret_into_element (
+ document,
+ WEBKIT_DOM_ELEMENT (prev_block),
+ FALSE);
+ }
return TRUE;
}
@@ -7895,12 +8125,6 @@ dom_fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *documen
if (!element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-quoted"))
goto restore;
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (node)),
- WEBKIT_DOM_NODE (selection_start_marker),
- WEBKIT_DOM_NODE (node),
- NULL);
-
block = get_parent_block_node_from_child (
WEBKIT_DOM_NODE (selection_start_marker));
end_block = get_parent_block_node_from_child (
@@ -7956,48 +8180,73 @@ static gboolean
split_citation (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
- EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorHistoryEvent *ev = NULL;
EHTMLEditorUndoRedoManager *manager;
WebKitDOMElement *element;
- ev = g_new0 (EHTMLEditorHistoryEvent, 1);
- ev->type = HISTORY_CITATION_SPLIT;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
- dom_selection_get_coordinates (
- document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, &ev->before.end.y);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_CITATION_SPLIT;
- if (!dom_selection_is_collapsed (document)) {
- WebKitDOMDocumentFragment *fragment;
- WebKitDOMDOMWindow *dom_window;
- WebKitDOMDOMSelection *dom_selection;
- WebKitDOMRange *range;
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x,
&ev->before.end.y);
- dom_window = webkit_dom_document_get_default_view (document);
- dom_selection = webkit_dom_dom_window_get_selection (dom_window);
- g_object_unref (dom_window);
+ if (!dom_selection_is_collapsed (document)) {
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
- if (!webkit_dom_dom_selection_get_range_count (dom_selection)) {
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+ g_object_unref (dom_window);
+
+ if (!webkit_dom_dom_selection_get_range_count (dom_selection)) {
+ g_object_unref (dom_selection);
+ return FALSE;
+ }
+
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+
+ g_object_unref (range);
g_object_unref (dom_selection);
- return FALSE;
- }
- range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
- fragment = webkit_dom_range_clone_contents (range, NULL);
+ ev->data.fragment = fragment;
+ } else {
+ WebKitDOMElement *selection_end;
+ WebKitDOMNode *sibling;
- g_object_unref (range);
- g_object_unref (dom_selection);
+ dom_selection_save (document);
- ev->data.fragment = fragment;
- } else
- ev->data.fragment = NULL;
+ selection_end = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
+
+ sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end));
+ if (!sibling || (WEBKIT_DOM_IS_HTML_BR_ELEMENT (sibling) &&
+ !element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-wrap-br"))) {
+ WebKitDOMDocumentFragment *fragment;
+
+ fragment = webkit_dom_document_create_document_fragment (document);
+ ev->data.fragment = fragment;
+ } else {
+ ev->data.fragment = NULL;
+ }
+
+ dom_selection_restore (document);
+ }
+ }
element = dom_insert_new_line_into_citation (document, extension, "");
- dom_selection_get_coordinates (
- document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
+ if (ev) {
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
- manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
- e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
return element != NULL;
}
@@ -8157,6 +8406,7 @@ dom_delete_character_from_quoted_line_start (WebKitDOMDocument *document,
guint key_val,
guint state)
{
+ gboolean success = FALSE;
WebKitDOMElement *element;
WebKitDOMNode *node, *beginning;
@@ -8178,46 +8428,112 @@ dom_delete_character_from_quoted_line_start (WebKitDOMDocument *document,
/* We have to be on the end of line. */
if (webkit_dom_node_get_next_sibling (node))
- return FALSE;
+ goto out;
/* Before the caret is just text. */
node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
if (!(node && WEBKIT_DOM_IS_TEXT (node)))
- return FALSE;
+ goto out;
/* There is just one character. */
if (webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (node)) != 1)
- return FALSE;
+ goto out;
beginning = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (node));
if (!(beginning && WEBKIT_DOM_IS_ELEMENT (beginning)))
- return FALSE;
+ goto out;
/* Before the text is the beginning of line. */
if (!(element_has_class (WEBKIT_DOM_ELEMENT (beginning), "-x-evo-quoted")))
- return FALSE;
+ goto out;
- if (key_val != ~0)
- save_history_for_delete_or_backspace (
- document, extension, key_val == GDK_KEY_Delete, (state & GDK_CONTROL_MASK) != 0);
+ /* If we are just on the beginning of the line and not on the beginning of
+ * the block we need to remove the last character ourselves as well, otherwise
+ * WebKit will put the caret to wrong position. */
+ if (webkit_dom_node_get_previous_sibling (beginning)) {
+ EHTMLEditorHistoryEvent *ev = NULL;
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMNode *prev_sibling;
- element = webkit_dom_node_get_parent_element (beginning);
+ if (key_val != ~0) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
- dom_remove_quoting_from_element (element);
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (
- webkit_dom_document_create_element (document, "br", NULL)),
- NULL);
+ fragment = webkit_dom_document_create_document_fragment (document);
+ }
- webkit_dom_element_set_attribute (element, "data-no-quote", "", NULL);
+ prev_sibling = webkit_dom_node_get_previous_sibling (beginning);
+ if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (prev_sibling)) {
+ if (key_val != ~0)
+ webkit_dom_node_append_child (WEBKIT_DOM_NODE (fragment), prev_sibling, NULL);
+ else
+ remove_node (prev_sibling);
+ }
- remove_node (node);
+ prev_sibling = webkit_dom_node_get_previous_sibling (beginning);
+ if (WEBKIT_DOM_IS_ELEMENT (prev_sibling) &&
+ webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (prev_sibling),
"data-hidden-space")) {
+ if (key_val != ~0)
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (fragment),
+ prev_sibling,
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+ NULL);
+ else
+ remove_node (prev_sibling);
+ }
+
+ if (key_val != ~0)
+ webkit_dom_node_append_child (WEBKIT_DOM_NODE (fragment), beginning, NULL);
+ else
+ remove_node (beginning);
+
+ if (key_val != ~0) {
+ EHTMLEditorUndoRedoManager *manager;
+ webkit_dom_node_append_child (WEBKIT_DOM_NODE (fragment), node, NULL);
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->after.start.x,
+ &ev->after.start.y,
+ &ev->after.end.x,
+ &ev->after.end.y);
+
+ ev->data.fragment = fragment;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ } else
+ remove_node (node);
+
+ dom_selection_restore (document);
+
+ return TRUE;
+ }
+
+ if (key_val != ~0)
+ save_history_for_delete_or_backspace (
+ document, extension, key_val == GDK_KEY_Delete, (state & GDK_CONTROL_MASK) != 0);
+
+ element = webkit_dom_node_get_parent_element (beginning);
+ remove_node (WEBKIT_DOM_NODE (element));
+
+ success = TRUE;
+ out:
dom_selection_restore (document);
- return TRUE;
+ if (success)
+ dom_insert_new_line_into_citation (document, extension, NULL);
+
+ return success;
}
static gboolean
@@ -8233,76 +8549,76 @@ static gboolean
insert_tabulator (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
- EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
gboolean success;
- ev = g_new0 (EHTMLEditorHistoryEvent, 1);
- ev->type = HISTORY_INPUT;
-
- if (!dom_selection_is_collapsed (document)) {
- WebKitDOMRange *tmp_range;
-
- tmp_range = dom_get_current_range (document);
- insert_delete_event (document, extension, tmp_range);
- g_object_unref (tmp_range);
- }
-
- dom_selection_get_coordinates (
- document,
- &ev->before.start.x,
- &ev->before.start.y,
- &ev->before.end.x,
- &ev->before.end.y);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
- ev->before.end.x = ev->before.start.x;
- ev->before.end.y = ev->before.start.y;
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_INPUT;
- success = dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, "\t");
+ if (!dom_selection_is_collapsed (document)) {
+ WebKitDOMRange *tmp_range;
- if (success) {
- EHTMLEditorUndoRedoManager *manager;
- WebKitDOMElement *element;
- WebKitDOMDocumentFragment *fragment;
+ tmp_range = dom_get_current_range (document);
+ insert_delete_event (document, extension, tmp_range);
+ g_object_unref (tmp_range);
+ }
dom_selection_get_coordinates (
document,
- &ev->after.start.x,
- &ev->after.start.y,
- &ev->after.end.x,
- &ev->after.end.y);
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
- fragment = webkit_dom_document_create_document_fragment (document);
- element = webkit_dom_document_create_element (document, "span", NULL);
- webkit_dom_html_element_set_inner_text (
- WEBKIT_DOM_HTML_ELEMENT (element), "\t", NULL);
- webkit_dom_element_set_attribute (
- element, "class", "Apple-tab-span", NULL);
- webkit_dom_element_set_attribute (
- element, "style", "white-space:pre", NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (fragment), WEBKIT_DOM_NODE (element), NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (fragment),
- WEBKIT_DOM_NODE (dom_create_selection_marker (document, TRUE)),
- NULL);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (fragment),
- WEBKIT_DOM_NODE (dom_create_selection_marker (document, FALSE)),
- NULL);
- ev->data.fragment = fragment;
+ ev->before.end.x = ev->before.start.x;
+ ev->before.end.y = ev->before.start.y;
+ }
- manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
- e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ success = dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, "\t");
- e_html_editor_web_extension_set_content_changed (extension);
- } else {
- EHTMLEditorUndoRedoManager *manager;
+ if (ev) {
+ if (success) {
+ WebKitDOMElement *element;
+ WebKitDOMDocumentFragment *fragment;
- manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ dom_selection_get_coordinates (
+ document,
+ &ev->after.start.x,
+ &ev->after.start.y,
+ &ev->after.end.x,
+ &ev->after.end.y);
- e_html_editor_undo_redo_manager_remove_current_history_event (manager);
- e_html_editor_undo_redo_manager_remove_current_history_event (manager);
- g_free (ev);
+ fragment = webkit_dom_document_create_document_fragment (document);
+ element = webkit_dom_document_create_element (document, "span", NULL);
+ webkit_dom_html_element_set_inner_text (
+ WEBKIT_DOM_HTML_ELEMENT (element), "\t", NULL);
+ webkit_dom_element_set_attribute (
+ element, "class", "Apple-tab-span", NULL);
+ webkit_dom_element_set_attribute (
+ element, "style", "white-space:pre", NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment), WEBKIT_DOM_NODE (element), NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (dom_create_selection_marker (document, TRUE)),
+ NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ WEBKIT_DOM_NODE (dom_create_selection_marker (document, FALSE)),
+ NULL);
+ ev->data.fragment = fragment;
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ e_html_editor_web_extension_set_content_changed (extension);
+ } else {
+ e_html_editor_undo_redo_manager_remove_current_history_event (manager);
+ e_html_editor_undo_redo_manager_remove_current_history_event (manager);
+ g_free (ev);
+ }
}
return success;
@@ -8468,138 +8784,273 @@ change_smiley_to_plain_text (WebKitDOMDocument *document)
}
gboolean
-dom_process_on_key_press (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension,
- guint key_val,
- guint state)
+key_press_event_process_return_key (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
- e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+ gboolean first_cell = FALSE;
+ WebKitDOMNode *table = NULL;
- if (key_val == GDK_KEY_Tab || key_val == GDK_KEY_ISO_Left_Tab) {
- if (jump_to_next_table_cell (document, key_val == GDK_KEY_ISO_Left_Tab))
+ /* Return pressed in the beginning of the first cell will insert
+ * new block before the table (and move the caret there) if none
+ * is already there, otherwise it will act as normal return. */
+ if (selection_is_in_table (document, &first_cell, &table) && first_cell) {
+ WebKitDOMNode *node;
+
+ node = webkit_dom_node_get_previous_sibling (table);
+ if (!node) {
+ node = webkit_dom_node_get_next_sibling (table);
+ node = webkit_dom_node_clone_node (node, FALSE);
+ webkit_dom_node_append_child (
+ node,
+ WEBKIT_DOM_NODE (webkit_dom_document_create_element (
+ document, "br", NULL)),
+ NULL);
+ dom_add_selection_markers_into_element_start (
+ document, WEBKIT_DOM_ELEMENT (node), NULL, NULL);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (table),
+ node,
+ table,
+ NULL);
+ dom_selection_restore (document);
+ e_html_editor_web_extension_set_content_changed (extension);
return TRUE;
+ }
+ }
- if (key_val == GDK_KEY_Tab)
- return insert_tabulator (document, extension);
- else
- return FALSE;
+ /* When user presses ENTER in a citation block, WebKit does
+ * not break the citation automatically, so we need to use
+ * the special command to do it. */
+ if (dom_selection_is_citation (document)) {
+ dom_remove_input_event_listener_from_body (document, extension);
+ if (split_citation (document, extension)) {
+ e_html_editor_web_extension_set_content_changed (extension);
+ return TRUE;
+ }
+ return FALSE;
}
- if (is_return_key (key_val)) {
- gboolean first_cell = FALSE;
- WebKitDOMNode *table = NULL;
+ /* If the ENTER key is pressed inside an empty list item then the list
+ * is broken into two and empty paragraph is inserted between lists. */
+ if (return_pressed_in_empty_list_item (document, extension, TRUE))
+ return TRUE;
- /* Return pressed in the beginning of the first cell will insert
- * new block before the table (and move the caret there) if none
- * is already there, otherwise it will act as normal return. */
- if (selection_is_in_table (document, &first_cell, &table) && first_cell) {
- WebKitDOMNode *node;
+ return FALSE;
+}
- node = webkit_dom_node_get_previous_sibling (table);
- if (!node) {
- node = webkit_dom_node_get_next_sibling (table);
- node = webkit_dom_node_clone_node (node, FALSE);
- webkit_dom_node_append_child (
- node,
- WEBKIT_DOM_NODE (webkit_dom_document_create_element (
- document, "br", NULL)),
- NULL);
- dom_add_selection_markers_into_element_start (
- document, WEBKIT_DOM_ELEMENT (node), NULL, NULL);
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (table),
- node,
- table,
- NULL);
- dom_selection_restore (document);
- e_html_editor_web_extension_set_content_changed (extension);
- return TRUE;
- }
+gboolean
+key_press_event_process_backspace_key (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ /* BackSpace pressed in the beginning of quoted content changes
+ * format to normal and inserts text into body */
+ if (dom_selection_is_collapsed (document)) {
+ dom_selection_save (document);
+ if (dom_change_quoted_block_to_normal (document, extension) || delete_hidden_space (document,
extension)) {
+ dom_selection_restore (document);
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ e_html_editor_web_extension_set_content_changed (extension);
+ return TRUE;
}
+ dom_selection_restore (document);
+ }
- /* When user presses ENTER in a citation block, WebKit does
- * not break the citation automatically, so we need to use
- * the special command to do it. */
- if (dom_selection_is_citation (document)) {
- dom_remove_input_event_listener_from_body (document, extension);
- if (split_citation (document, extension)) {
- e_html_editor_web_extension_set_content_changed (extension);
- return TRUE;
- }
- return FALSE;
- }
+ /* BackSpace in indented block decrease indent level by one */
+ if (dom_selection_is_indented (document) &&
+ dom_selection_is_collapsed (document)) {
+ WebKitDOMElement *selection_start;
+ WebKitDOMNode *prev_sibling;
+
+ dom_selection_save (document);
+ selection_start = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
- /* If the ENTER key is pressed inside an empty list item then the list
- * is broken into two and empty paragraph is inserted between lists. */
- if (return_pressed_in_empty_list_item (document, extension, TRUE))
+ /* Empty text node before caret */
+ prev_sibling = webkit_dom_node_get_previous_sibling (
+ WEBKIT_DOM_NODE (selection_start));
+ if (prev_sibling && WEBKIT_DOM_IS_TEXT (prev_sibling))
+ if (webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (prev_sibling))
== 0)
+ prev_sibling = webkit_dom_node_get_previous_sibling (prev_sibling);
+
+ dom_selection_restore (document);
+ if (!prev_sibling) {
+ dom_selection_unindent (document, extension);
+ e_html_editor_web_extension_set_content_changed (extension);
return TRUE;
+ }
}
- if (key_val == GDK_KEY_BackSpace) {
- /* BackSpace pressed in the beginning of quoted content changes
- * format to normal and inserts text into body */
- if (dom_selection_is_collapsed (document)) {
- dom_selection_save (document);
- if (dom_change_quoted_block_to_normal (document, extension)) {
- dom_selection_restore (document);
- dom_force_spell_check_for_current_paragraph (document, extension);
- e_html_editor_web_extension_set_content_changed (extension);
- return TRUE;
- }
+ if (prevent_from_deleting_last_element_in_body (document))
+ return TRUE;
+
+ return FALSE;
+}
+
+gboolean
+key_press_event_process_delete_or_backspace_key (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ guint key_val,
+ guint state,
+ gboolean delete)
+{
+ gboolean html_mode;
+ gboolean local_delete;
+
+ html_mode = e_html_editor_web_extension_get_html_mode (extension);
+ local_delete = (key_val == GDK_KEY_Delete) || delete;
+
+ if (!html_mode && e_html_editor_web_extension_get_magic_links_enabled (extension)) {
+ /* If deleting something in a smiley it won't be a smiley
+ * anymore (at least from Evolution' POV), so remove all
+ * the elements that are hidden in the wrapper and leave
+ * just the text. Also this ensures that when a smiley is
+ * recognized and we press the BackSpace key we won't delete
+ * the UNICODE_HIDDEN_SPACE, but we will correctly delete
+ * the last character of smiley. */
+ change_smiley_to_plain_text (document);
+ }
+
+ if (!local_delete && !html_mode &&
+ dom_delete_character_from_quoted_line_start (document, extension, key_val, state))
+ goto out;
+
+ if (dom_fix_structure_after_delete_before_quoted_content (document, extension, key_val, state, FALSE))
+ goto out;
+
+ if (local_delete) {
+ WebKitDOMElement *selection_start_marker;
+ WebKitDOMNode *sibling, *block, *next_block;
+
+ /* This needs to be performed just in plain text mode
+ * and when the selection is collapsed. */
+ if (html_mode || !dom_selection_is_collapsed (document))
+ return FALSE;
+
+ dom_selection_save (document);
+
+ selection_start_marker = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ sibling = webkit_dom_node_get_previous_sibling (
+ WEBKIT_DOM_NODE (selection_start_marker));
+ /* Check if the key was pressed in the beginning of block. */
+ if (!(sibling && WEBKIT_DOM_IS_ELEMENT (sibling) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-quoted"))) {
dom_selection_restore (document);
+ return FALSE;
}
- /* BackSpace in indented block decrease indent level by one */
- if (dom_selection_is_indented (document) &&
- dom_selection_is_collapsed (document)) {
- WebKitDOMElement *selection_start;
- WebKitDOMNode *prev_sibling;
+ sibling = webkit_dom_node_get_next_sibling (
+ WEBKIT_DOM_NODE (selection_start_marker));
+ sibling = webkit_dom_node_get_next_sibling (sibling);
- dom_selection_save (document);
- selection_start = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-start-marker");
+ /* And also the current block was empty. */
+ if (!(!sibling || (sibling && WEBKIT_DOM_IS_HTML_BR_ELEMENT (sibling) &&
+ !element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-wrap-br")))) {
+ dom_selection_restore (document);
+ return FALSE;
+ }
- /* Empty text node before caret */
- prev_sibling = webkit_dom_node_get_previous_sibling (
- WEBKIT_DOM_NODE (selection_start));
- if (prev_sibling && WEBKIT_DOM_IS_TEXT (prev_sibling))
- if (webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA
(prev_sibling)) == 0)
- prev_sibling = webkit_dom_node_get_previous_sibling (prev_sibling);
+ block = get_parent_block_node_from_child (
+ WEBKIT_DOM_NODE (selection_start_marker));
+ next_block = webkit_dom_node_get_next_sibling (block);
+
+ remove_node (block);
+
+ dom_move_caret_into_element (
+ document, WEBKIT_DOM_ELEMENT (next_block), TRUE);
+
+ goto out;
+ } else {
+ /* Concatenating a non-quoted block with Backspace key to the
+ * previous block that is inside a quoted content. */
+ WebKitDOMElement *selection_start_marker;
+ WebKitDOMNode *node, *block, *prev_block, *last_child, *child;
+
+ if (html_mode || !dom_selection_is_collapsed (document) ||
+ dom_selection_is_citation (document))
+ return FALSE;
+
+ dom_selection_save (document);
+
+ selection_start_marker = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (selection_start_marker));
+ if (node) {
dom_selection_restore (document);
- if (!prev_sibling) {
- dom_selection_unindent (document, extension);
- e_html_editor_web_extension_set_content_changed (extension);
- return TRUE;
- }
+ return FALSE;
}
- if (prevent_from_deleting_last_element_in_body (document))
- return TRUE;
+ block = get_parent_block_node_from_child (
+ WEBKIT_DOM_NODE (selection_start_marker));
+
+ prev_block = webkit_dom_node_get_previous_sibling (block);
+ if (!prev_block || !WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (prev_block)) {
+ dom_selection_restore (document);
+ return FALSE;
+ }
+
+ last_child = webkit_dom_node_get_last_child (prev_block);
+ while (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (last_child))
+ last_child = webkit_dom_node_get_last_child (last_child);
+
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (last_child));
+ dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (last_child));
+
+ node = webkit_dom_node_get_last_child (last_child);
+ if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (node))
+ remove_node (node);
+
+ while ((child = webkit_dom_node_get_first_child (block)))
+ webkit_dom_node_append_child (last_child, child, NULL);
+
+ remove_node (block);
+
+ if (WEBKIT_DOM_IS_ELEMENT (last_child))
+ wrap_and_quote_element (document, extension, WEBKIT_DOM_ELEMENT (last_child));
+
+ dom_selection_restore (document);
+
+ goto out;
}
- if (key_val == GDK_KEY_Delete || key_val == GDK_KEY_BackSpace) {
- gboolean html_mode;
+ return FALSE;
+ out:
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ e_html_editor_web_extension_set_content_changed (extension);
- html_mode = e_html_editor_web_extension_get_html_mode (extension);
- if (!html_mode && e_html_editor_web_extension_get_magic_links_enabled (extension)) {
- /* If deleting something in a smiley it won't be a smiley
- * anymore (at least from Evolution' POV), so remove all
- * the elements that are hidden in the wrapper and leave
- * just the text. Also this ensures that when a smiley is
- * recognized and we press the BackSpace key we won't delete
- * the UNICODE_HIDDEN_SPACE, but we will correctly delete
- * the last character of smiley. */
- change_smiley_to_plain_text (document);
- }
- if (key_val == GDK_KEY_BackSpace && !html_mode) {
- if (dom_delete_character_from_quoted_line_start (document, extension, key_val,
state)) {
- e_html_editor_web_extension_set_content_changed (extension);
- return TRUE;
- }
- }
- if (dom_fix_structure_after_delete_before_quoted_content (document, extension, key_val,
state))
+ return TRUE;
+}
+
+gboolean
+dom_process_on_key_press (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ guint key_val,
+ guint state)
+{
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+
+ if (key_val == GDK_KEY_Tab || key_val == GDK_KEY_ISO_Left_Tab) {
+ if (jump_to_next_table_cell (document, key_val == GDK_KEY_ISO_Left_Tab))
return TRUE;
+
+ if (key_val == GDK_KEY_Tab)
+ return insert_tabulator (document, extension);
+ else
+ return FALSE;
+ }
+
+ if (is_return_key (key_val) && key_press_event_process_return_key (document, extension))
+ return TRUE;
+
+ if (key_val == GDK_KEY_BackSpace &&
+ key_press_event_process_backspace_key (document, extension)) {
+ return TRUE;
+ }
+
+ if ((key_val == GDK_KEY_Delete || key_val == GDK_KEY_BackSpace) &&
+ key_press_event_process_delete_or_backspace_key (document, extension, key_val, state, key_val ==
GDK_KEY_Delete)) {
+ return TRUE;
}
return FALSE;
diff --git a/web-extensions/composer/e-html-editor-view-dom-functions.h
b/web-extensions/composer/e-html-editor-view-dom-functions.h
index bcc9d59..8fc6691 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.h
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.h
@@ -169,7 +169,8 @@ gboolean dom_fix_structure_after_delete_before_quoted_content
(WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
guint key_val,
- guint state);
+ guint state,
+ gboolean delete_key);
void dom_disable_quote_marks_select (WebKitDOMDocument *document);
void dom_remove_node_and_parents_if_empty
(WebKitDOMNode *node);
@@ -180,6 +181,34 @@ gboolean return_pressed_in_empty_list_item
void dom_merge_siblings_if_necessarry
(WebKitDOMDocument *document,
WebKitDOMDocumentFragment *deleted_content);
+void body_key_up_event_process_return_key
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+gboolean key_press_event_process_backspace_key
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+gboolean key_press_event_process_delete_or_backspace_key
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ guint key_val,
+ guint state,
+ gboolean delete);
+void body_input_event_process (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMEvent *event);
+void body_key_up_event_process_backspace_or_delete
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ gboolean delete);
+gboolean key_press_event_process_return_key
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+WebKitDOMElement *
+ wrap_and_quote_element (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMElement *element);
+gint get_citation_level (WebKitDOMNode *node,
+ gboolean set_plaintext_quoted);
G_END_DECLS
diff --git a/web-extensions/composer/e-html-editor-web-extension.c
b/web-extensions/composer/e-html-editor-web-extension.c
index b7fa35f..6a47af6 100644
--- a/web-extensions/composer/e-html-editor-web-extension.c
+++ b/web-extensions/composer/e-html-editor-web-extension.c
@@ -96,6 +96,7 @@ struct _EHTMLEditorWebExtensionPrivate {
gboolean dont_save_history_in_body_input;
gboolean composition_in_progress;
gboolean is_pasting_content_from_itself;
+ gboolean renew_history_after_coordinates;
GHashTable *inline_images;
@@ -2983,6 +2984,7 @@ e_html_editor_web_extension_init (EHTMLEditorWebExtension *extension)
extension->priv->dont_save_history_in_body_input = FALSE;
extension->priv->is_pasting_content_from_itself = FALSE;
extension->priv->composition_in_progress = FALSE;
+ extension->priv->renew_history_after_coordinates = TRUE;
extension->priv->node_under_mouse_click = NULL;
@@ -3656,6 +3658,19 @@ e_html_editor_web_extension_is_pasting_content_from_itself (EHTMLEditorWebExtens
return extension->priv->is_pasting_content_from_itself;
}
+gboolean
+e_html_editor_web_extension_get_renew_history_after_coordinates (EHTMLEditorWebExtension *extension)
+{
+ return extension->priv->renew_history_after_coordinates;
+}
+
+void
+e_html_editor_web_extension_set_renew_history_after_coordinates (EHTMLEditorWebExtension *extension,
+ gboolean renew_history_after_coordinates)
+{
+ extension->priv->renew_history_after_coordinates = renew_history_after_coordinates;
+}
+
EHTMLEditorUndoRedoManager *
e_html_editor_web_extension_get_undo_redo_manager (EHTMLEditorWebExtension *extension)
{
diff --git a/web-extensions/composer/e-html-editor-web-extension.h
b/web-extensions/composer/e-html-editor-web-extension.h
index 2d74427..65eca0a 100644
--- a/web-extensions/composer/e-html-editor-web-extension.h
+++ b/web-extensions/composer/e-html-editor-web-extension.h
@@ -216,6 +216,11 @@ void e_html_editor_web_extension_set_dont_save_history_in_body_input
gboolean value);
gboolean e_html_editor_web_extension_is_pasting_content_from_itself
(EHTMLEditorWebExtension *extension);
+gboolean e_html_editor_web_extension_get_renew_history_after_coordinates
+ (EHTMLEditorWebExtension *extension);
+void e_html_editor_web_extension_set_renew_history_after_coordinates
+ (EHTMLEditorWebExtension *extension,
+ gboolean renew_history_after_coordinates);
struct _EHTMLEditorUndoRedoManager *
e_html_editor_web_extension_get_undo_redo_manager
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]