[evolution/wip/webkit2] Bug 724651 - [webkit-composer] Undo or Redo does not work
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/webkit2] Bug 724651 - [webkit-composer] Undo or Redo does not work
- Date: Wed, 22 Apr 2015 13:15:51 +0000 (UTC)
commit 397528dfd75fde454b6af9ac26b9b30eae660384
Author: Tomas Popela <tpopela redhat com>
Date: Tue Apr 21 15:04:30 2015 +0200
Bug 724651 - [webkit-composer] Undo or Redo does not work
Implement the undo and redo operations in EHTMLEditorView. We have
to implement all the stuff ourselves as there was nothing that we
can reuse on WebKit side (at least not now).
e-util/e-html-editor-actions.c | 13 +-
e-util/e-html-editor-cell-dialog.c | 51 +-
e-util/e-html-editor-cell-dialog.h | 1 -
e-util/e-html-editor-hrule-dialog.c | 4 +-
e-util/e-html-editor-image-dialog.c | 8 +-
e-util/e-html-editor-page-dialog.c | 21 +
e-util/e-html-editor-table-dialog.c | 4 +-
e-util/e-html-editor-view.c | 35 +-
e-util/e-html-editor-view.h | 2 +
web-extensions/Makefile.am | 5 +
.../e-html-editor-actions-dom-functions.c | 142 ++-
.../e-html-editor-actions-dom-functions.h | 26 +-
.../e-html-editor-cell-dialog-dom-functions.c | 52 +
.../e-html-editor-cell-dialog-dom-functions.h | 7 +
web-extensions/e-html-editor-history-event.h | 98 +
.../e-html-editor-hrule-dialog-dom-functions.c | 64 +-
.../e-html-editor-hrule-dialog-dom-functions.h | 4 +
.../e-html-editor-image-dialog-dom-functions.c | 51 +
.../e-html-editor-image-dialog-dom-functions.h | 11 +
.../e-html-editor-link-dialog-dom-functions.c | 5 +-
.../e-html-editor-link-dialog-dom-functions.h | 3 +
.../e-html-editor-page-dialog-dom-functions.c | 63 +
.../e-html-editor-page-dialog-dom-functions.h | 38 +
.../e-html-editor-selection-dom-functions.c | 819 +++++++--
.../e-html-editor-selection-dom-functions.h | 28 +-
.../e-html-editor-table-dialog-dom-functions.c | 55 +-
.../e-html-editor-table-dialog-dom-functions.h | 5 +
web-extensions/e-html-editor-undo-redo-manager.c | 1867 ++++++++++++++++++++
web-extensions/e-html-editor-undo-redo-manager.h | 102 ++
web-extensions/e-html-editor-view-dom-functions.c | 796 +++++++--
web-extensions/e-html-editor-view-dom-functions.h | 25 +
web-extensions/e-html-editor-web-extension.c | 194 ++-
web-extensions/e-html-editor-web-extension.h | 19 +-
33 files changed, 4186 insertions(+), 432 deletions(-)
---
diff --git a/e-util/e-html-editor-actions.c b/e-util/e-html-editor-actions.c
index eb7e17a..65a7d86 100644
--- a/e-util/e-html-editor-actions.c
+++ b/e-util/e-html-editor-actions.c
@@ -572,8 +572,7 @@ action_properties_cell_cb (GtkAction *action,
e_html_editor_cell_dialog_new (editor);
}
- e_html_editor_cell_dialog_show (
- E_HTML_EDITOR_CELL_DIALOG (editor->priv->cell_dialog));
+ gtk_window_present (GTK_WINDOW (editor->priv->cell_dialog));
}
static void
@@ -668,8 +667,7 @@ action_redo_cb (GtkAction *action,
EHTMLEditorView *view = e_html_editor_get_view (editor);
if (gtk_widget_has_focus (GTK_WIDGET (view)))
- webkit_web_view_execute_editing_command (
- WEBKIT_WEB_VIEW (view), WEBKIT_EDITING_COMMAND_REDO);
+ e_html_editor_view_redo (view);
}
static void
@@ -737,8 +735,7 @@ action_undo_cb (GtkAction *action,
EHTMLEditorView *view = e_html_editor_get_view (editor);
if (gtk_widget_has_focus (GTK_WIDGET (view)))
- webkit_web_view_execute_editing_command (
- WEBKIT_WEB_VIEW (view), WEBKIT_EDITING_COMMAND_UNDO);
+ e_html_editor_view_undo (view);
}
static void
@@ -749,7 +746,7 @@ action_unindent_cb (GtkAction *action,
if (gtk_widget_has_focus (GTK_WIDGET (view)))
html_editor_call_simple_extension_function (
- editor, "EHTMLEditorSelectionDOMUnindent");
+ editor, "DOMSelectionUnindent");
}
static void
@@ -760,7 +757,7 @@ action_wrap_lines_cb (GtkAction *action,
if (gtk_widget_has_focus (GTK_WIDGET (view)))
html_editor_call_simple_extension_function (
- editor, "EHTMLEditorSelectionDOMWrapLines");
+ editor, "DOMSelectionWrap");
}
static void
diff --git a/e-util/e-html-editor-cell-dialog.c b/e-util/e-html-editor-cell-dialog.c
index 0b58149..e70f52e 100644
--- a/e-util/e-html-editor-cell-dialog.c
+++ b/e-util/e-html-editor-cell-dialog.c
@@ -450,6 +450,19 @@ html_editor_cell_dialog_show (GtkWidget *widget)
if (!web_extension)
return;
+ g_dbus_proxy_call (
+ web_extension,
+ "EHTMLEditorCellDialogMarkCurrentCellElement",
+ g_variant_new (
+ "(ts)",
+ webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)),
+ "-x-evo-table-cell"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+
gtk_toggle_button_set_active (
GTK_TOGGLE_BUTTON (dialog->priv->scope_cell_button), TRUE);
@@ -670,8 +683,8 @@ html_editor_cell_dialog_hide (GtkWidget *widget)
editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
view = e_html_editor_get_view (editor);
- e_html_editor_view_remove_element_attribute (
- view, "#-x-evo-current-cell", "id");
+ e_html_editor_view_call_simple_extension_function_sync (
+ view, "EHTMLEditorCellDialogSaveHistoryOnExit");
GTK_WIDGET_CLASS (e_html_editor_cell_dialog_parent_class)->hide (widget);
}
@@ -982,37 +995,3 @@ e_html_editor_cell_dialog_new (EHTMLEditor *editor)
"title", _("Cell Properties"),
NULL));
}
-
-void
-e_html_editor_cell_dialog_show (EHTMLEditorCellDialog *dialog)
-{
- EHTMLEditor *editor;
- EHTMLEditorView *view;
- EHTMLEditorCellDialogClass *class;
- GDBusProxy *web_extension;
-
- g_return_if_fail (E_IS_HTML_EDITOR_CELL_DIALOG (dialog));
-
- editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
- view = e_html_editor_get_view (editor);
- web_extension = e_html_editor_view_get_web_extension_proxy (view);
- if (!web_extension)
- return;
-
- g_dbus_proxy_call (
- web_extension,
- "EHTMLEditorCellDialogMarkCurrentCellElement",
- g_variant_new (
- "(ts)",
- webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view)),
- "-x-evo-table-cell"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL,
- NULL);
-
- class = E_HTML_EDITOR_CELL_DIALOG_GET_CLASS (dialog);
- GTK_WIDGET_CLASS (class)->show (GTK_WIDGET (dialog));
-}
-
diff --git a/e-util/e-html-editor-cell-dialog.h b/e-util/e-html-editor-cell-dialog.h
index 963e12b..68ae1bb 100644
--- a/e-util/e-html-editor-cell-dialog.h
+++ b/e-util/e-html-editor-cell-dialog.h
@@ -64,7 +64,6 @@ struct _EHTMLEditorCellDialogClass {
GType e_html_editor_cell_dialog_get_type
(void) G_GNUC_CONST;
GtkWidget * e_html_editor_cell_dialog_new (EHTMLEditor *editor);
-void e_html_editor_cell_dialog_show (EHTMLEditorCellDialog *dialog);
G_END_DECLS
diff --git a/e-util/e-html-editor-hrule-dialog.c b/e-util/e-html-editor-hrule-dialog.c
index 4b8ff38..e60bde8 100644
--- a/e-util/e-html-editor-hrule-dialog.c
+++ b/e-util/e-html-editor-hrule-dialog.c
@@ -281,8 +281,8 @@ html_editor_hrule_dialog_hide (GtkWidget *widget)
editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
view = e_html_editor_get_view (editor);
- e_html_editor_view_remove_element_attribute (
- view, "#-x-evo-current-hr", "id");
+ e_html_editor_view_call_simple_extension_function (
+ view, "EHTMLEditorHRuleDialogSaveHistoryOnExit");
GTK_WIDGET_CLASS (e_html_editor_hrule_dialog_parent_class)->hide (widget);
}
diff --git a/e-util/e-html-editor-image-dialog.c b/e-util/e-html-editor-image-dialog.c
index 84d2296..4030986 100644
--- a/e-util/e-html-editor-image-dialog.c
+++ b/e-util/e-html-editor-image-dialog.c
@@ -522,6 +522,9 @@ html_editor_image_dialog_show (GtkWidget *widget)
if (!web_extension)
return;
+ e_html_editor_view_call_simple_extension_function (
+ view, "EHTMLEditorImageDialogMarkImage");
+
result = e_html_editor_view_get_element_attribute (
view, "#-x-evo-current-img", "data-uri");
@@ -690,8 +693,9 @@ html_editor_image_dialog_hide (GtkWidget *widget)
dialog = E_HTML_EDITOR_IMAGE_DIALOG (widget);
editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
view = e_html_editor_get_view (editor);
- e_html_editor_view_remove_element_attribute (
- view, "#-x-evo-current-img", "id");
+
+ e_html_editor_view_call_simple_extension_function (
+ view, "EHTMLEditorImageDialogSaveHistoryOnExit");
GTK_WIDGET_CLASS (e_html_editor_image_dialog_parent_class)->hide (widget);
}
diff --git a/e-util/e-html-editor-page-dialog.c b/e-util/e-html-editor-page-dialog.c
index 795c748..269be51 100644
--- a/e-util/e-html-editor-page-dialog.c
+++ b/e-util/e-html-editor-page-dialog.c
@@ -342,6 +342,9 @@ html_editor_page_dialog_show (GtkWidget *widget)
if (!web_extension)
return;
+ e_html_editor_view_call_simple_extension_function (
+ view, "EHTMLEditorPageDialogSaveHistory");
+
result = e_html_editor_view_get_element_attribute (
view, "body", "data-uri");
@@ -441,6 +444,23 @@ html_editor_page_dialog_show (GtkWidget *widget)
}
static void
+html_editor_page_dialog_hide (GtkWidget *widget)
+{
+ EHTMLEditor *editor;
+ EHTMLEditorView *view;
+ EHTMLEditorPageDialog *dialog;
+
+ dialog = E_HTML_EDITOR_PAGE_DIALOG (widget);
+ editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
+ view = e_html_editor_get_view (editor);
+
+ e_html_editor_view_call_simple_extension_function (
+ view, "EHTMLEditorPageDialogSaveHistoryOnExit");
+
+ GTK_WIDGET_CLASS (e_html_editor_page_dialog_parent_class)->hide (widget);
+}
+
+static void
e_html_editor_page_dialog_class_init (EHTMLEditorPageDialogClass *class)
{
GtkWidgetClass *widget_class;
@@ -449,6 +469,7 @@ e_html_editor_page_dialog_class_init (EHTMLEditorPageDialogClass *class)
widget_class = GTK_WIDGET_CLASS (class);
widget_class->show = html_editor_page_dialog_show;
+ widget_class->hide = html_editor_page_dialog_hide;
}
static void
diff --git a/e-util/e-html-editor-table-dialog.c b/e-util/e-html-editor-table-dialog.c
index ab7c420..92e606f 100644
--- a/e-util/e-html-editor-table-dialog.c
+++ b/e-util/e-html-editor-table-dialog.c
@@ -754,8 +754,8 @@ html_editor_table_dialog_hide (GtkWidget *widget)
editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
view = e_html_editor_get_view (editor);
- e_html_editor_view_remove_element_attribute (
- view, "#-x-evo-current-table", "id");
+ e_html_editor_view_call_simple_extension_function (
+ view, "EHTMLEditorTableDialogSaveHistoryOnExit");
GTK_WIDGET_CLASS (e_html_editor_table_dialog_parent_class)->hide (widget);
}
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 805d411..5da9b4e 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -149,6 +149,7 @@ html_editor_view_can_redo_cb (WebKitWebView *webkit_web_view,
{
gboolean value;
+/* FIXME WK2 Connect to extension */
value = webkit_web_view_can_execute_editing_command_finish (
webkit_web_view, result, NULL);
@@ -171,6 +172,7 @@ html_editor_view_can_undo_cb (WebKitWebView *webkit_web_view,
{
gboolean value;
+/* FIXME WK2 Connect to extension */
value = webkit_web_view_can_execute_editing_command_finish (
webkit_web_view, result, NULL);
@@ -186,6 +188,22 @@ html_editor_view_can_undo (EHTMLEditorView *view)
return view->priv->can_undo;
}
+void
+e_html_editor_view_undo (EHTMLEditorView *view)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_VIEW (view));
+
+ e_html_editor_view_call_simple_extension_function (view, "DOMUndo");
+}
+
+void
+e_html_editor_view_redo (EHTMLEditorView *view)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_VIEW (view));
+
+ e_html_editor_view_call_simple_extension_function (view, "DOMUndo");
+}
+
static void
html_editor_view_user_changed_contents_cb (EHTMLEditorView *view)
{
@@ -194,20 +212,6 @@ html_editor_view_user_changed_contents_cb (EHTMLEditorView *view)
web_view = WEBKIT_WEB_VIEW (view);
e_html_editor_view_set_changed (view, TRUE);
-
- webkit_web_view_can_execute_editing_command (
- WEBKIT_WEB_VIEW (web_view),
- WEBKIT_EDITING_COMMAND_REDO,
- NULL, /* cancellable */
- (GAsyncReadyCallback) html_editor_view_can_redo_cb,
- view);
-
- webkit_web_view_can_execute_editing_command (
- WEBKIT_WEB_VIEW (web_view),
- WEBKIT_EDITING_COMMAND_UNDO,
- NULL, /* cancellable */
- (GAsyncReadyCallback) html_editor_view_can_undo_cb,
- view);
}
static void
@@ -521,8 +525,6 @@ html_editor_view_dispose (GObject *object)
priv = E_HTML_EDITOR_VIEW_GET_PRIVATE (object);
- g_clear_object (&priv->selection);
-
if (priv->aliasing_settings != NULL) {
g_signal_handlers_disconnect_by_data (priv->aliasing_settings, object);
g_object_unref (priv->aliasing_settings);
@@ -1550,7 +1552,6 @@ e_html_editor_view_set_html_mode (EHTMLEditorView *view,
view->priv->html_mode = html_mode;
-
e_html_editor_view_call_simple_extension_function_sync (
view, "DOMProcessContentAfterModeChange");
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index e4ad31c..e54657f 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -106,6 +106,8 @@ EHTMLEditorSelection *
gboolean e_html_editor_view_get_changed (EHTMLEditorView *view);
void e_html_editor_view_set_changed (EHTMLEditorView *view,
gboolean changed);
+void e_html_editor_view_undo (EHTMLEditorView *view);
+void e_html_editor_view_redo (EHTMLEditorView *view);
gboolean e_html_editor_view_get_html_mode
(EHTMLEditorView *view);
void e_html_editor_view_set_html_mode
diff --git a/web-extensions/Makefile.am b/web-extensions/Makefile.am
index ab28cae..ad2b7ae 100644
--- a/web-extensions/Makefile.am
+++ b/web-extensions/Makefile.am
@@ -49,12 +49,15 @@ libehtmleditorwebextension_la_SOURCES = \
e-dom-utils.h \
e-html-editor-actions-dom-functions.h \
e-html-editor-cell-dialog-dom-functions.h \
+ e-html-editor-history-event.h \
e-html-editor-hrule-dialog-dom-functions.h \
e-html-editor-image-dialog-dom-functions.h \
e-html-editor-link-dialog-dom-functions.h \
+ e-html-editor-page-dialog-dom-functions.h \
e-html-editor-selection-dom-functions.h \
e-html-editor-spell-check-dialog-dom-functions.h\
e-html-editor-table-dialog-dom-functions.h \
+ e-html-editor-undo-redo-manager.h \
e-html-editor-view-dom-functions.h \
e-msg-composer-dom-functions.h \
e-composer-private-dom-functions.c \
@@ -64,9 +67,11 @@ libehtmleditorwebextension_la_SOURCES = \
e-html-editor-hrule-dialog-dom-functions.c \
e-html-editor-image-dialog-dom-functions.c \
e-html-editor-link-dialog-dom-functions.c \
+ e-html-editor-page-dialog-dom-functions.c \
e-html-editor-selection-dom-functions.c \
e-html-editor-spell-check-dialog-dom-functions.c\
e-html-editor-table-dialog-dom-functions.c \
+ e-html-editor-undo-redo-manager.c \
e-html-editor-view-dom-functions.c \
e-msg-composer-dom-functions.c \
e-html-editor-web-extension.c \
diff --git a/web-extensions/e-html-editor-actions-dom-functions.c
b/web-extensions/e-html-editor-actions-dom-functions.c
index e2980fd..fa64aec 100644
--- a/web-extensions/e-html-editor-actions-dom-functions.c
+++ b/web-extensions/e-html-editor-actions-dom-functions.c
@@ -19,6 +19,8 @@
#include "e-html-editor-actions-dom-functions.h"
#include "e-dom-utils.h"
+#include "e-html-editor-history-event.h"
+#include "e-html-editor-selection-dom-functions.h"
static WebKitDOMElement *
get_table_cell_element (WebKitDOMDocument *document)
@@ -26,11 +28,49 @@ get_table_cell_element (WebKitDOMDocument *document)
return webkit_dom_document_get_element_by_id (document, "-x-evo-table-cell");
}
+static void
+prepare_history_for_table (WebKitDOMDocument *document,
+ WebKitDOMElement *table,
+ EHTMLEditorHistoryEvent *ev)
+{
+ ev->type = HISTORY_TABLE_DIALOG;
+
+ 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 (table), TRUE);
+}
+
+
+static void
+save_history_for_table (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMElement *table,
+ EHTMLEditorHistoryEvent *ev)
+{
+ EHTMLEditorUndoRedoManager *manager;
+
+ if (table)
+ ev->data.dom.to = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (table), TRUE);
+ else
+ ev->data.dom.to = NULL;
+
+ 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);
+}
+
void
-e_html_editor_dialog_delete_cell_contents (WebKitDOMDocument *document)
+e_html_editor_dialog_delete_cell_contents (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
WebKitDOMNode *node;
- WebKitDOMElement *cell, *table_cell;
+ WebKitDOMElement *cell, *table_cell, *table;
table_cell = get_table_cell_element (document);
g_return_if_fail (table_cell != NULL);
@@ -40,13 +80,23 @@ e_html_editor_dialog_delete_cell_contents (WebKitDOMDocument *document)
cell = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TH");
g_return_if_fail (cell != NULL);
+ table = dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TABLE");
+ g_return_if_fail (table != NULL);
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
while ((node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (cell))))
remove_node (node);
+
+ save_history_for_table (document, extension, table, ev);
}
void
-e_html_editor_dialog_delete_column (WebKitDOMDocument *document)
+e_html_editor_dialog_delete_column (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
WebKitDOMElement *cell, *table, *table_cell;
WebKitDOMHTMLCollection *rows;
gulong index, length, ii;
@@ -63,6 +113,9 @@ e_html_editor_dialog_delete_column (WebKitDOMDocument *document)
table = dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TABLE");
g_return_if_fail (table != NULL);
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
rows = webkit_dom_html_table_element_get_rows (
WEBKIT_DOM_HTML_TABLE_ELEMENT (table));
length = webkit_dom_html_collection_get_length (rows);
@@ -81,12 +134,16 @@ e_html_editor_dialog_delete_column (WebKitDOMDocument *document)
}
g_object_unref (rows);
+
+ save_history_for_table (document, extension, table, ev);
}
void
-e_html_editor_dialog_delete_row (WebKitDOMDocument *document)
+e_html_editor_dialog_delete_row (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
- WebKitDOMElement *row, *table_cell;
+ EHTMLEditorHistoryEvent *ev = NULL;
+ WebKitDOMElement *row, *table, *table_cell;
table_cell = get_table_cell_element (document);
g_return_if_fail (table_cell != NULL);
@@ -94,14 +151,22 @@ e_html_editor_dialog_delete_row (WebKitDOMDocument *document)
row = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TR");
g_return_if_fail (row != NULL);
- webkit_dom_node_remove_child (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row)),
- WEBKIT_DOM_NODE (row), NULL);
+ table = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TABLE");
+ g_return_if_fail (table != NULL);
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
+ remove_node (WEBKIT_DOM_NODE (row));
+
+ save_history_for_table (document, extension, table, ev);
}
void
-e_html_editor_dialog_delete_table (WebKitDOMDocument *document)
+e_html_editor_dialog_delete_table (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
WebKitDOMElement *table, *table_cell;
table_cell = get_table_cell_element (document);
@@ -110,16 +175,21 @@ e_html_editor_dialog_delete_table (WebKitDOMDocument *document)
table = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TABLE");
g_return_if_fail (table != NULL);
- webkit_dom_node_remove_child (
- webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (table)),
- WEBKIT_DOM_NODE (table), NULL);
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
+ remove_node (WEBKIT_DOM_NODE (table));
+
+ save_history_for_table (document, extension, NULL, ev);
}
void
-e_html_editor_dialog_insert_column_after (WebKitDOMDocument *document)
+e_html_editor_dialog_insert_column_after (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
- WebKitDOMElement *cell, *row, *table_cell;
+ EHTMLEditorHistoryEvent *ev = NULL;
gulong index;
+ WebKitDOMElement *cell, *row, *table_cell, *table;
table_cell = get_table_cell_element (document);
g_return_if_fail (table_cell != NULL);
@@ -132,6 +202,12 @@ e_html_editor_dialog_insert_column_after (WebKitDOMDocument *document)
row = dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TR");
g_return_if_fail (row != NULL);
+ table = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TABLE");
+ g_return_if_fail (table != NULL);
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
/* Get the first row in the table */
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_first_child (
@@ -147,13 +223,17 @@ e_html_editor_dialog_insert_column_after (WebKitDOMDocument *document)
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (row)));
}
+
+ save_history_for_table (document, extension, table, ev);
}
void
-e_html_editor_dialog_insert_column_before (WebKitDOMDocument *document)
+e_html_editor_dialog_insert_column_before (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
- WebKitDOMElement *cell, *row, *table_cell;
+ EHTMLEditorHistoryEvent *ev = NULL;
gulong index;
+ WebKitDOMElement *cell, *row, *table_cell, *table;
table_cell = get_table_cell_element (document);
g_return_if_fail (table_cell != NULL);
@@ -167,6 +247,12 @@ e_html_editor_dialog_insert_column_before (WebKitDOMDocument *document)
row = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TR");
g_return_if_fail (row != NULL);
+ table = dom_node_find_parent_element (WEBKIT_DOM_NODE (table_cell), "TABLE");
+ g_return_if_fail (table != NULL);
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
/* Get the first row in the table */
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_first_child (
@@ -182,15 +268,19 @@ e_html_editor_dialog_insert_column_before (WebKitDOMDocument *document)
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (row)));
}
+
+ save_history_for_table (document, extension, table, ev);
}
void
-e_html_editor_dialog_insert_row_above (WebKitDOMDocument *document)
+e_html_editor_dialog_insert_row_above (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ gulong index, cell_count, ii;
WebKitDOMElement *row, *table, *table_cell;
WebKitDOMHTMLCollection *cells;
WebKitDOMHTMLElement *new_row;
- gulong index, cell_count, ii;
table_cell = get_table_cell_element (document);
g_return_if_fail (table_cell != NULL);
@@ -201,6 +291,9 @@ e_html_editor_dialog_insert_row_above (WebKitDOMDocument *document)
table = dom_node_find_parent_element (WEBKIT_DOM_NODE (row), "TABLE");
g_return_if_fail (table != NULL);
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
index = webkit_dom_html_table_row_element_get_row_index (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
@@ -216,15 +309,19 @@ e_html_editor_dialog_insert_row_above (WebKitDOMDocument *document)
}
g_object_unref (cells);
+
+ save_history_for_table (document, extension, table, ev);
}
void
-e_html_editor_dialog_insert_row_below (WebKitDOMDocument *document)
+e_html_editor_dialog_insert_row_below (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ gulong index, cell_count, ii;
WebKitDOMElement *row, *table, *table_cell;
WebKitDOMHTMLCollection *cells;
WebKitDOMHTMLElement *new_row;
- gulong index, cell_count, ii;
table_cell = get_table_cell_element (document);
g_return_if_fail (table_cell != NULL);
@@ -235,6 +332,9 @@ e_html_editor_dialog_insert_row_below (WebKitDOMDocument *document)
table = dom_node_find_parent_element (WEBKIT_DOM_NODE (row), "TABLE");
g_return_if_fail (table != NULL);
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ prepare_history_for_table (document, table, ev);
+
index = webkit_dom_html_table_row_element_get_row_index (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
@@ -250,4 +350,6 @@ e_html_editor_dialog_insert_row_below (WebKitDOMDocument *document)
}
g_object_unref (cells);
+
+ save_history_for_table (document, extension, table, ev);
}
diff --git a/web-extensions/e-html-editor-actions-dom-functions.h
b/web-extensions/e-html-editor-actions-dom-functions.h
index ce7632a..1a78099 100644
--- a/web-extensions/e-html-editor-actions-dom-functions.h
+++ b/web-extensions/e-html-editor-actions-dom-functions.h
@@ -21,31 +21,41 @@
#include <webkitdom/webkitdom.h>
+#include "e-html-editor-web-extension.h"
+
G_BEGIN_DECLS
void e_html_editor_dialog_delete_cell_contents
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_delete_column
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_delete_row
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_delete_table
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_insert_column_after
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_insert_column_before
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_insert_row_above
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void e_html_editor_dialog_insert_row_below
- (WebKitDOMDocument *document);
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
G_END_DECLS
diff --git a/web-extensions/e-html-editor-cell-dialog-dom-functions.c
b/web-extensions/e-html-editor-cell-dialog-dom-functions.c
index 91aa50b..1fe2f2c 100644
--- a/web-extensions/e-html-editor-cell-dialog-dom-functions.c
+++ b/web-extensions/e-html-editor-cell-dialog-dom-functions.c
@@ -19,6 +19,8 @@
#include "e-html-editor-cell-dialog-dom-functions.h"
#include "e-dom-utils.h"
+#include "e-html-editor-undo-redo-manager.h"
+#include "e-html-editor-selection-dom-functions.h"
enum {
SCOPE_CELL,
@@ -231,8 +233,10 @@ cell_set_header_style (WebKitDOMHTMLTableCellElement *cell,
void
e_html_editor_cell_dialog_mark_current_cell_element (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
const gchar *id)
{
+ EHTMLEditorUndoRedoManager *manager;
WebKitDOMElement *element, *parent = NULL;
element = webkit_dom_document_get_element_by_id (document, id);
@@ -245,7 +249,55 @@ e_html_editor_cell_dialog_mark_current_cell_element (WebKitDOMDocument *document
if (element)
webkit_dom_element_remove_attribute (element, "id");
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EHTMLEditorHistoryEvent *ev;
+ WebKitDOMElement *table;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_TABLE_DIALOG;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ table = dom_node_find_parent_element (
+ WEBKIT_DOM_NODE (parent), "TABLE");
+ ev->data.dom.from = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (table), TRUE);
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+
webkit_dom_element_set_id (parent, "-x-evo-current-cell");
+
+}
+
+void
+e_html_editor_cell_dialog_save_history_on_exit (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
+ WebKitDOMElement *cell, *table;
+
+ cell = get_current_cell_element (document);
+
+ table = dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TABLE");
+ g_return_if_fail (table != NULL);
+
+ webkit_dom_element_remove_attribute (cell, "id");
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ ev->data.dom.to = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (table), TRUE);
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
}
void
diff --git a/web-extensions/e-html-editor-cell-dialog-dom-functions.h
b/web-extensions/e-html-editor-cell-dialog-dom-functions.h
index 83959b2..75ec4a2 100644
--- a/web-extensions/e-html-editor-cell-dialog-dom-functions.h
+++ b/web-extensions/e-html-editor-cell-dialog-dom-functions.h
@@ -21,12 +21,19 @@
#include <webkitdom/webkitdom.h>
+#include "e-html-editor-web-extension.h"
+
G_BEGIN_DECLS
void e_html_editor_cell_dialog_mark_current_cell_element
(WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
const gchar *id);
+void e_html_editor_cell_dialog_save_history_on_exit
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
void e_html_editor_cell_dialog_set_element_v_align
(WebKitDOMDocument *document,
const gchar *v_align,
diff --git a/web-extensions/e-html-editor-history-event.h b/web-extensions/e-html-editor-history-event.h
new file mode 100644
index 0000000..62e65d2
--- /dev/null
+++ b/web-extensions/e-html-editor-history-event.h
@@ -0,0 +1,98 @@
+/*
+ * e-html-editor-history-event.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_HTML_EDITOR_HISTORY_EVENT_H
+#define E_HTML_EDITOR_HISTORY_EVENT_H
+
+#include "config.h"
+
+G_BEGIN_DECLS
+
+enum EHTMLEditorHistoryEventType {
+ HISTORY_ALIGNMENT,
+ HISTORY_BLOCK_FORMAT,
+ HISTORY_BOLD,
+ HISTORY_CELL_DIALOG,
+ HISTORY_DELETE, /* BackSpace, Delete, with and without selection */
+ HISTORY_FONT_COLOR,
+ HISTORY_FONT_SIZE,
+ HISTORY_HRULE_DIALOG,
+ HISTORY_INDENT,
+ HISTORY_INPUT,
+ HISTORY_IMAGE,
+ HISTORY_IMAGE_DIALOG,
+ HISTORY_INSERT_HTML,
+ HISTORY_ITALIC,
+ HISTORY_MONOSPACE,
+ HISTORY_PAGE_DIALOG,
+ HISTORY_PASTE,
+ HISTORY_PASTE_AS_TEXT,
+ HISTORY_PASTE_QUOTED,
+ HISTORY_REMOVE_LINK,
+ HISTORY_REPLACE,
+ HISTORY_REPLACE_ALL,
+ HISTORY_CITATION_SPLIT,
+ HISTORY_SMILEY,
+ HISTORY_START, /* Start of history */
+ HISTORY_STRIKETHROUGH,
+ HISTORY_TABLE_DIALOG,
+ HISTORY_UNDERLINE,
+ HISTORY_WRAP
+};
+
+typedef struct {
+ gint from; /* From what format we are changing. */
+ gint to; /* To what format we are changing. */
+} EHTMLEditorStyleChange;
+
+/* This is used for e-html-editor-*-dialogs */
+typedef struct {
+ WebKitDOMNode *from; /* From what node we are changing. */
+ WebKitDOMNode *to; /* To what node we are changing. */
+} EHTMLEditorDOMChange;
+
+typedef struct {
+ gchar *from; /* From what format we are changing. */
+ gchar *to; /* To what format we are changing. */
+} EHTMLEditorStringChange;
+
+typedef struct {
+ guint x;
+ guint y;
+} EHTMLEditorSelectionPoint;
+
+typedef struct {
+ EHTMLEditorSelectionPoint start;
+ EHTMLEditorSelectionPoint end;
+} EHTMLEditorSelection;
+
+typedef struct {
+ enum EHTMLEditorHistoryEventType type;
+ EHTMLEditorSelection before;
+ EHTMLEditorSelection after;
+ union {
+ WebKitDOMDocumentFragment *fragment;
+ EHTMLEditorStyleChange style;
+ EHTMLEditorStringChange string;
+ EHTMLEditorDOMChange dom;
+ } data;
+} EHTMLEditorHistoryEvent;
+
+G_END_DECLS
+
+#endif /* E_HTML_EDITOR_HISTORY_EVENT_H */
diff --git a/web-extensions/e-html-editor-hrule-dialog-dom-functions.c
b/web-extensions/e-html-editor-hrule-dialog-dom-functions.c
index ef158b2..66f269c 100644
--- a/web-extensions/e-html-editor-hrule-dialog-dom-functions.c
+++ b/web-extensions/e-html-editor-hrule-dialog-dom-functions.c
@@ -20,22 +20,33 @@
#include "e-dom-utils.h"
#include "e-html-editor-selection-dom-functions.h"
+#include "e-html-editor-web-extension.h"
+#include "e-html-editor-undo-redo-manager.h"
#define WEBKIT_DOM_USE_UNSTABLE_API
#include <webkitdom/WebKitDOMDOMSelection.h>
#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
+static WebKitDOMElement *
+get_current_hrule_element (WebKitDOMDocument *document)
+{
+ return webkit_dom_document_get_element_by_id (document, "-x-evo-current-hr");
+}
+
gboolean
e_html_editor_hrule_dialog_find_hrule (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
WebKitDOMNode *node_under_mouse_click)
{
- if (node_under_mouse_click && WEBKIT_DOM_IS_HTML_HR_ELEMENT (node_under_mouse_click)) {
- webkit_dom_element_set_id (WEBKIT_DOM_ELEMENT (node_under_mouse_click), "-x-evo-current-hr");
+ EHTMLEditorUndoRedoManager *manager;
+ gboolean created = FALSE;
+ WebKitDOMElement *rule;
- return FALSE;
+ if (node_under_mouse_click && WEBKIT_DOM_IS_HTML_HR_ELEMENT (node_under_mouse_click)) {
+ rule = WEBKIT_DOM_ELEMENT (node_under_mouse_click);
+ webkit_dom_element_set_id (rule, "-x-evo-current-hr");
} else {
- WebKitDOMElement *selection_start, *parent, *rule;
+ WebKitDOMElement *selection_start, *parent;
dom_selection_save (document);
@@ -56,6 +67,49 @@ e_html_editor_hrule_dialog_find_hrule (WebKitDOMDocument *document,
dom_selection_restore (document);
e_html_editor_web_extension_set_content_changed (extension);
+
+ created = TRUE;
+ }
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EHTMLEditorHistoryEvent *ev;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_HRULE_DIALOG;
+
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x,
&ev->before.end.y);
+ if (!created)
+ ev->data.dom.from = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (rule), FALSE);
+ else
+ ev->data.dom.from = NULL;
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
}
- return TRUE;
+
+ return created;
+}
+
+void
+e_html_editor_hrule_dialog_save_history_on_exit (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
+ WebKitDOMElement *element;
+
+ element = get_current_hrule_element (document);
+ g_return_if_fail (element != NULL);
+
+ webkit_dom_element_remove_attribute (element, "id");
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ ev->data.dom.to = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (element), TRUE);
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
}
diff --git a/web-extensions/e-html-editor-hrule-dialog-dom-functions.h
b/web-extensions/e-html-editor-hrule-dialog-dom-functions.h
index 1d7c55a..de9eb93 100644
--- a/web-extensions/e-html-editor-hrule-dialog-dom-functions.h
+++ b/web-extensions/e-html-editor-hrule-dialog-dom-functions.h
@@ -30,6 +30,10 @@ gboolean e_html_editor_hrule_dialog_find_hrule
EHTMLEditorWebExtension *extension,
WebKitDOMNode *node_under_mouse_click);
+void e_html_editor_hrule_dialog_save_history_on_exit
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
G_END_DECLS
#endif /* E_HTML_EDITOR_HRULE_DIALOG_DOM_FUNCTIONS_H */
diff --git a/web-extensions/e-html-editor-image-dialog-dom-functions.c
b/web-extensions/e-html-editor-image-dialog-dom-functions.c
index 4d9fb32..a892476 100644
--- a/web-extensions/e-html-editor-image-dialog-dom-functions.c
+++ b/web-extensions/e-html-editor-image-dialog-dom-functions.c
@@ -19,6 +19,9 @@
#include "e-html-editor-image-dialog-dom-functions.h"
#include "e-dom-utils.h"
+#include "e-html-editor-selection-dom-functions.h"
+#include "e-html-editor-web-extension.h"
+#include "e-html-editor-undo-redo-manager.h"
static WebKitDOMElement *
get_current_image_element (WebKitDOMDocument *document)
@@ -27,6 +30,54 @@ get_current_image_element (WebKitDOMDocument *document)
}
void
+e_html_editor_image_dialog_mark_image (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMNode *node_under_mouse_click)
+{
+ EHTMLEditorUndoRedoManager *manager;
+
+ g_return_if_fail (node_under_mouse_click && WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT
(node_under_mouse_click));
+
+ webkit_dom_element_set_id (WEBKIT_DOM_ELEMENT (node_under_mouse_click), "-x-evo-current-img");
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EHTMLEditorHistoryEvent *ev;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_IMAGE_DIALOG;
+
+ 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 (node_under_mouse_click, FALSE);
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+}
+
+void
+e_html_editor_image_dialog_save_history_on_exit (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
+ WebKitDOMElement *element;
+
+ element = get_current_image_element (document);
+ g_return_if_fail (element != NULL);
+
+ webkit_dom_element_remove_attribute (element, "id");
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ ev->data.dom.to = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (element), TRUE);
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
+}
+
+void
e_html_editor_image_dialog_set_element_url (WebKitDOMDocument *document,
const gchar *url)
{
diff --git a/web-extensions/e-html-editor-image-dialog-dom-functions.h
b/web-extensions/e-html-editor-image-dialog-dom-functions.h
index 63d4b31..46dd716 100644
--- a/web-extensions/e-html-editor-image-dialog-dom-functions.h
+++ b/web-extensions/e-html-editor-image-dialog-dom-functions.h
@@ -21,8 +21,19 @@
#include <webkitdom/webkitdom.h>
+#include "e-html-editor-web-extension.h"
+
G_BEGIN_DECLS
+void e_html_editor_image_dialog_mark_image
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMNode *node_under_mouse_click);
+
+void e_html_editor_image_dialog_save_history_on_exit
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
void e_html_editor_image_dialog_set_element_url
(WebKitDOMDocument *document,
const gchar *url);
diff --git a/web-extensions/e-html-editor-link-dialog-dom-functions.c
b/web-extensions/e-html-editor-link-dialog-dom-functions.c
index 7e392ea..1e18c92 100644
--- a/web-extensions/e-html-editor-link-dialog-dom-functions.c
+++ b/web-extensions/e-html-editor-link-dialog-dom-functions.c
@@ -30,6 +30,7 @@
void
e_html_editor_link_dialog_ok (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
const gchar *url,
const gchar *inner_text)
{
@@ -92,13 +93,13 @@ e_html_editor_link_dialog_ok (WebKitDOMDocument *document,
/* Check whether a text is selected or not */
text = webkit_dom_range_get_text (range);
if (text && *text) {
- dom_create_link (document, url);
+ dom_create_link (document, extension, url);
} else {
gchar *html = g_strdup_printf (
"<a href=\"%s\">%s</a>", url, inner_text);
dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html);
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html);
g_free (html);
}
diff --git a/web-extensions/e-html-editor-link-dialog-dom-functions.h
b/web-extensions/e-html-editor-link-dialog-dom-functions.h
index 89cbd6e..d47a732 100644
--- a/web-extensions/e-html-editor-link-dialog-dom-functions.h
+++ b/web-extensions/e-html-editor-link-dialog-dom-functions.h
@@ -21,9 +21,12 @@
#include <webkitdom/webkitdom.h>
+#include "e-html-editor-web-extension.h"
+
G_BEGIN_DECLS
void e_html_editor_link_dialog_ok (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
const gchar *url,
const gchar *inner_text);
diff --git a/web-extensions/e-html-editor-page-dialog-dom-functions.c
b/web-extensions/e-html-editor-page-dialog-dom-functions.c
new file mode 100644
index 0000000..b34e85a
--- /dev/null
+++ b/web-extensions/e-html-editor-page-dialog-dom-functions.c
@@ -0,0 +1,63 @@
+/*
+ * e-html-editor-page-dialog-dom-functions.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-html-editor-page-dialog-dom-functions.h"
+
+#include "e-dom-utils.h"
+#include "e-html-editor-selection-dom-functions.h"
+#include "e-html-editor-web-extension.h"
+
+void
+e_html_editor_page_dialog_save_history (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorUndoRedoManager *manager;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EHTMLEditorHistoryEvent *ev;
+ WebKitDOMHTMLElement *body;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_PAGE_DIALOG;
+
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x,
&ev->before.end.y);
+ body = webkit_dom_document_get_body (document);
+ ev->data.dom.from = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (body), FALSE);
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+}
+
+void
+e_html_editor_page_dialog_save_history_on_exit (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMHTMLElement *body;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ body = webkit_dom_document_get_body (document);
+ ev->data.dom.to = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (body), FALSE);
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
+}
diff --git a/web-extensions/e-html-editor-page-dialog-dom-functions.h
b/web-extensions/e-html-editor-page-dialog-dom-functions.h
new file mode 100644
index 0000000..6dc10b4
--- /dev/null
+++ b/web-extensions/e-html-editor-page-dialog-dom-functions.h
@@ -0,0 +1,38 @@
+/*
+ * e-html-editor-page-dialog-dom-functions.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_HTML_EDITOR_PAGE_DIALOG_DOM_FUNCTIONS_H
+#define E_HTML_EDITOR_PAGE_DIALOG_DOM_FUNCTIONS_H
+
+#include <webkitdom/webkitdom.h>
+
+#include "e-html-editor-web-extension.h"
+
+G_BEGIN_DECLS
+
+void e_html_editor_page_dialog_save_history
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
+void e_html_editor_page_dialog_save_history_on_exit
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
+G_END_DECLS
+
+#endif /* E_HTML_EDITOR_PAGE_DIALOG_DOM_FUNCTIONS_H */
diff --git a/web-extensions/e-html-editor-selection-dom-functions.c
b/web-extensions/e-html-editor-selection-dom-functions.c
index a170e8b..8ae732e 100644
--- a/web-extensions/e-html-editor-selection-dom-functions.c
+++ b/web-extensions/e-html-editor-selection-dom-functions.c
@@ -344,16 +344,31 @@ dom_insert_base64_image (WebKitDOMDocument *document,
const gchar *uri,
const gchar *base64_content)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
WebKitDOMElement *element, *selection_start_marker, *resizable_wrapper;
WebKitDOMText *text;
if (!dom_selection_is_collapsed (document))
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
dom_selection_save (document);
selection_start_marker = webkit_dom_document_query_selector (
document, "span#-x-evo-selection-start-marker", NULL);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_IMAGE;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+ }
+
resizable_wrapper =
webkit_dom_document_create_element (document, "span", NULL);
webkit_dom_element_set_attribute (
@@ -394,6 +409,30 @@ dom_insert_base64_image (WebKitDOMDocument *document,
WEBKIT_DOM_NODE (selection_start_marker),
NULL);
+ if (ev) {
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMNode *node;
+
+ fragment = webkit_dom_document_create_document_fragment (document);
+ node = webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (resizable_wrapper), TRUE),
+ NULL);
+
+ webkit_dom_html_element_insert_adjacent_html (
+ WEBKIT_DOM_HTML_ELEMENT (node), "afterend", "​", 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);
+ }
+
dom_selection_restore (document);
dom_force_spell_check_for_current_paragraph (document, extension);
}
@@ -406,8 +445,10 @@ dom_insert_base64_image (WebKitDOMDocument *document,
* cursor position.
*/
void
-dom_unlink (WebKitDOMDocument *document)
+dom_selection_unlink (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorUndoRedoManager *manager;
gchar *text;
WebKitDOMDOMWindow *window;
WebKitDOMDOMSelection *selection_dom;
@@ -433,12 +474,37 @@ dom_unlink (WebKitDOMDocument *document)
} else
link = WEBKIT_DOM_ELEMENT (node);
} else {
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_UNLINK, NULL);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_UNLINK, NULL);
}
if (!link)
return;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EHTMLEditorHistoryEvent *ev;
+ WebKitDOMDocumentFragment *fragment;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_REMOVE_LINK;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ fragment = webkit_dom_document_create_document_fragment (document);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (link), TRUE),
+ NULL);
+ ev->data.fragment = fragment;
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+
text = webkit_dom_html_element_get_inner_text (
WEBKIT_DOM_HTML_ELEMENT (link));
webkit_dom_html_element_set_outer_html (
@@ -455,11 +521,12 @@ dom_unlink (WebKitDOMDocument *document)
*/
void
dom_create_link (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
const gchar *uri)
{
g_return_if_fail (uri != NULL && *uri != '\0');
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_CREATE_LINK, uri);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_CREATE_LINK, uri);
}
/**
@@ -677,27 +744,6 @@ create_list_element (WebKitDOMDocument *document,
return list;
}
-static WebKitDOMNode *
-get_parent_block_node_from_child (WebKitDOMNode *node)
-{
- WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
-
- if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-temp-text-wrapper") ||
- element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quoted") ||
- element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quote-character") ||
- element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-signature") ||
- WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent) ||
- element_has_tag (WEBKIT_DOM_ELEMENT (parent), "b") ||
- element_has_tag (WEBKIT_DOM_ELEMENT (parent), "i") ||
- element_has_tag (WEBKIT_DOM_ELEMENT (parent), "u"))
- parent = webkit_dom_node_get_parent_node (parent);
-
- if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quoted"))
- parent = webkit_dom_node_get_parent_node (parent);
-
- return parent;
-}
-
static void
merge_list_into_list (WebKitDOMNode *from,
WebKitDOMNode *to,
@@ -936,9 +982,9 @@ dom_get_alignment_from_node (WebKitDOMNode *node)
return alignment;
}
-static WebKitDOMElement *
-create_selection_marker (WebKitDOMDocument *document,
- gboolean start)
+WebKitDOMElement *
+dom_create_selection_marker (WebKitDOMDocument *document,
+ gboolean selection_start_marker)
{
WebKitDOMElement *element;
@@ -946,7 +992,8 @@ create_selection_marker (WebKitDOMDocument *document,
document, "SPAN", NULL);
webkit_dom_element_set_id (
element,
- start ? "-x-evo-selection-start-marker" :
+ selection_start_marker ?
+ "-x-evo-selection-start-marker" :
"-x-evo-selection-end-marker");
return element;
@@ -967,16 +1014,16 @@ remove_selection_markers (WebKitDOMDocument *document)
remove_node (WEBKIT_DOM_NODE (marker));
}
-static void
-add_selection_markers_into_element_start (WebKitDOMDocument *document,
- WebKitDOMElement *element,
- WebKitDOMElement **selection_start_marker,
- WebKitDOMElement **selection_end_marker)
+void
+dom_add_selection_markers_into_element_start (WebKitDOMDocument *document,
+ WebKitDOMElement *element,
+ WebKitDOMElement **selection_start_marker,
+ WebKitDOMElement **selection_end_marker)
{
WebKitDOMElement *marker;
remove_selection_markers (document);
- marker = create_selection_marker (document, FALSE);
+ marker = dom_create_selection_marker (document, FALSE);
webkit_dom_node_insert_before (
WEBKIT_DOM_NODE (element),
WEBKIT_DOM_NODE (marker),
@@ -985,7 +1032,7 @@ add_selection_markers_into_element_start (WebKitDOMDocument *document,
if (selection_end_marker)
*selection_end_marker = marker;
- marker = create_selection_marker (document, TRUE);
+ marker = dom_create_selection_marker (document, TRUE);
webkit_dom_node_insert_before (
WEBKIT_DOM_NODE (element),
WEBKIT_DOM_NODE (marker),
@@ -995,6 +1042,28 @@ add_selection_markers_into_element_start (WebKitDOMDocument *document,
*selection_start_marker = marker;
}
+void
+dom_add_selection_markers_into_element_end (WebKitDOMDocument *document,
+ WebKitDOMElement *element,
+ WebKitDOMElement **selection_start_marker,
+ WebKitDOMElement **selection_end_marker)
+{
+ WebKitDOMElement *marker;
+
+ remove_selection_markers (document);
+ marker = dom_create_selection_marker (document, TRUE);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (marker), NULL);
+ if (selection_start_marker)
+ *selection_start_marker = marker;
+
+ marker = dom_create_selection_marker (document, FALSE);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (marker), NULL);
+ if (selection_end_marker)
+ *selection_end_marker = marker;
+}
+
/**
* e_html_editor_selection_indent:
* @selection: an #EHTMLEditorSelection
@@ -1005,12 +1074,30 @@ void
dom_selection_indent (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
gboolean after_selection_start = FALSE, after_selection_end = FALSE;
WebKitDOMElement *selection_start_marker, *selection_end_marker;
WebKitDOMNode *block;
dom_selection_save (document);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_INDENT;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.style.from = 1;
+ ev->data.style.to = 1;
+ }
+
selection_start_marker = webkit_dom_document_query_selector (
document, "span#-x-evo-selection-start-marker", NULL);
@@ -1025,7 +1112,7 @@ dom_selection_indent (WebKitDOMDocument *document,
body = webkit_dom_document_get_body (document);
child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document,
WEBKIT_DOM_ELEMENT (child),
&selection_start_marker,
@@ -1124,6 +1211,16 @@ dom_selection_indent (WebKitDOMDocument *document,
block = next_block;
}
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
dom_force_spell_check_for_current_paragraph (document, extension);
@@ -1308,6 +1405,8 @@ void
dom_selection_unindent (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
gboolean after_selection_start = FALSE, after_selection_end = FALSE;
WebKitDOMElement *selection_start_marker, *selection_end_marker;
WebKitDOMNode *block;
@@ -1322,30 +1421,29 @@ dom_selection_unindent (WebKitDOMDocument *document,
/* If the selection was not saved, move it into the first child of body */
if (!selection_start_marker || !selection_end_marker) {
WebKitDOMHTMLElement *body;
+ WebKitDOMNode *child;
body = webkit_dom_document_get_body (document);
- selection_start_marker = webkit_dom_document_create_element (
- document, "SPAN", NULL);
- webkit_dom_element_set_id (
- selection_start_marker, "-x-evo-selection-start-marker");
- webkit_dom_node_insert_before (
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
- WEBKIT_DOM_NODE (selection_start_marker),
- webkit_dom_node_get_first_child (
- webkit_dom_node_get_first_child (
- WEBKIT_DOM_NODE (body))),
- NULL);
- selection_end_marker = webkit_dom_document_create_element (
- document, "SPAN", NULL);
- webkit_dom_element_set_id (
- selection_end_marker, "-x-evo-selection-end-marker");
- webkit_dom_node_insert_before (
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
- WEBKIT_DOM_NODE (selection_end_marker),
- webkit_dom_node_get_first_child (
- webkit_dom_node_get_first_child (
- WEBKIT_DOM_NODE (body))),
- NULL);
+ child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
+
+ dom_add_selection_markers_into_element_start (
+ document,
+ WEBKIT_DOM_ELEMENT (child),
+ &selection_start_marker,
+ &selection_end_marker);
+ }
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_INDENT;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
}
block = get_parent_indented_block (
@@ -1419,6 +1517,16 @@ dom_selection_unindent (WebKitDOMDocument *document,
block = next_block;
}
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
dom_force_spell_check_for_current_paragraph (document, extension);
@@ -1497,7 +1605,7 @@ dom_selection_save (WebKitDOMDocument *document)
return;
collapsed = webkit_dom_range_get_collapsed (range, NULL);
- start_marker = create_selection_marker (document, TRUE);
+ start_marker = dom_create_selection_marker (document, TRUE);
container = webkit_dom_range_get_start_container (range, NULL);
offset = webkit_dom_range_get_start_offset (range, NULL);
@@ -1517,6 +1625,16 @@ dom_selection_save (WebKitDOMDocument *document)
NULL);
goto insert_end_marker;
}
+ } else if (element_has_class (WEBKIT_DOM_ELEMENT (parent_node), "-x-evo-smiley-text")) {
+ WebKitDOMNode *node;
+
+ node = webkit_dom_node_get_parent_node (parent_node);
+ marker_node = webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (start_marker),
+ webkit_dom_node_get_next_sibling (node),
+ NULL);
+ goto insert_end_marker;
}
if (WEBKIT_DOM_IS_TEXT (container)) {
@@ -1617,7 +1735,7 @@ dom_selection_save (WebKitDOMDocument *document)
webkit_dom_node_normalize (parent_node);
insert_end_marker:
- end_marker = create_selection_marker (document, FALSE);
+ end_marker = dom_create_selection_marker (document, FALSE);
if (collapsed) {
webkit_dom_node_insert_before (
@@ -2406,7 +2524,7 @@ wrap_lines (WebKitDOMDocument *document,
/* Get HTML code of the processed content */
html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT (element));
- /* Overwrite the current selection be the processed content */
+ /* Overwrite the current selection by the processed content */
dom_insert_html (document, extension, html);
g_free (html);
@@ -2527,6 +2645,35 @@ dom_put_node_into_paragraph (WebKitDOMDocument *document,
return container;
}
+static gint
+get_citation_level (WebKitDOMNode *node)
+{
+ WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
+ gint level = 0;
+
+ while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+ if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent) &&
+ webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (parent), "type"))
+ level++;
+
+ parent = webkit_dom_node_get_parent_node (parent);
+ }
+
+ return level;
+}
+
+WebKitDOMElement *
+dom_wrap_paragraph_length (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ WebKitDOMElement *paragraph,
+ gint length)
+{
+ g_return_val_if_fail (WEBKIT_DOM_IS_ELEMENT (paragraph), NULL);
+ g_return_val_if_fail (length >= MINIMAL_PARAGRAPH_WIDTH, NULL);
+
+ return wrap_lines (document, extension, WEBKIT_DOM_NODE (paragraph), FALSE, length);
+}
+
/**
* e_html_editor_selection_wrap_lines:
* @selection: an #EHTMLEditorSelection
@@ -2534,10 +2681,12 @@ dom_put_node_into_paragraph (WebKitDOMDocument *document,
* Wraps all lines in current selection to be 71 characters long.
*/
-static void
-dom_wrap_lines (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension)
+void
+dom_selection_wrap (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
gboolean after_selection_end = FALSE, html_mode;
gint word_wrap_length;
WebKitDOMElement *selection_start_marker, *selection_end_marker;
@@ -2554,30 +2703,32 @@ dom_wrap_lines (WebKitDOMDocument *document,
/* If the selection was not saved, move it into the first child of body */
if (!selection_start_marker || !selection_end_marker) {
WebKitDOMHTMLElement *body;
+ WebKitDOMNode *child;
body = webkit_dom_document_get_body (document);
- selection_start_marker = webkit_dom_document_create_element (
- document, "SPAN", NULL);
- webkit_dom_element_set_id (
- selection_start_marker, "-x-evo-selection-start-marker");
- webkit_dom_node_insert_before (
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
- WEBKIT_DOM_NODE (selection_start_marker),
- webkit_dom_node_get_first_child (
- webkit_dom_node_get_first_child (
- WEBKIT_DOM_NODE (body))),
- NULL);
- selection_end_marker = webkit_dom_document_create_element (
- document, "SPAN", NULL);
- webkit_dom_element_set_id (
- selection_end_marker, "-x-evo-selection-end-marker");
- webkit_dom_node_insert_before (
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
- WEBKIT_DOM_NODE (selection_end_marker),
- webkit_dom_node_get_first_child (
- webkit_dom_node_get_first_child (
- WEBKIT_DOM_NODE (body))),
- NULL);
+ child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
+
+ dom_add_selection_markers_into_element_start (
+ document,
+ WEBKIT_DOM_ELEMENT (child),
+ &selection_start_marker,
+ &selection_end_marker);
+ }
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_WRAP;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.style.from = 1;
+ ev->data.style.to = 1;
}
block = get_parent_block_node_from_child (
@@ -2617,6 +2768,16 @@ dom_wrap_lines (WebKitDOMDocument *document,
block = next_block;
}
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
dom_force_spell_check_for_current_paragraph (document, extension);
@@ -2845,6 +3006,140 @@ dom_selection_is_underline (WebKitDOMDocument *document,
return ret_val;
}
+static WebKitDOMElement *
+set_font_style (WebKitDOMDocument *document,
+ const gchar *element_name,
+ gboolean value)
+{
+ WebKitDOMElement *element;
+ WebKitDOMNode *parent;
+
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-selection-end-marker");
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
+ if (value) {
+ WebKitDOMNode *node;
+ WebKitDOMElement *el;
+ gchar *name;
+
+ el = webkit_dom_document_create_element (document, element_name, NULL);
+ webkit_dom_html_element_set_inner_text (
+ WEBKIT_DOM_HTML_ELEMENT (el), UNICODE_ZERO_WIDTH_SPACE, NULL);
+
+ node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (el), node, NULL);
+ name = webkit_dom_node_get_local_name (parent);
+ if (g_strcmp0 (name, element_name) == 0)
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (parent),
+ WEBKIT_DOM_NODE (el),
+ webkit_dom_node_get_next_sibling (parent),
+ NULL);
+ else
+ webkit_dom_node_insert_before (
+ parent,
+ WEBKIT_DOM_NODE (el),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ g_free (name);
+
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (el), WEBKIT_DOM_NODE (element), NULL);
+
+ return el;
+ } else {
+ WebKitDOMNode *node;
+
+ node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (parent),
+ WEBKIT_DOM_NODE (element),
+ webkit_dom_node_get_next_sibling (parent),
+ NULL);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (parent),
+ WEBKIT_DOM_NODE (node),
+ webkit_dom_node_get_next_sibling (parent),
+ NULL);
+
+ webkit_dom_html_element_insert_adjacent_text (
+ WEBKIT_DOM_HTML_ELEMENT (parent),
+ "afterend",
+ UNICODE_ZERO_WIDTH_SPACE,
+ NULL);
+ }
+
+ return NULL;
+}
+
+static void
+selection_set_font_style (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorViewCommand command,
+ gboolean value)
+{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
+
+ dom_selection_save (document);
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ if (command == E_HTML_EDITOR_VIEW_COMMAND_BOLD)
+ ev->type = HISTORY_BOLD;
+ else if (command == E_HTML_EDITOR_VIEW_COMMAND_ITALIC)
+ ev->type = HISTORY_ITALIC;
+ else if (command == E_HTML_EDITOR_VIEW_COMMAND_UNDERLINE)
+ ev->type = HISTORY_UNDERLINE;
+ else if (command == E_HTML_EDITOR_VIEW_COMMAND_STRIKETHROUGH)
+ ev->type = HISTORY_STRIKETHROUGH;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.style.from = !value;
+ ev->data.style.to = value;
+ }
+
+ if (dom_selection_is_collapsed (document)) {
+ const gchar *element_name;
+
+ if (command == E_HTML_EDITOR_VIEW_COMMAND_BOLD)
+ element_name = "b";
+ else if (command == E_HTML_EDITOR_VIEW_COMMAND_ITALIC)
+ element_name = "i";
+ else if (command == E_HTML_EDITOR_VIEW_COMMAND_UNDERLINE)
+ element_name = "u";
+ else if (command == E_HTML_EDITOR_VIEW_COMMAND_STRIKETHROUGH)
+ element_name = "strike";
+
+ set_font_style (document, element_name, value);
+ dom_selection_restore (document);
+
+ goto exit;
+ }
+ dom_selection_restore (document);
+
+ dom_exec_command (document, extension, command, NULL);
+exit:
+ if (ev) {
+ 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);
+ }
+
+ dom_force_spell_check_for_current_paragraph (document, extension);
+}
+
/**
* e_html_editor_selection_set_underline:
* @selection: an #EHTMLEditorSelection
@@ -2861,9 +3156,8 @@ dom_selection_set_underline (WebKitDOMDocument *document,
if (dom_selection_is_underline (document, extension) == underline)
return;
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_UNDERLINE, NULL);
-
- dom_force_spell_check_for_current_paragraph (document, extension);
+ selection_set_font_style (
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_UNDERLINE, underline);
set_dbus_property_boolean (extension, "Underline", underline);
}
@@ -2920,7 +3214,7 @@ dom_selection_set_subscript (WebKitDOMDocument *document,
if (dom_selection_is_subscript (document, extension) == subscript)
return;
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_SUBSCRIPT, NULL);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_SUBSCRIPT, NULL);
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "subscript");
@@ -2979,7 +3273,7 @@ dom_selection_set_superscript (WebKitDOMDocument *document,
if (dom_selection_is_superscript (document, extension) == superscript)
return;
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_SUPERSCRIPT, NULL);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_SUPERSCRIPT, NULL);
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "superscript");
@@ -3057,8 +3351,8 @@ dom_selection_set_strikethrough (WebKitDOMDocument *document,
/* FIXME WK2
selection->priv->is_strikethrough = strikethrough;
*/
-
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_STRIKETHROUGH, NULL);
+ selection_set_font_style (
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_STRIKETHROUGH, strikethrough);
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "strikethrough");
*/
@@ -3154,6 +3448,8 @@ dom_selection_set_monospaced (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
gboolean monospaced)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
guint font_size = 0;
WebKitDOMRange *range;
WebKitDOMDOMWindow *window;
@@ -3168,6 +3464,22 @@ dom_selection_set_monospaced (WebKitDOMDocument *document,
if (!range)
return;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_MONOSPACE;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.style.from = !monospaced;
+ ev->data.style.to = monospaced;
+ }
+
font_size = e_html_editor_web_extension_get_font_size (extension);
if (font_size == 0)
font_size = E_HTML_EDITOR_SELECTION_FONT_SIZE_NORMAL;
@@ -3197,13 +3509,13 @@ dom_selection_set_monospaced (WebKitDOMDocument *document,
webkit_dom_node_insert_before (
WEBKIT_DOM_NODE (monospace),
- WEBKIT_DOM_NODE (create_selection_marker (document, TRUE)),
+ WEBKIT_DOM_NODE (dom_create_selection_marker (document, TRUE)),
webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (monospace)),
NULL);
webkit_dom_node_append_child (
WEBKIT_DOM_NODE (monospace),
- WEBKIT_DOM_NODE (create_selection_marker (document, FALSE)),
+ WEBKIT_DOM_NODE (dom_create_selection_marker (document, FALSE)),
NULL);
dom_selection_restore (document);
@@ -3361,6 +3673,16 @@ dom_selection_set_monospaced (WebKitDOMDocument *document,
dom_selection_set_font_size (document, extension, font_size);
}
+ if (ev) {
+ 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);
+ }
+
dom_force_spell_check_for_current_paragraph (document, extension);
/* FIXME WK2
@@ -3439,7 +3761,8 @@ dom_selection_set_bold (WebKitDOMDocument *document,
/* FIXME WK2
selection->priv->is_bold = bold; */
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_BOLD, NULL);
+ selection_set_font_style (
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_BOLD, bold);
dom_force_spell_check_for_current_paragraph (document, extension);
/* FIXME WK2
@@ -3518,9 +3841,8 @@ dom_selection_set_italic (WebKitDOMDocument *document,
/* FIXME WK2
selection->priv->is_italic = italic;*/
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_ITALIC, NULL);
-
- dom_force_spell_check_for_current_paragraph (document, extension);
+ selection_set_font_style (
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_ITALIC, italic);
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "italic");*/
}
@@ -3682,13 +4004,50 @@ dom_selection_set_font_size (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
guint font_size)
{
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
gchar *size_str;
+ guint current_font_size;
+
+ current_font_size = dom_selection_get_font_size (document, extension);
+ if (current_font_size == font_size)
+ return;
+
+ dom_selection_save (document);
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_FONT_SIZE;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.style.from = current_font_size;
+ ev->data.style.to = font_size;
+ }
+
/* FIXME WK2
selection->priv->font_size = font_size; */
-
size_str = g_strdup_printf ("%d", font_size);
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_FONT_SIZE, size_str);
- g_free (size_str);
+
+ if (dom_selection_is_collapsed (document)) {
+ WebKitDOMElement *font;
+
+ font = set_font_style (document, "font", font_size != 3);
+ if (font)
+ webkit_dom_element_set_attribute (font, "size", size_str, NULL);
+ dom_selection_restore (document);
+ goto exit;
+ }
+
+ dom_selection_restore (document);
+
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_FONT_SIZE, size_str);
/* Text in <font size="3"></font> (size 3 is our default size) is a little
* bit smaller than font outsize it. So move it outside of it. */
@@ -3710,6 +4069,19 @@ dom_selection_set_font_size (WebKitDOMDocument *document,
}
}
+ exit:
+ g_free (size_str);
+
+ if (ev) {
+ 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);
+ }
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "font-size"); */
}
@@ -3727,7 +4099,7 @@ dom_selection_set_font_name (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *font_name)
{
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_FONT_NAME, font_name);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_FONT_NAME, font_name);
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "font-name");*/
}
@@ -3775,10 +4147,39 @@ dom_selection_set_font_color (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *color)
{
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_FONT_COLOR;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+/* FIXME WK2
+ ev->data.string.from = g_strdup (selection->priv->font_color);*/
+ ev->data.string.to = g_strdup (color);
+ }
+
/* FIXME WK2
selection->priv->font_color = g_strdup (color); */
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_FORE_COLOR, color);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_FORE_COLOR, color);
+ if (ev) {
+ 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);
+ }
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "font-color"); */
}
@@ -3893,26 +4294,6 @@ dom_selection_get_block_format (WebKitDOMDocument *document,
}
static gboolean
-is_citation_node (WebKitDOMNode *node)
-{
- char *value;
-
- if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node))
- return FALSE;
-
- value = webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (node), "type");
-
- /* citation == <blockquote type='cite'> */
- if (g_strcmp0 (value, "cite") == 0) {
- g_free (value);
- return TRUE;
- } else {
- g_free (value);
- return FALSE;
- }
-}
-
-static gboolean
process_block_to_block (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
EHTMLEditorSelectionBlockFormat format,
@@ -3931,7 +4312,7 @@ process_block_to_block (WebKitDOMDocument *document,
WebKitDOMNode *child;
WebKitDOMElement *element;
- if (is_citation_node (block)) {
+ if (dom_node_is_citation_node (block)) {
gboolean finished;
next_block = webkit_dom_node_get_next_sibling (block);
@@ -4063,7 +4444,7 @@ format_change_block_to_block (WebKitDOMDocument *document,
body = webkit_dom_document_get_body (document);
child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document,
WEBKIT_DOM_ELEMENT (child),
&selection_start_marker,
@@ -4112,7 +4493,7 @@ format_change_block_to_list (WebKitDOMDocument *document,
body = webkit_dom_document_get_body (document);
child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document,
WEBKIT_DOM_ELEMENT (child),
&selection_start_marker,
@@ -4139,7 +4520,7 @@ format_change_block_to_list (WebKitDOMDocument *document,
dom_restore_caret_position (document);
dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT, NULL);
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT,
NULL);
element = webkit_dom_document_query_selector (
document, "body>br", NULL);
@@ -4490,6 +4871,8 @@ dom_selection_set_block_format (WebKitDOMDocument *document,
EHTMLEditorSelectionBlockFormat format)
{
EHTMLEditorSelectionBlockFormat current_format;
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
const gchar *value;
gboolean from_list = FALSE, to_list = FALSE, html_mode = FALSE;
WebKitDOMRange *range;
@@ -4560,6 +4943,21 @@ dom_selection_set_block_format (WebKitDOMDocument *document,
if (!range)
return;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_BLOCK_FORMAT;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+ ev->data.style.from = current_format;
+ ev->data.style.to = format;
+ }
+
if (from_list && to_list)
format_change_list_to_list (document, extension, format, html_mode);
@@ -4579,6 +4977,16 @@ dom_selection_set_block_format (WebKitDOMDocument *document,
document, extension, e_html_editor_web_extension_get_alignment (extension));
e_html_editor_web_extension_set_content_changed (extension);
+
+ if (ev) {
+ 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);
+ }
/*
g_object_notify (G_OBJECT (selection), "block-format");*/
}
@@ -4627,7 +5035,7 @@ dom_selection_set_background_color (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *color)
{
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_BACKGROUND_COLOR, color);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_BACKGROUND_COLOR, color);
/* FIXME WK2
g_object_notify (G_OBJECT (selection), "background-color");*/
}
@@ -4715,12 +5123,17 @@ dom_selection_set_alignment (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
EHTMLEditorSelectionAlignment alignment)
{
+ EHTMLEditorSelectionAlignment current_alignment;
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev = NULL;
gboolean after_selection_end = FALSE;
const gchar *class = "", *list_class = "";
WebKitDOMElement *selection_start_marker, *selection_end_marker;
WebKitDOMNode *block;
- if (dom_selection_get_alignment (document, extension) == alignment)
+ current_alignment = dom_selection_get_alignment (document, extension);
+
+ if (current_alignment == alignment)
return;
switch (alignment) {
@@ -4742,6 +5155,21 @@ dom_selection_set_alignment (WebKitDOMDocument *document,
dom_selection_save (document);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_ALIGNMENT;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+ ev->data.style.from = current_alignment;
+ ev->data.style.to = alignment;
+ }
+
selection_start_marker = webkit_dom_document_query_selector (
document, "span#-x-evo-selection-start-marker", NULL);
selection_end_marker = webkit_dom_document_query_selector (
@@ -4811,6 +5239,16 @@ dom_selection_set_alignment (WebKitDOMDocument *document,
block = next_block;
}
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
dom_force_spell_check_for_current_paragraph (document, extension);
@@ -4831,8 +5269,50 @@ dom_selection_replace (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *replacement)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ WebKitDOMDOMWindow *window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_REPLACE;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (window);
+
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ ev->data.string.from = webkit_dom_range_get_text (range);
+ ev->data.string.to = g_strdup (replacement);
+ }
+
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, replacement);
+
+ if (ev) {
+ 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);
+ }
+
+ dom_force_spell_check_for_current_paragraph (document, extension);
+
e_html_editor_web_extension_set_content_changed (extension);
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, replacement);
}
/**
@@ -4859,7 +5339,7 @@ dom_replace_caret_word (WebKitDOMDocument *document,
webkit_dom_range_expand (range, "word", NULL);
webkit_dom_dom_selection_add_range (dom_selection, range);
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, replacement);
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, replacement);
dom_force_spell_check_for_current_paragraph (document, extension);
}
@@ -4964,7 +5444,7 @@ dom_prepare_paragraph (WebKitDOMDocument *document,
paragraph = dom_get_paragraph_element (document, extension, -1, 0);
if (with_selection)
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document, paragraph, NULL, NULL);
element = webkit_dom_document_create_element (document, "BR", NULL);
@@ -4991,3 +5471,74 @@ dom_selection_set_on_point (WebKitDOMDocument *document,
webkit_dom_dom_selection_remove_all_ranges (dom_selection);
webkit_dom_dom_selection_add_range (dom_selection, range);
}
+
+void
+dom_selection_get_coordinates (WebKitDOMDocument *document,
+ guint *start_x,
+ guint *start_y,
+ guint *end_x,
+ guint *end_y)
+{
+ gboolean created_selection_markers = FALSE;
+ guint local_x = 0, local_y = 0;
+ WebKitDOMElement *element, *parent;
+
+ g_return_if_fail (start_x != NULL);
+ g_return_if_fail (start_y != NULL);
+ g_return_if_fail (end_x != NULL);
+ g_return_if_fail (end_y != NULL);
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ if (!element) {
+ created_selection_markers = TRUE;
+ dom_selection_save (document);
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ if (!element)
+ return;
+ }
+
+ parent = element;
+ while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+ local_x += (guint) webkit_dom_element_get_offset_left (parent);
+ local_y += (guint) webkit_dom_element_get_offset_top (parent);
+ parent = webkit_dom_element_get_offset_parent (parent);
+ }
+
+ if (start_x)
+ *start_x = local_x;
+ if (start_y)
+ *start_y = local_y;
+
+ if (dom_selection_is_collapsed (document)) {
+ *end_x = local_x;
+ *end_y = local_y;
+
+ if (created_selection_markers)
+ dom_selection_restore (document);
+
+ return;
+ }
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
+
+ local_x = 0;
+ local_y = 0;
+
+ parent = element;
+ while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+ local_x += (guint) webkit_dom_element_get_offset_left (parent);
+ local_y += (guint) webkit_dom_element_get_offset_top (parent);
+ parent = webkit_dom_element_get_offset_parent (parent);
+ }
+
+ if (end_x)
+ *end_x = local_x;
+ if (end_y)
+ *end_y = local_y;
+
+ if (created_selection_markers)
+ dom_selection_restore (document);
+}
diff --git a/web-extensions/e-html-editor-selection-dom-functions.h
b/web-extensions/e-html-editor-selection-dom-functions.h
index 19049b7..7de382d 100644
--- a/web-extensions/e-html-editor-selection-dom-functions.h
+++ b/web-extensions/e-html-editor-selection-dom-functions.h
@@ -84,9 +84,11 @@ void dom_insert_base64_image (WebKitDOMDocument *document,
const gchar *uri,
const gchar *base64_content);
-void dom_unlink (WebKitDOMDocument *document);
+void dom_selection_unlink (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
void dom_create_link (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
const gchar *uri);
EHTMLEditorSelectionBlockFormat
@@ -119,6 +121,22 @@ void dom_set_paragraph_style (WebKitDOMDocument *document,
const gchar *style_to_add);
WebKitDOMElement *
+ dom_create_selection_marker (WebKitDOMDocument *document,
+ gboolean selection_start_marker);
+
+void dom_add_selection_markers_into_element_start
+ (WebKitDOMDocument *document,
+ WebKitDOMElement *element,
+ WebKitDOMElement **selection_start_marker,
+ WebKitDOMElement **selection_end_marker);
+
+void dom_add_selection_markers_into_element_end
+ (WebKitDOMDocument *document,
+ WebKitDOMElement *element,
+ WebKitDOMElement **selection_start_marker,
+ WebKitDOMElement **selection_end_marker);
+
+WebKitDOMElement *
dom_get_paragraph_element (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
gint width,
@@ -130,6 +148,9 @@ WebKitDOMElement *
WebKitDOMNode *node,
WebKitDOMNode *caret_position);
+void dom_selection_wrap (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
WebKitDOMElement *
dom_wrap_paragraph_length (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
@@ -268,6 +289,11 @@ void dom_selection_set_on_point (WebKitDOMDocument *document,
guint x,
guint y);
+void dom_selection_get_coordinates (WebKitDOMDocument *document,
+ guint *start_x,
+ guint *start_y,
+ guint *end_x,
+ guint *end_y);
G_END_DECLS
#endif /* E_HTML_EDITOR_SELECTION_DOM_FUNCTIONS_H */
diff --git a/web-extensions/e-html-editor-table-dialog-dom-functions.c
b/web-extensions/e-html-editor-table-dialog-dom-functions.c
index 64ab7db..e2706db 100644
--- a/web-extensions/e-html-editor-table-dialog-dom-functions.c
+++ b/web-extensions/e-html-editor-table-dialog-dom-functions.c
@@ -149,7 +149,7 @@ e_html_editor_table_dialog_get_column_count (WebKitDOMDocument *document)
return count;
}
-static void
+static WebKitDOMElement *
create_table (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
@@ -226,19 +226,23 @@ create_table (WebKitDOMDocument *document,
dom_selection_restore (document);
e_html_editor_web_extension_set_content_changed (extension);
+
+ return table;
}
gboolean
e_html_editor_table_dialog_show (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorUndoRedoManager *manager;
+ gboolean created = FALSE;
WebKitDOMDOMWindow *window;
WebKitDOMDOMSelection *selection;
+ WebKitDOMElement *table = NULL;
window = webkit_dom_document_get_default_view (document);
selection = webkit_dom_dom_window_get_selection (window);
if (selection && (webkit_dom_dom_selection_get_range_count (selection) > 0)) {
- WebKitDOMElement *table;
WebKitDOMRange *range;
range = webkit_dom_dom_selection_get_range_at (selection, 0, NULL);
@@ -247,12 +251,51 @@ e_html_editor_table_dialog_show (WebKitDOMDocument *document,
if (table) {
webkit_dom_element_set_id (table, "-x-evo-current-table");
- return FALSE;
} else {
- create_table (document, extension);
- return TRUE;
+ table = create_table (document, extension);
+ created = TRUE;
}
}
- return FALSE;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ EHTMLEditorHistoryEvent *ev;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_TABLE_DIALOG;
+
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x,
&ev->before.end.y);
+ if (!created)
+ ev->data.dom.from = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (table), TRUE);
+ else
+ ev->data.dom.from = NULL;
+
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+
+ return created;
+}
+
+void
+e_html_editor_table_dialog_save_history_on_exit (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMElement *element;
+
+ element = WEBKIT_DOM_ELEMENT (get_current_table_element (document));
+ g_return_if_fail (element != NULL);
+
+ webkit_dom_element_remove_attribute (element, "id");
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ ev->data.dom.to = webkit_dom_node_clone_node (
+ WEBKIT_DOM_NODE (element), TRUE);
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y);
}
diff --git a/web-extensions/e-html-editor-table-dialog-dom-functions.h
b/web-extensions/e-html-editor-table-dialog-dom-functions.h
index fcdf392..40198b6 100644
--- a/web-extensions/e-html-editor-table-dialog-dom-functions.h
+++ b/web-extensions/e-html-editor-table-dialog-dom-functions.h
@@ -41,6 +41,11 @@ gulong e_html_editor_table_dialog_get_column_count
gboolean e_html_editor_table_dialog_show (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension);
+
+void e_html_editor_table_dialog_save_history_on_exit
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
G_END_DECLS
#endif /* E_HTML_EDITOR_TABLE_DIALOG_DOM_FUNCTIONS_H */
diff --git a/web-extensions/e-html-editor-undo-redo-manager.c
b/web-extensions/e-html-editor-undo-redo-manager.c
new file mode 100644
index 0000000..f4f51fd
--- /dev/null
+++ b/web-extensions/e-html-editor-undo-redo-manager.c
@@ -0,0 +1,1867 @@
+/*
+ * e-html-editor-undo-redo-manager.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "config.h"
+
+#include "e-html-editor-undo-redo-manager.h"
+#include "e-html-editor-web-extension.h"
+#include "e-html-editor-selection-dom-functions.h"
+#include "e-html-editor-view-dom-functions.h"
+#include "e-dom-utils.h"
+
+#define WEBKIT_DOM_USE_UNSTABLE_API
+#include <webkitdom/WebKitDOMDocumentFragmentUnstable.h>
+#include <webkitdom/WebKitDOMRangeUnstable.h>
+#include <webkitdom/WebKitDOMDOMSelection.h>
+#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
+#include <webkitdom/WebKitDOMHTMLElementUnstable.h>
+#include <webkitdom/WebKitDOMDocumentUnstable.h>
+
+#define E_HTML_EDITOR_UNDO_REDO_MANAGER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER, EHTMLEditorUndoRedoManagerPrivate))
+
+struct _EHTMLEditorUndoRedoManagerPrivate {
+ WebKitDOMDocument *document;
+ GWeakRef extension;
+
+ gboolean can_undo;
+ gboolean can_redo;
+ gboolean operation_in_progress;
+
+ GList *history;
+ guint history_size;
+};
+
+enum {
+ PROP_0,
+ PROP_CAN_REDO,
+ PROP_CAN_UNDO,
+ PROP_HTML_EDITOR_WEB_EXTENSION
+};
+
+#define HISTORY_SIZE_LIMIT 30
+
+#define d(x)
+
+G_DEFINE_TYPE (
+ EHTMLEditorUndoRedoManager,
+ e_html_editor_undo_redo_manager,
+ G_TYPE_OBJECT
+);
+
+void
+e_html_editor_undo_redo_manager_set_document (EHTMLEditorUndoRedoManager *manager,
+ WebKitDOMDocument *document)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager));
+
+ manager->priv->document = document;
+
+ /* The history is not valid if document is changed. */
+ e_html_editor_undo_redo_manager_clean_history (manager);
+}
+
+static EHTMLEditorWebExtension *
+html_editor_undo_redo_manager_ref_extension (EHTMLEditorUndoRedoManager *manager)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager), NULL);
+
+ return g_weak_ref_get (&manager->priv->extension);
+}
+
+static WebKitDOMRange *
+get_range_for_point (WebKitDOMDocument *document,
+ EHTMLEditorSelectionPoint point)
+{
+ glong scroll_left, scroll_top;
+ WebKitDOMHTMLElement *body;
+ WebKitDOMRange *range;
+
+ body = webkit_dom_document_get_body (document);
+ scroll_left = webkit_dom_element_get_scroll_left (WEBKIT_DOM_ELEMENT (body));
+ scroll_top = webkit_dom_element_get_scroll_top (WEBKIT_DOM_ELEMENT (body));
+
+ range = webkit_dom_document_caret_range_from_point (
+ document, point.x - scroll_left, point.y - scroll_top);
+
+ /* The point is outside the viewport, scroll to it. */
+ if (!range) {
+ WebKitDOMDOMWindow *window;
+
+ window = webkit_dom_document_get_default_view (document);
+ webkit_dom_dom_window_scroll_to (window, point.x, point.y);
+
+ scroll_left = webkit_dom_element_get_scroll_left (WEBKIT_DOM_ELEMENT (body));
+ scroll_top = webkit_dom_element_get_scroll_top (WEBKIT_DOM_ELEMENT (body));
+ range = webkit_dom_document_caret_range_from_point (
+ document, point.x - scroll_left, point.y - scroll_top);
+ }
+
+ return range;
+}
+
+static void
+restore_selection_to_history_event_state (WebKitDOMDocument *document,
+ EHTMLEditorSelection selection_state)
+{
+ gboolean was_collapsed = FALSE;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element, *tmp;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ /* Restore the selection how it was before the event occured. */
+ range = get_range_for_point (document, selection_state.start);
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+
+ was_collapsed = selection_state.start.x == selection_state.end.x;
+ was_collapsed = was_collapsed && selection_state.start.y == selection_state.end.y;
+ if (was_collapsed)
+ return;
+
+ dom_selection_save (document);
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
+
+ remove_node (WEBKIT_DOM_NODE (element));
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+
+ webkit_dom_element_remove_attribute (element, "id");
+
+ range = get_range_for_point (document, selection_state.end);
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+
+ dom_selection_save (document);
+
+ tmp = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+
+ remove_node (WEBKIT_DOM_NODE (tmp));
+
+ webkit_dom_element_set_id (
+ element, "-x-evo-selection-start-marker");
+
+ dom_selection_restore (document);
+}
+
+static void
+undo_delete (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event)
+{
+ gboolean empty, single_block;
+ gchar *content;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
+ WebKitDOMElement *element;
+ WebKitDOMNode *first_child, *fragment;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ 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);
+ empty = content && !*content;
+ g_free (content);
+
+ /* Tabulator */
+ single_block = event->type == HISTORY_INPUT;
+ single_block = single_block && event->before.start.x != 0 && event->before.end.y != 0;
+
+ if (!single_block) {
+ /* One block delete */
+ if ((single_block = WEBKIT_DOM_IS_ELEMENT (first_child)))
+ single_block = element_has_id (WEBKIT_DOM_ELEMENT (first_child),
"-x-evo-selection-start-marker");
+ else
+ single_block = WEBKIT_DOM_IS_TEXT (first_child);
+ }
+
+ /* Redoing Return key press */
+ if (empty) {
+ WebKitDOMNode *node;
+
+ 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);
+
+ node = webkit_dom_range_get_start_container (range, NULL);
+ if (!node)
+ return;
+
+ element = get_parent_block_element (node);
+ 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);
+
+ dom_selection_restore (document);
+ dom_force_spell_check (document, extension);
+
+ return;
+ }
+
+ /* Multi block delete */
+ if (WEBKIT_DOM_IS_ELEMENT (first_child) && !single_block) {
+ WebKitDOMNode *node, *parent, *last_child;
+ WebKitDOMNode *parent_deleted_content;
+ WebKitDOMNode *parent_current_block;
+ WebKitDOMNode *insert_before;
+
+ 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);
+ dom_selection_save (document);
+
+ 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);
+ while (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (last_child))
+ last_child = webkit_dom_node_get_last_child (last_child);
+
+ /* All the nodes that are in current block after the caret position
+ * belongs on the end of the deleted content. */
+ node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+ while (node) {
+ WebKitDOMNode *next_sibling;
+
+ next_sibling = webkit_dom_node_get_next_sibling (node);
+ webkit_dom_node_append_child (last_child, node, NULL);
+ node = next_sibling;
+ }
+
+ /* Get the first block in deleted content. */
+ while (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (first_child))
+ first_child = webkit_dom_node_get_first_child (first_child);
+
+ /* 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);
+
+ 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);
+
+ /* Remove the first block from deleted content as its content was already
+ * moved to the right place. */
+ remove_node (first_child);
+
+ /* Move the deleted content back to the body. Start from the next sibling
+ * of the first block (if presented) where the delete occured. */
+ while (parent_deleted_content) {
+ WebKitDOMNode *tmp, *sibling;
+
+ /* Move all the siblings from current level back to the body. */
+ sibling = webkit_dom_node_get_first_child (parent_deleted_content);
+ while (sibling) {
+ WebKitDOMNode *next_sibling;
+
+ next_sibling = webkit_dom_node_get_next_sibling (sibling);
+ webkit_dom_node_insert_before (
+ parent_current_block, sibling, insert_before, NULL);
+ sibling = next_sibling;
+ }
+ tmp = webkit_dom_node_get_parent_node (parent_deleted_content);
+ remove_node (parent_deleted_content);
+ parent_deleted_content = tmp;
+ insert_before = webkit_dom_node_get_next_sibling (parent_current_block);
+ parent_current_block = webkit_dom_node_get_parent_node (parent_current_block);
+ }
+
+ dom_selection_restore (document);
+ dom_force_spell_check (document, extension);
+ } else {
+ WebKitDOMNode *inserted_node, *nd;
+
+ element = webkit_dom_document_create_element (document, "span", NULL);
+
+ range = get_range_for_point (document, event->after.start);
+ /* Create temporary node on the selection where the delete occured. */
+ webkit_dom_range_surround_contents (range, WEBKIT_DOM_NODE (element), NULL);
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+
+ nd = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+ if (nd && WEBKIT_DOM_IS_TEXT (nd)) {
+ gchar *text = webkit_dom_character_data_get_data (WEBKIT_DOM_CHARACTER_DATA (nd));
+ glong length = webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (nd));
+
+ /* We have to preserve empty paragraphs with just UNICODE_ZERO_WIDTH_SPACE
+ * character as when we will remove it it will collapse */
+ if (length > 1) {
+ if (g_str_has_prefix (text, UNICODE_ZERO_WIDTH_SPACE))
+ webkit_dom_character_data_replace_data (
+ WEBKIT_DOM_CHARACTER_DATA (nd), 0, 1, "", NULL);
+ else if (g_str_has_suffix (text, UNICODE_ZERO_WIDTH_SPACE))
+ webkit_dom_character_data_replace_data (
+ WEBKIT_DOM_CHARACTER_DATA (nd), length - 1, 1, "", NULL);
+ }
+ g_free (text);
+ }
+
+ /* Insert the deleted content back to the body. */
+ inserted_node = webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ fragment,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ remove_node (WEBKIT_DOM_NODE (element));
+
+ /* If the selection markers are presented restore the selection,
+ * otherwise the selection was not callapsed so select the deleted
+ * content as it was before the delete occured. */
+ if (webkit_dom_document_fragment_query_selector (event->data.fragment,
"span#-x-evo-selection-start-marker", NULL)) {
+ dom_selection_restore (document);
+ } else {
+ webkit_dom_range_select_node (range, WEBKIT_DOM_NODE (inserted_node), NULL);
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+ }
+
+ 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))
+ dom_check_magic_links (document, extension, FALSE);
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ }
+}
+
+static void
+redo_delete (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event)
+{
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMDocumentFragment *fragment = event->data.fragment;
+ WebKitDOMNode *first_child;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ first_child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+
+ 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;
+
+ /* 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");
+ if (delete)
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "right", "character");
+ else
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+ }
+
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+ dom_force_spell_check_for_current_paragraph (document, extension);
+}
+
+typedef void (*SelectionStyleChangeFunc) (WebKitDOMDocument *document, EHTMLEditorWebExtension *extension,
gint style);
+
+static void
+undo_redo_style_change (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ SelectionStyleChangeFunc func;
+
+ switch (event->type) {
+ case HISTORY_ALIGNMENT:
+ func = (SelectionStyleChangeFunc) dom_selection_set_alignment;
+ break;
+ case HISTORY_BOLD:
+ func = dom_selection_set_bold;
+ break;
+ case HISTORY_BLOCK_FORMAT:
+ func = (SelectionStyleChangeFunc) dom_selection_set_block_format;
+ break;
+ case HISTORY_FONT_SIZE:
+ func = (SelectionStyleChangeFunc) dom_selection_set_font_size;
+ break;
+ case HISTORY_ITALIC:
+ func = dom_selection_set_italic;
+ break;
+ case HISTORY_MONOSPACE:
+ func = dom_selection_set_monospaced;
+ break;
+ case HISTORY_STRIKETHROUGH:
+ func = dom_selection_set_strikethrough;
+ break;
+ case HISTORY_UNDERLINE:
+ func = dom_selection_set_underline;
+ break;
+ default:
+ return;
+ }
+
+ restore_selection_to_history_event_state (document, undo ? event->after : event->before);
+
+ func (document, extension, undo ? event->data.style.from : event->data.style.to);
+
+ restore_selection_to_history_event_state (document, undo ? event->before : event->after);
+}
+
+static void
+undo_redo_indent (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ gboolean was_indent = FALSE;
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ was_indent = event->data.style.from && event->data.style.to;
+
+ if ((undo && was_indent) || (!undo && !was_indent))
+ dom_selection_unindent (document, extension);
+ else
+ dom_selection_indent (document, extension);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_font_color (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ dom_exec_command (
+ document,
+ extension,
+ E_HTML_EDITOR_VIEW_COMMAND_FORE_COLOR,
+ undo ? event->data.string.from : event->data.string.to);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_wrap (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ if (undo) {
+ WebKitDOMNode *node;
+ WebKitDOMElement *element;
+ WebKitDOMRange *range;
+
+ range = dom_get_current_range (document);
+ node = webkit_dom_range_get_common_ancestor_container (range, NULL);
+ element = get_parent_block_element (WEBKIT_DOM_NODE (node));
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (element));
+
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ } else
+ dom_selection_wrap (document, extension);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_page_dialog (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ WebKitDOMHTMLElement *body;
+ WebKitDOMNamedNodeMap *attributes, *attributes_history;
+ gint length, length_history, ii, jj;
+
+ body = webkit_dom_document_get_body (document);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ if (undo) {
+ attributes = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (body));
+ attributes_history = webkit_dom_element_get_attributes (
+ WEBKIT_DOM_ELEMENT (event->data.dom.from));
+ } else {
+ attributes_history = webkit_dom_element_get_attributes (WEBKIT_DOM_ELEMENT (body));
+ attributes = webkit_dom_element_get_attributes (
+ WEBKIT_DOM_ELEMENT (event->data.dom.to));
+ }
+
+ length = webkit_dom_named_node_map_get_length (attributes);
+ length_history = webkit_dom_named_node_map_get_length (attributes_history);
+ for (ii = length - 1; ii >= 0; ii--) {
+ gchar *name;
+ WebKitDOMNode *attr;
+ gboolean replaced = FALSE;
+
+ attr = webkit_dom_named_node_map_item (attributes, ii);
+ name = webkit_dom_node_get_local_name (attr);
+
+ for (jj = length_history - 1; jj >= 0; jj--) {
+ gchar *name_history;
+ WebKitDOMNode *attr_history;
+
+ attr_history = webkit_dom_named_node_map_item (attributes_history, jj);
+ name_history = webkit_dom_node_get_local_name (attr_history);
+ if (g_strcmp0 (name, name_history) == 0) {
+ WebKitDOMNode *attr_clone;
+
+ attr_clone = webkit_dom_node_clone_node (
+ undo ? attr_history : attr, TRUE);
+ webkit_dom_element_set_attribute_node (
+ WEBKIT_DOM_ELEMENT (body),
+ WEBKIT_DOM_ATTR (attr_clone),
+ NULL);
+
+ /* Link color has to replaced in HEAD as well. */
+ if (g_strcmp0 (name, "link") == 0) {
+ gchar *value;
+
+ value = webkit_dom_node_get_node_value (attr_clone);
+ dom_set_link_color (document, value);
+ g_free (value);
+ }
+ replaced = TRUE;
+ }
+ g_free (name_history);
+ g_object_unref (attr_history);
+ if (replaced)
+ break;
+ }
+
+ if (!replaced) {
+ if (undo) {
+ webkit_dom_element_remove_attribute_node (
+ WEBKIT_DOM_ELEMENT (body),
+ WEBKIT_DOM_ATTR (attr),
+ NULL);
+ } else {
+ webkit_dom_element_set_attribute_node (
+ WEBKIT_DOM_ELEMENT (body),
+ WEBKIT_DOM_ATTR (
+ webkit_dom_node_clone_node (attr, TRUE)),
+ NULL);
+ }
+ }
+ g_free (name);
+ g_object_unref (attr);
+ }
+ g_object_unref (attributes);
+ g_object_unref (attributes_history);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_hrule_dialog (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ WebKitDOMElement *element;
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ dom_selection_save (document);
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+
+ if (undo) {
+ WebKitDOMNode *node;
+ WebKitDOMElement *parent;
+
+ parent = get_parent_block_element (WEBKIT_DOM_NODE (element));
+ if (event->data.dom.from)
+ node = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (parent));
+ else
+ node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent));
+
+ if (node && WEBKIT_DOM_IS_HTML_HR_ELEMENT (node)) {
+ if (!event->data.dom.from)
+ remove_node (node);
+ else
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (node),
+ event->data.dom.from,
+ node,
+ NULL);
+ }
+ } else {
+ WebKitDOMNode *node;
+ WebKitDOMElement *parent;
+
+ parent = get_parent_block_element (WEBKIT_DOM_NODE (element));
+
+ if (event->data.dom.from) {
+ node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent));
+
+ if (node && WEBKIT_DOM_IS_HTML_HR_ELEMENT (node))
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (node),
+ event->data.dom.to,
+ node,
+ NULL);
+ } else {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (parent)),
+ event->data.dom.to,
+ webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent)),
+ NULL);
+ }
+ }
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_image_dialog (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ WebKitDOMElement *element;
+ WebKitDOMNode *sibling, *image = NULL;
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ dom_selection_save (document);
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ sibling = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (element));
+ if (sibling && WEBKIT_DOM_IS_ELEMENT (sibling)) {
+ if (WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (sibling))
+ image = sibling;
+ else if (element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-resizable-wrapper"))
+ image = webkit_dom_node_get_first_child (sibling);
+ }
+
+ if (!image) {
+ element = WEBKIT_DOM_ELEMENT (webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element)));
+ sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+ if (sibling && WEBKIT_DOM_IS_ELEMENT (sibling)) {
+ if (WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT (sibling))
+ image = sibling;
+ else if (element_has_class (WEBKIT_DOM_ELEMENT (sibling), "-x-evo-resizable-wrapper"))
+ image = webkit_dom_node_get_first_child (sibling);
+ }
+ }
+
+ if (!image)
+ return;
+
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (image),
+ undo ? event->data.dom.from : event->data.dom.to,
+ image,
+ NULL);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_table_dialog (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ WebKitDOMElement *table, *element;
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ dom_selection_save (document);
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker");
+ if (!element)
+ return;
+
+ table = dom_node_find_parent_element (WEBKIT_DOM_NODE (element), "TABLE");
+
+ if (!table) {
+ if ((!event->data.dom.to && undo) || (!event->data.dom.from && !undo)) {
+ WebKitDOMElement *parent;
+
+ parent = get_parent_block_element (WEBKIT_DOM_NODE (element));
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (parent)),
+ undo ? event->data.dom.from : event->data.dom.to,
+ WEBKIT_DOM_NODE (parent),
+ NULL);
+ restore_selection_to_history_event_state (document, event->before);
+ return;
+ } else
+ return;
+ }
+
+ if (undo) {
+ if (!event->data.dom.from)
+ remove_node (WEBKIT_DOM_NODE (table));
+ else
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (table)),
+ event->data.dom.from,
+ WEBKIT_DOM_NODE (table),
+ NULL);
+ } else {
+ if (!event->data.dom.to)
+ remove_node (WEBKIT_DOM_NODE (table));
+ else
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (table)),
+ event->data.dom.to,
+ WEBKIT_DOM_NODE (table),
+ NULL);
+ }
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_redo_paste (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ if (undo) {
+ if (event->type == HISTORY_PASTE_QUOTED) {
+ WebKitDOMElement *tmp;
+ WebKitDOMNode *parent;
+ WebKitDOMNode *sibling;
+
+ restore_selection_to_history_event_state (document, event->after);
+
+ dom_selection_save (document);
+ tmp = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ if (!tmp)
+ return;
+
+ parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (tmp));
+ while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (parent)))
+ parent = webkit_dom_node_get_parent_node (parent);
+
+ sibling = webkit_dom_node_get_previous_sibling (parent);
+ if (sibling) {
+ dom_add_selection_markers_into_element_end (document, WEBKIT_DOM_ELEMENT
(sibling), NULL, NULL);
+
+ remove_node (parent);
+ } else {
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (parent),
+ WEBKIT_DOM_NODE (dom_prepare_paragraph (document, extension, TRUE)),
+ parent,
+ NULL);
+ }
+ dom_selection_restore (document);
+ } else {
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element, *tmp;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ /* Restore the selection how it was before the event occured. */
+ 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);
+
+ dom_selection_save (document);
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
+
+ remove_node (WEBKIT_DOM_NODE (element));
+
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+
+ webkit_dom_element_remove_attribute (element, "id");
+
+ 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);
+
+ dom_selection_save (document);
+
+ tmp = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+
+ remove_node (WEBKIT_DOM_NODE (tmp));
+
+ webkit_dom_element_set_id (
+ element, "-x-evo-selection-start-marker");
+
+ dom_selection_restore (document);
+
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ }
+ } else {
+ restore_selection_to_history_event_state (document, event->before);
+
+ if (event->type == HISTORY_PASTE)
+ dom_convert_and_insert_html_into_selection (document, extension,
event->data.string.to, FALSE);
+ else if (event->type == HISTORY_PASTE_QUOTED)
+ dom_quote_and_insert_text_into_selection (document, extension, event->data.string.to);
+ else if (event->type == HISTORY_INSERT_HTML)
+ dom_insert_html (document, extension, event->data.string.to);
+ else
+ dom_convert_and_insert_html_into_selection (document, extension,
event->data.string.to, FALSE);
+ //e_html_editor_selection_insert_as_text (selection, event->data.string.to);
+ }
+}
+
+static void
+undo_redo_image (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ if (undo) {
+ WebKitDOMElement *element;
+ WebKitDOMNode *node;
+
+ 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);
+
+ dom_selection_save (document);
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-end-marker");
+
+ node = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (element));
+
+ if (WEBKIT_DOM_IS_ELEMENT (node))
+ if (element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-resizable-wrapper") ||
+ element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-smiley-wrapper"))
+ remove_node (node);
+ dom_selection_restore (document);
+ } else {
+ WebKitDOMElement *element;
+
+ range = get_range_for_point (document, event->before.start);
+ /* Create temporary node on the selection where the delete occured. */
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, range);
+
+ dom_selection_save (document);
+ element = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+
+ /* Insert the deleted content back to the body. */
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (event->data.fragment), TRUE),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ dom_selection_restore (document);
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ }
+}
+
+static void
+undo_redo_replace (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ restore_selection_to_history_event_state (document, undo ? event->after : event->before);
+
+ if (undo) {
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "word");
+ }
+
+ dom_exec_command (
+ document,
+ extension,
+ E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT,
+ undo ? event->data.string.from : event->data.string.to);
+
+ dom_force_spell_check_for_current_paragraph (document, extension);
+
+ restore_selection_to_history_event_state (document, undo ? event->before : event->after);
+}
+
+static void
+undo_redo_replace_all (EHTMLEditorUndoRedoManager *manager,
+ WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ if (undo) {
+ if (event->type == HISTORY_REPLACE) {
+ undo_redo_replace (document, extension, event, undo);
+ return;
+ } else {
+ EHTMLEditorHistoryEvent *next_event;
+ GList *next_item;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+
+ next_item = manager->priv->history->next;
+
+ while (next_item) {
+ next_event = next_item->data;
+
+ if (next_event->type != HISTORY_REPLACE)
+ break;
+
+ if (g_strcmp0 (next_event->data.string.from, event->data.string.from) != 0)
+ break;
+
+ if (g_strcmp0 (next_event->data.string.to, event->data.string.to) != 0)
+ break;
+
+ undo_redo_replace (document, extension, next_event, undo);
+
+ next_item = next_item->next;
+ }
+
+ manager->priv->history = next_item->prev;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+ webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
+ }
+ } else {
+ /* Find if this history item is part of HISTORY_REPLACE_ALL. */
+ EHTMLEditorHistoryEvent *prev_event;
+ GList *prev_item;
+ gboolean replace_all = FALSE;
+
+ prev_item = manager->priv->history->prev;
+ while (prev_item) {
+ prev_event = prev_item->data;
+
+ if (prev_event->type == HISTORY_REPLACE)
+ prev_item = prev_item->prev;
+ else if (prev_event->type == HISTORY_REPLACE_ALL) {
+ replace_all = TRUE;
+ break;
+ } else
+ break;
+ }
+
+ if (!replace_all) {
+ undo_redo_replace (document, extension, event, undo);
+ return;
+ }
+
+ prev_item = manager->priv->history->prev;
+ while (prev_item) {
+ prev_event = prev_item->data;
+
+ if (prev_event->type == HISTORY_REPLACE) {
+ undo_redo_replace (document, extension, prev_event, undo);
+ prev_item = prev_item->prev;
+ } else
+ break;
+ }
+
+ manager->priv->history = prev_item->next;
+ }
+}
+
+static void
+undo_redo_remove_link (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ if (undo) {
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+ /* Select the anchor. */
+ webkit_dom_dom_selection_modify (dom_selection, "move", "left", "word");
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "right", "word");
+
+ range = dom_get_current_range (document);
+ element = webkit_dom_document_create_element (document, "SPAN", NULL);
+ webkit_dom_range_surround_contents (range, WEBKIT_DOM_NODE (element), NULL);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (event->data.fragment), TRUE),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ remove_node (WEBKIT_DOM_NODE (element));
+ } else
+ dom_selection_unlink (document, extension);
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->before);
+}
+
+static void
+undo_input (EHTMLEditorUndoRedoManager *manager,
+ WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event)
+{
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ restore_selection_to_history_event_state (document, event->after);
+
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+ if (dom_selection_is_citation (document)) {
+ /* Post processing of quoted text in body_input_event_cb needs to be called. */
+ manager->priv->operation_in_progress = FALSE;
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, TRUE);
+ }
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+}
+
+static void
+undo_redo_citation_split (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ if (undo) {
+ gint citation_level = 1, length, word_wrap_length;
+ WebKitDOMElement *selection_start, *parent;
+ WebKitDOMNode *citation_before, *citation_after, *child, *last_child, *tmp;
+
+ restore_selection_to_history_event_state (document, event->after);
+
+ dom_selection_save (document);
+ selection_start = webkit_dom_document_get_element_by_id (
+ document, "-x-evo-selection-start-marker");
+ if (!selection_start)
+ return;
+
+ parent = get_parent_block_element (WEBKIT_DOM_NODE (selection_start));
+
+ citation_before = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (parent));
+ if (!dom_node_is_citation_node (citation_before))
+ return;
+
+ citation_after = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent));
+ if (!dom_node_is_citation_node (citation_after))
+ return;
+
+ /* 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++;
+ child = webkit_dom_node_get_first_child (child);
+ }
+
+ dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (child));
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (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);
+
+ dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (last_child));
+ dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (last_child));
+
+ /* Copy the content of the first block to the last block to get
+ * to the state how the block looked like before it was split. */
+ 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);
+
+ remove_node (child);
+
+ /* Move all the block from next citation to the previous one. */
+ while ((child = webkit_dom_node_get_first_child (citation_after)))
+ webkit_dom_node_append_child (citation_before, child, NULL);
+
+ remove_node (WEBKIT_DOM_NODE (parent));
+ remove_node (WEBKIT_DOM_NODE (citation_after));
+
+ /* If enter was pressed when some text was selected, restore it. */
+ if (event->data.fragment != NULL)
+ undo_delete (document, extension, event);
+
+ restore_selection_to_history_event_state (document, event->before);
+
+ dom_force_spell_check (document, extension);
+ } else {
+ dom_insert_new_line_into_citation (document, extension, "");
+ }
+}
+
+gboolean
+e_html_editor_undo_redo_manager_is_operation_in_progress (EHTMLEditorUndoRedoManager *manager)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager), FALSE);
+
+ return manager->priv->operation_in_progress;
+}
+
+void
+e_html_editor_undo_redo_manager_set_operation_in_progress (EHTMLEditorUndoRedoManager *manager,
+ gboolean value)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager));
+
+ manager->priv->operation_in_progress = value;
+}
+
+#if d(1)+0
+static void
+print_fragment_inner_html (WebKitDOMDocumentFragment *fragment)
+{
+ WebKitDOMDocument *document;
+ WebKitDOMElement *div;
+ gchar *inner_html;
+
+ if (!fragment) {
+ printf ("\tNone'\n");
+ return;
+ }
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (fragment));
+ div = webkit_dom_document_create_element (document, "div", NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (div),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (fragment), TRUE),
+ NULL);
+
+ inner_html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT (div));
+ printf ("\t'%s'\n", inner_html);
+ remove_node (WEBKIT_DOM_NODE (div));
+ g_free (inner_html);
+}
+
+static void
+print_node_inner_html (WebKitDOMNode *fragment)
+{
+ WebKitDOMDocument *document;
+ WebKitDOMElement *div;
+ gchar *inner_html;
+
+ if (!fragment) {
+ printf ("\tnone\n");
+ return;
+ }
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (fragment));
+ div = webkit_dom_document_create_element (document, "div", NULL);
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (div),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (fragment), TRUE),
+ NULL);
+
+ inner_html = webkit_dom_html_element_get_inner_html (WEBKIT_DOM_HTML_ELEMENT (div));
+ remove_node (WEBKIT_DOM_NODE (div));
+
+ printf ("\t'%s'\n", inner_html);
+
+ g_free (inner_html);
+}
+
+static void
+print_history_event (EHTMLEditorHistoryEvent *event)
+{
+ printf ("HISTORY EVENT: %d ; \n", event->type);
+ printf ("\t before: start_x: %u ; start_y: %u ; end_x: %u ; end_y: %u ;\n", event->before.start.x,
event->before.start.y, event->before.end.x, event->before.end.y);
+ printf ("\t after: start_x: %u ; start_y: %u ; end_x: %u ; end_y: %u ;\n", event->after.start.x,
event->after.start.y, event->after.end.x, event->after.end.y);
+ switch (event->type) {
+ case HISTORY_DELETE:
+ case HISTORY_INPUT:
+ case HISTORY_REMOVE_LINK:
+ case HISTORY_SMILEY:
+ case HISTORY_IMAGE:
+ case HISTORY_CITATION_SPLIT:
+ print_fragment_inner_html (event->data.fragment);
+ break;
+ case HISTORY_ALIGNMENT:
+ case HISTORY_BLOCK_FORMAT:
+ case HISTORY_BOLD:
+ case HISTORY_FONT_SIZE:
+ case HISTORY_INDENT:
+ case HISTORY_ITALIC:
+ case HISTORY_MONOSPACE:
+ case HISTORY_UNDERLINE:
+ case HISTORY_STRIKETHROUGH:
+ case HISTORY_WRAP:
+ printf (" from %d to %d ;\n", event->data.style.from, event->data.style.to);
+ break;
+ case HISTORY_PASTE:
+ case HISTORY_PASTE_AS_TEXT:
+ case HISTORY_PASTE_QUOTED:
+ case HISTORY_INSERT_HTML:
+ printf (" pasting: '%s' ; \n", event->data.string.to);
+ break;
+ case HISTORY_HRULE_DIALOG:
+ case HISTORY_IMAGE_DIALOG:
+ case HISTORY_CELL_DIALOG:
+ case HISTORY_TABLE_DIALOG:
+ case HISTORY_PAGE_DIALOG:
+ print_node_inner_html (event->data.dom.from);
+ print_node_inner_html (event->data.dom.to);
+ break;
+ case HISTORY_FONT_COLOR:
+ case HISTORY_REPLACE:
+ case HISTORY_REPLACE_ALL:
+ printf (" from '%s' to '%s';\n", event->data.string.from, event->data.string.to);
+ break;
+ case HISTORY_START:
+ printf ("HISTORY START\n");
+ break;
+ default:
+ printf ("Unknown history type\n");
+ }
+}
+
+static void
+print_history (EHTMLEditorUndoRedoManager *manager)
+{
+ if (manager->priv->history) {
+ printf ("\n");
+ g_list_foreach (
+ manager->priv->history, (GFunc) print_history_event, NULL);
+ printf ("\n");
+ } else {
+ printf ("History empty!\n");
+ }
+}
+
+static void
+print_undo_events (EHTMLEditorUndoRedoManager *manager)
+{
+ GList *item = manager->priv->history;
+
+ printf ("UNDO EVENTS:\n");
+ if (!item || !item->next) {
+ printf ("EMPTY\n");
+ return;
+ }
+
+ print_history_event (item->data);
+ item = item->next;
+ while (item) {
+ print_history_event (item->data);
+ item = item->next;
+ }
+
+ printf ("\n");
+
+}
+
+static void
+print_redo_events (EHTMLEditorUndoRedoManager *manager)
+{
+ GList *item = manager->priv->history;
+
+ printf ("REDO EVENTS:\n");
+ if (!item || !item->prev) {
+ printf ("EMPTY\n");
+ return;
+ }
+
+ item = item->prev;
+ while (item) {
+ print_history_event (item->data);
+ item = item->prev;
+ }
+
+ printf ("\n");
+}
+#endif
+
+static void
+free_history_event_content (EHTMLEditorHistoryEvent *event)
+{
+ switch (event->type) {
+ case HISTORY_INPUT:
+ case HISTORY_DELETE:
+ case HISTORY_CITATION_SPLIT:
+ case HISTORY_IMAGE:
+ case HISTORY_SMILEY:
+ case HISTORY_REMOVE_LINK:
+ if (event->data.fragment != NULL)
+ g_object_unref (event->data.fragment);
+ break;
+ case HISTORY_FONT_COLOR:
+ case HISTORY_PASTE:
+ case HISTORY_PASTE_AS_TEXT:
+ case HISTORY_PASTE_QUOTED:
+ case HISTORY_INSERT_HTML:
+ case HISTORY_REPLACE:
+ case HISTORY_REPLACE_ALL:
+ if (event->data.string.from != NULL)
+ g_free (event->data.string.from);
+ if (event->data.string.to != NULL)
+ g_free (event->data.string.to);
+ break;
+ case HISTORY_HRULE_DIALOG:
+ case HISTORY_IMAGE_DIALOG:
+ case HISTORY_CELL_DIALOG:
+ case HISTORY_TABLE_DIALOG:
+ case HISTORY_PAGE_DIALOG:
+ if (event->data.dom.from != NULL)
+ g_object_unref (event->data.dom.from);
+ if (event->data.dom.to != NULL)
+ g_object_unref (event->data.dom.to);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+free_history_event (EHTMLEditorHistoryEvent *event)
+{
+ if (event == NULL)
+ return;
+
+ free_history_event_content (event);
+
+ g_free (event);
+}
+
+static void
+remove_history_event (EHTMLEditorUndoRedoManager *manager,
+ GList *item)
+{
+ free_history_event_content (item->data);
+
+ manager->priv->history = g_list_delete_link (manager->priv->history, item);
+ manager->priv->history_size--;
+}
+
+static void
+remove_forward_redo_history_events_if_needed (EHTMLEditorUndoRedoManager *manager)
+{
+ GList *history = manager->priv->history;
+ GList *item;
+
+ if (!history || !history->prev)
+ return;
+
+ item = history->prev;
+ while (item) {
+ GList *prev_item = item->prev;
+
+ remove_history_event (manager, item);
+ item = prev_item;
+ }
+}
+
+void
+e_html_editor_undo_redo_manager_insert_history_event (EHTMLEditorUndoRedoManager *manager,
+ EHTMLEditorHistoryEvent *event)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager));
+
+ if (manager->priv->operation_in_progress)
+ return;
+
+ d (print_history_event (event));
+
+ remove_forward_redo_history_events_if_needed (manager);
+
+ if (manager->priv->history_size >= HISTORY_SIZE_LIMIT)
+ remove_history_event (manager, g_list_last (manager->priv->history)->prev);
+
+ manager->priv->history = g_list_prepend (manager->priv->history, event);
+ manager->priv->history_size++;
+ manager->priv->can_undo = TRUE;
+
+ g_object_notify (G_OBJECT (manager), "can-undo");
+}
+
+EHTMLEditorHistoryEvent *
+e_html_editor_undo_redo_manager_get_current_history_event (EHTMLEditorUndoRedoManager *manager)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager), NULL);
+
+ if (manager->priv->history)
+ return manager->priv->history->data;
+
+ return NULL;
+}
+
+gboolean
+e_html_editor_undo_redo_manager_can_undo (EHTMLEditorUndoRedoManager *manager)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager), FALSE);
+
+ if (manager->priv->history) {
+ EHTMLEditorHistoryEvent *event;
+
+ event = manager->priv->history->data;
+
+ return (event->type != HISTORY_START);
+ } else
+ return FALSE;
+}
+
+static gboolean
+event_selection_was_collapsed (EHTMLEditorHistoryEvent *ev)
+{
+ return (ev->before.start.x == ev->before.end.x) && (ev->before.start.y == ev->before.end.y);
+}
+
+void
+e_html_editor_undo_redo_manager_undo (EHTMLEditorUndoRedoManager *manager)
+{
+ EHTMLEditorHistoryEvent *event;
+ EHTMLEditorWebExtension *extension;
+ GList *history;
+ WebKitDOMDocument *document;
+
+ g_return_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager));
+
+ if (!e_html_editor_undo_redo_manager_can_undo (manager))
+ return;
+
+ history = manager->priv->history;
+ event = history->data;
+
+ d (print_history_event (event));
+
+ manager->priv->operation_in_progress = TRUE;
+
+ document = manager->priv->document;
+ extension = html_editor_undo_redo_manager_ref_extension (manager);
+ g_return_if_fail (extension != NULL);
+
+ switch (event->type) {
+ case HISTORY_BOLD:
+ case HISTORY_ITALIC:
+ case HISTORY_STRIKETHROUGH:
+ case HISTORY_UNDERLINE:
+ case HISTORY_FONT_SIZE:
+ if (event_selection_was_collapsed (event)) {
+ if (history->next) {
+ manager->priv->history = history->next;
+ e_html_editor_undo_redo_manager_undo (manager);
+ }
+ manager->priv->operation_in_progress = FALSE;
+ g_object_unref (extension);
+ return;
+ }
+ case HISTORY_ALIGNMENT:
+ case HISTORY_BLOCK_FORMAT:
+ case HISTORY_MONOSPACE:
+ undo_redo_style_change (document, extension, event, TRUE);
+ break;
+ case HISTORY_DELETE:
+ undo_delete (document, extension, event);
+ break;
+ case HISTORY_INDENT:
+ undo_redo_indent (document, extension, event, TRUE);
+ break;
+ case HISTORY_INPUT:
+ undo_input (manager, document, extension, event);
+ break;
+ case HISTORY_REMOVE_LINK:
+ undo_redo_remove_link (document, extension, event, TRUE);
+ break;
+ case HISTORY_FONT_COLOR:
+ undo_redo_font_color (document, extension, event, TRUE);
+ break;
+ case HISTORY_CITATION_SPLIT:
+ undo_redo_citation_split (document, extension, event, TRUE);
+ break;
+ case HISTORY_PASTE:
+ case HISTORY_PASTE_AS_TEXT:
+ case HISTORY_PASTE_QUOTED:
+ case HISTORY_INSERT_HTML:
+ undo_redo_paste (document, extension, event, TRUE);
+ break;
+ case HISTORY_IMAGE:
+ case HISTORY_SMILEY:
+ undo_redo_image (document, extension, event, TRUE);
+ break;
+ case HISTORY_WRAP:
+ undo_redo_wrap (document, extension, event, TRUE);
+ break;
+ case HISTORY_IMAGE_DIALOG:
+ undo_redo_image_dialog (document, extension, event, TRUE);
+ break;
+ case HISTORY_TABLE_DIALOG:
+ undo_redo_table_dialog (document, extension, event, TRUE);
+ break;
+ case HISTORY_PAGE_DIALOG:
+ undo_redo_page_dialog (document, extension, event, TRUE);
+ break;
+ case HISTORY_HRULE_DIALOG:
+ undo_redo_hrule_dialog (document, extension, event, TRUE);
+ break;
+ case HISTORY_REPLACE:
+ case HISTORY_REPLACE_ALL:
+ undo_redo_replace_all (manager, document, extension, event, TRUE);
+ break;
+ default:
+ g_object_unref (extension);
+ return;
+ }
+
+ if (history->next)
+ manager->priv->history = manager->priv->history->next;
+
+ d (print_history (manager));
+/* FIXME WK2
+ html_editor_view_user_changed_contents_cb (view);*/
+
+ manager->priv->operation_in_progress = FALSE;
+
+ g_object_unref (extension);
+}
+
+gboolean
+e_html_editor_undo_redo_manager_can_redo (EHTMLEditorUndoRedoManager *manager)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager), FALSE);
+
+ if (manager->priv->history && manager->priv->history->prev)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void
+e_html_editor_undo_redo_manager_redo (EHTMLEditorUndoRedoManager *manager)
+{
+ EHTMLEditorWebExtension *extension;
+ EHTMLEditorHistoryEvent *event;
+ GList *history;
+ WebKitDOMDocument *document;
+
+ if (!e_html_editor_undo_redo_manager_can_redo (manager))
+ return;
+
+ history = manager->priv->history;
+ event = history->prev->data;
+
+ d (print_history_event (event));
+
+ document = manager->priv->document;
+ extension = html_editor_undo_redo_manager_ref_extension (manager);
+ g_return_if_fail (extension != NULL);
+
+ manager->priv->operation_in_progress = TRUE;
+
+ switch (event->type) {
+ case HISTORY_BOLD:
+ case HISTORY_MONOSPACE:
+ case HISTORY_STRIKETHROUGH:
+ case HISTORY_UNDERLINE:
+ case HISTORY_ALIGNMENT:
+ case HISTORY_BLOCK_FORMAT:
+ case HISTORY_FONT_SIZE:
+ case HISTORY_ITALIC:
+ undo_redo_style_change (document, extension, event, FALSE);
+ break;
+ case HISTORY_DELETE:
+ redo_delete (document, extension, event);
+ break;
+ case HISTORY_INDENT:
+ undo_redo_indent (document, extension, event, FALSE);
+ break;
+ case HISTORY_INPUT:
+ undo_delete (document, extension, event);
+ break;
+ case HISTORY_REMOVE_LINK:
+ undo_redo_remove_link (document, extension, event, FALSE);
+ break;
+ case HISTORY_FONT_COLOR:
+ undo_redo_font_color (document, extension, event, FALSE);
+ break;
+ case HISTORY_CITATION_SPLIT:
+ undo_redo_citation_split (document, extension, event, FALSE);
+ break;
+ case HISTORY_PASTE:
+ case HISTORY_PASTE_AS_TEXT:
+ case HISTORY_PASTE_QUOTED:
+ case HISTORY_INSERT_HTML:
+ undo_redo_paste (document, extension, event, FALSE);
+ break;
+ case HISTORY_IMAGE:
+ case HISTORY_SMILEY:
+ undo_redo_image (document, extension, event, FALSE);
+ break;
+ case HISTORY_WRAP:
+ undo_redo_wrap (document, extension, event, FALSE);
+ break;
+ case HISTORY_IMAGE_DIALOG:
+ undo_redo_image_dialog (document, extension, event, FALSE);
+ break;
+ case HISTORY_TABLE_DIALOG:
+ undo_redo_table_dialog (document, extension, event, FALSE);
+ break;
+ case HISTORY_PAGE_DIALOG:
+ undo_redo_page_dialog (document, extension, event, FALSE);
+ break;
+ case HISTORY_HRULE_DIALOG:
+ undo_redo_hrule_dialog (document, extension, event, FALSE);
+ break;
+ case HISTORY_REPLACE:
+ case HISTORY_REPLACE_ALL:
+ undo_redo_replace_all (manager, document, extension, event, FALSE);
+ break;
+ default:
+ g_object_unref (extension);
+ return;
+ }
+
+ manager->priv->history = manager->priv->history->prev;
+
+ d (print_history (manager));
+/* FIXME WK2
+ html_editor_view_user_changed_contents_cb (view);*/
+
+ manager->priv->operation_in_progress = FALSE;
+
+ g_object_unref (extension);
+}
+
+void
+e_html_editor_undo_redo_manager_clean_history (EHTMLEditorUndoRedoManager *manager)
+{
+ EHTMLEditorWebExtension *extension;
+ EHTMLEditorHistoryEvent *ev;
+
+ g_return_if_fail (E_IS_HTML_EDITOR_UNDO_REDO_MANAGER (manager));
+
+ if (manager->priv->history != NULL) {
+ g_list_free_full (manager->priv->history, (GDestroyNotify) free_history_event);
+ manager->priv->history = NULL;
+ }
+
+ manager->priv->history_size = 0;
+ extension = html_editor_undo_redo_manager_ref_extension (manager);
+ g_return_if_fail (extension != NULL);
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+ g_object_unref (extension);
+ manager->priv->operation_in_progress = FALSE;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_START;
+ manager->priv->history = g_list_append (manager->priv->history, ev);
+
+ manager->priv->can_undo = FALSE;
+ g_object_notify (G_OBJECT (manager), "can-undo");
+ manager->priv->can_redo = FALSE;
+ g_object_notify (G_OBJECT (manager), "can-redo");
+}
+
+static void
+html_editor_undo_redo_manager_set_extension (EHTMLEditorUndoRedoManager *manager,
+ EHTMLEditorWebExtension *extension)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_WEB_EXTENSION (extension));
+
+ g_weak_ref_set (&manager->priv->extension, extension);
+}
+
+static void
+html_editor_undo_redo_manager_dispose (GObject *object)
+{
+ EHTMLEditorUndoRedoManagerPrivate *priv;
+ EHTMLEditorWebExtension *extension;
+
+ priv = E_HTML_EDITOR_UNDO_REDO_MANAGER_GET_PRIVATE (object);
+
+ if (priv->history != NULL) {
+ g_list_free_full (priv->history, (GDestroyNotify) free_history_event);
+ priv->history = NULL;
+ }
+
+ extension = g_weak_ref_get (&priv->extension);
+ g_clear_object (&extension);
+ g_weak_ref_set (&priv->extension, NULL);
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_html_editor_undo_redo_manager_parent_class)->dispose (object);
+}
+
+static void
+html_editor_undo_redo_manager_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CAN_REDO:
+ g_value_set_boolean (
+ value, e_html_editor_undo_redo_manager_can_redo (
+ E_HTML_EDITOR_UNDO_REDO_MANAGER (object)));
+ return;
+
+ case PROP_CAN_UNDO:
+ g_value_set_boolean (
+ value, e_html_editor_undo_redo_manager_can_undo (
+ E_HTML_EDITOR_UNDO_REDO_MANAGER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+html_editor_undo_redo_manager_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_HTML_EDITOR_WEB_EXTENSION:
+ html_editor_undo_redo_manager_set_extension (
+ E_HTML_EDITOR_UNDO_REDO_MANAGER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_html_editor_undo_redo_manager_class_init (EHTMLEditorUndoRedoManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EHTMLEditorUndoRedoManagerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = html_editor_undo_redo_manager_dispose;
+ object_class->get_property = html_editor_undo_redo_manager_get_property;
+ object_class->set_property = html_editor_undo_redo_manager_set_property;
+
+ /**
+ * EHTMLEditorUndoRedoManager:can-redo
+ *
+ * Determines whether it's possible to redo previous action. The action
+ * is usually disabled when there is no action to redo.
+ */
+ g_object_class_install_property (
+ object_class,
+ PROP_CAN_REDO,
+ g_param_spec_boolean (
+ "can-redo",
+ "Can Redo",
+ NULL,
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * EHTMLEditorUndoRedoManager:can-undo
+ *
+ * Determines whether it's possible to undo last action. The action
+ * is usually disabled when there is no previous action to undo.
+ */
+ g_object_class_install_property (
+ object_class,
+ PROP_CAN_UNDO,
+ g_param_spec_boolean (
+ "can-undo",
+ "Can Undo",
+ NULL,
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HTML_EDITOR_WEB_EXTENSION,
+ g_param_spec_object (
+ "html-editor-web-extension",
+ NULL,
+ NULL,
+ E_TYPE_HTML_EDITOR_WEB_EXTENSION,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_html_editor_undo_redo_manager_init (EHTMLEditorUndoRedoManager *manager)
+{
+ manager->priv = E_HTML_EDITOR_UNDO_REDO_MANAGER_GET_PRIVATE (manager);
+
+ manager->priv->operation_in_progress = FALSE;
+ manager->priv->history = NULL;
+ e_html_editor_undo_redo_manager_clean_history (manager);
+}
diff --git a/web-extensions/e-html-editor-undo-redo-manager.h
b/web-extensions/e-html-editor-undo-redo-manager.h
new file mode 100644
index 0000000..a1d227e
--- /dev/null
+++ b/web-extensions/e-html-editor-undo-redo-manager.h
@@ -0,0 +1,102 @@
+/*
+ * e-html-editor-undo-redo-manager.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_HTML_EDITOR_UNDO_REDO_MANAGER_H
+#define E_HTML_EDITOR_UNDO_REDO_MANAGER_H
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <webkitdom/webkitdom.h>
+
+#include "e-html-editor-history-event.h"
+
+#define E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER \
+ (e_html_editor_undo_redo_manager_get_type ())
+#define E_HTML_EDITOR_UNDO_REDO_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER, EHTMLEditorUndoRedoManager))
+#define E_HTML_EDITOR_UNDO_REDO_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER, EHTMLEditorUndoRedoManagerClass))
+#define E_IS_HTML_EDITOR_UNDO_REDO_MANAGER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER))
+#define E_IS_HTML_EDITOR_UNDO_REDO_MANAGER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER))
+#define E_HTML_EDITOR_UNDO_REDO_MANAGER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER, EHTMLEditorUndoRedoManagerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EHTMLEditorUndoRedoManager EHTMLEditorUndoRedoManager;
+typedef struct _EHTMLEditorUndoRedoManagerClass EHTMLEditorUndoRedoManagerClass;
+typedef struct _EHTMLEditorUndoRedoManagerPrivate EHTMLEditorUndoRedoManagerPrivate;
+
+struct _EHTMLEditorUndoRedoManager {
+ GObject parent;
+ EHTMLEditorUndoRedoManagerPrivate *priv;
+};
+
+struct _EHTMLEditorUndoRedoManagerClass
+{
+ GObjectClass parent_class;
+};
+
+GType e_html_editor_undo_redo_manager_get_type
+ (void) G_GNUC_CONST;
+
+void e_html_editor_undo_redo_manager_set_document
+ (EHTMLEditorUndoRedoManager *manager,
+ WebKitDOMDocument *document);
+
+gboolean e_html_editor_undo_redo_manager_is_operation_in_progress
+ (EHTMLEditorUndoRedoManager *manager);
+
+void e_html_editor_undo_redo_manager_set_operation_in_progress
+ (EHTMLEditorUndoRedoManager *manager,
+ gboolean value);
+
+void e_html_editor_undo_redo_manager_insert_history_event
+ (EHTMLEditorUndoRedoManager *manager,
+ EHTMLEditorHistoryEvent *event);
+
+EHTMLEditorHistoryEvent *
+ e_html_editor_undo_redo_manager_get_current_history_event
+ (EHTMLEditorUndoRedoManager *manager);
+
+gboolean e_html_editor_undo_redo_manager_can_undo
+ (EHTMLEditorUndoRedoManager *manager);
+
+void e_html_editor_undo_redo_manager_undo
+ (EHTMLEditorUndoRedoManager *manager);
+
+gboolean e_html_editor_undo_redo_manager_can_redo
+ (EHTMLEditorUndoRedoManager *manager);
+
+void e_html_editor_undo_redo_manager_redo
+ (EHTMLEditorUndoRedoManager *manager);
+
+void e_html_editor_undo_redo_manager_clean_history
+ (EHTMLEditorUndoRedoManager *manager);
+
+G_END_DECLS
+
+#endif /* E_HTML_EDITOR_UNDO_REDO_MANAGER_H */
diff --git a/web-extensions/e-html-editor-view-dom-functions.c
b/web-extensions/e-html-editor-view-dom-functions.c
index d6f28db..e2a363f 100644
--- a/web-extensions/e-html-editor-view-dom-functions.c
+++ b/web-extensions/e-html-editor-view-dom-functions.c
@@ -54,6 +54,7 @@
*/
gboolean
dom_exec_command (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
EHTMLEditorViewCommand command,
const gchar *value)
{
@@ -120,6 +121,8 @@ dom_exec_command (WebKitDOMDocument *document,
CHECK_COMMAND (E_HTML_EDITOR_VIEW_COMMAND_USE_CSS, "UseCSS", TRUE)
}
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, TRUE);
+
return webkit_dom_document_exec_command (
document, cmd_str, FALSE, has_value ? value : "" );
}
@@ -214,87 +217,6 @@ dom_force_spell_check_for_current_paragraph (WebKitDOMDocument *document,
dom_selection_restore (document);
}
-static WebKitDOMElement *
-create_selection_marker (WebKitDOMDocument *document,
- gboolean start)
-{
- WebKitDOMElement *element;
-
- element = webkit_dom_document_create_element (
- document, "SPAN", NULL);
- webkit_dom_element_set_id (
- element,
- start ? "-x-evo-selection-start-marker" :
- "-x-evo-selection-end-marker");
-
- return element;
-}
-
-static void
-remove_selection_markers (WebKitDOMDocument *document)
-{
- WebKitDOMElement *marker;
-
- marker = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-start-marker");
- if (marker)
- remove_node (WEBKIT_DOM_NODE (marker));
- marker = webkit_dom_document_get_element_by_id (
- document, "-x-evo-selection-end-marker");
- if (marker)
- remove_node (WEBKIT_DOM_NODE (marker));
-}
-
-static void
-add_selection_markers_into_element_start (WebKitDOMDocument *document,
- WebKitDOMElement *element,
- WebKitDOMElement **selection_start_marker,
- WebKitDOMElement **selection_end_marker)
-{
- WebKitDOMElement *marker;
-
- remove_selection_markers (document);
- marker = create_selection_marker (document, FALSE);
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (marker),
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element)),
- NULL);
- if (selection_end_marker)
- *selection_end_marker = marker;
-
- marker = create_selection_marker (document, TRUE);
- webkit_dom_node_insert_before (
- WEBKIT_DOM_NODE (element),
- WEBKIT_DOM_NODE (marker),
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element)),
- NULL);
- if (selection_start_marker)
- *selection_start_marker = marker;
-}
-
-static void
-add_selection_markers_into_element_end (WebKitDOMDocument *document,
- WebKitDOMElement *element,
- WebKitDOMElement **selection_start_marker,
- WebKitDOMElement **selection_end_marker)
-{
- WebKitDOMElement *marker;
-
- remove_selection_markers (document);
- marker = create_selection_marker (document, TRUE);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (marker), NULL);
- if (selection_start_marker)
- *selection_start_marker = marker;
-
- marker = create_selection_marker (document, FALSE);
- webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (marker), NULL);
- if (selection_end_marker)
- *selection_end_marker = marker;
-}
-
static void
refresh_spell_check (WebKitDOMDocument *document,
gboolean enable_spell_check)
@@ -333,7 +255,7 @@ refresh_spell_check (WebKitDOMDocument *document,
if (!child)
return;
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document,
WEBKIT_DOM_ELEMENT (child),
&selection_start_marker,
@@ -401,6 +323,26 @@ dom_force_spell_check (WebKitDOMDocument *document,
refresh_spell_check (document, TRUE);
}
+gboolean
+dom_node_is_citation_node (WebKitDOMNode *node)
+{
+ char *value;
+
+ if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node))
+ return FALSE;
+
+ value = webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (node), "type");
+
+ /* citation == <blockquote type='cite'> */
+ if (g_strcmp0 (value, "cite") == 0) {
+ g_free (value);
+ return TRUE;
+ } else {
+ g_free (value);
+ return FALSE;
+ }
+}
+
static gint
get_citation_level (WebKitDOMNode *node,
gboolean set_plaintext_quoted)
@@ -442,10 +384,10 @@ get_quotation_for_level (gint quote_level)
return g_string_free (output, FALSE);
}
-static void
-quote_plain_text_element_after_wrapping (WebKitDOMDocument *document,
- WebKitDOMElement *element,
- gint quote_level)
+void
+dom_quote_plain_text_element_after_wrapping (WebKitDOMDocument *document,
+ WebKitDOMElement *element,
+ gint quote_level)
{
WebKitDOMNodeList *list;
WebKitDOMNode *quoted_node;
@@ -485,26 +427,6 @@ quote_plain_text_element_after_wrapping (WebKitDOMDocument *document,
}
static gboolean
-is_citation_node (WebKitDOMNode *node)
-{
- char *value;
-
- if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node))
- return FALSE;
-
- value = webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (node), "type");
-
- /* citation == <blockquote type='cite'> */
- if (g_strcmp0 (value, "cite") == 0) {
- g_free (value);
- return TRUE;
- } else {
- g_free (value);
- return FALSE;
- }
-}
-
-static gboolean
return_pressed_in_empty_line (WebKitDOMDocument *document)
{
WebKitDOMNode *node;
@@ -532,7 +454,7 @@ return_pressed_in_empty_line (WebKitDOMDocument *document)
return FALSE;
}
-static WebKitDOMNode *
+WebKitDOMNode *
get_parent_block_node_from_child (WebKitDOMNode *node)
{
WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
@@ -553,10 +475,10 @@ get_parent_block_node_from_child (WebKitDOMNode *node)
return parent;
}
-static WebKitDOMElement *
-insert_new_line_into_citation (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension,
- const gchar *html_to_insert)
+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;
@@ -639,7 +561,7 @@ insert_new_line_into_citation (WebKitDOMDocument *document,
return NULL;
} else {
ret_val = dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT, NULL);
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT,
NULL);
if (!ret_val)
return NULL;
@@ -663,7 +585,7 @@ insert_new_line_into_citation (WebKitDOMDocument *document,
WebKitDOMNode *node;
node = webkit_dom_node_get_first_child (next_sibling);
- while (node && is_citation_node (node))
+ while (node && dom_node_is_citation_node (node))
node = webkit_dom_node_get_first_child (node);
citation_level = get_citation_level (node, FALSE);
@@ -677,7 +599,7 @@ insert_new_line_into_citation (WebKitDOMDocument *document,
dom_remove_wrapping_from_element (WEBKIT_DOM_ELEMENT (node));
node = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
document, extension, WEBKIT_DOM_ELEMENT (node), length));
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (node), citation_level);
}
@@ -691,7 +613,7 @@ insert_new_line_into_citation (WebKitDOMDocument *document,
WEBKIT_DOM_HTML_ELEMENT (paragraph),
html_to_insert,
NULL);
- add_selection_markers_into_element_end (
+ dom_add_selection_markers_into_element_end (
document, paragraph, NULL, NULL);
} else
paragraph = dom_prepare_paragraph (document, extension, TRUE);
@@ -1168,8 +1090,10 @@ emoticon_insert_span (EEmoticon *emoticon,
LoadContext *load_context,
WebKitDOMElement *span)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
EHTMLEditorWebExtension *extension = load_context->extension;
- gboolean misplaced_selection = FALSE, empty = FALSE;
+ gboolean misplaced_selection = FALSE, empty = FALSE, smiley_written;
gchar *node_text = NULL, *content;
const gchar *emoticon_start;
WebKitDOMDocument *document = load_context->document;
@@ -1178,15 +1102,54 @@ emoticon_insert_span (EEmoticon *emoticon,
WebKitDOMNode *selection_end_marker_parent;
WebKitDOMRange *range;
- if (!dom_selection_is_collapsed (document))
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+ smiley_written = e_html_editor_web_extension_get_is_smiley_written (extension);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
- dom_selection_save (document);
+ if (dom_selection_is_collapsed (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");
+ 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 (!smiley_written) {
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_SMILEY;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+ }
+ }
+ } else {
+ if (!smiley_written) {
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_SMILEY;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+ }
+ }
+
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+
+ 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 the selection was not saved, move it into the first child of body */
if (!selection_start_marker || !selection_end_marker) {
@@ -1196,11 +1159,18 @@ emoticon_insert_span (EEmoticon *emoticon,
body = webkit_dom_document_get_body (document);
child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document,
WEBKIT_DOM_ELEMENT (child),
&selection_start_marker,
&selection_end_marker);
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
}
/* Sometimes selection end marker is in body. Move it into next sibling */
@@ -1213,6 +1183,12 @@ emoticon_insert_span (EEmoticon *emoticon,
WEBKIT_DOM_NODE (selection_end_marker),
WEBKIT_DOM_NODE (selection_start_marker),
NULL);
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
}
selection_end_marker_parent = webkit_dom_node_get_parent_node (
WEBKIT_DOM_NODE (selection_end_marker));
@@ -1281,13 +1257,27 @@ emoticon_insert_span (EEmoticon *emoticon,
}
/* ​ == UNICODE_ZERO_WIDTH_SPACE */
- if (empty || !e_html_editor_web_extension_get_is_smiley_written (extension))
+ if (empty || !smiley_written)
webkit_dom_html_element_insert_adjacent_html (
WEBKIT_DOM_HTML_ELEMENT (span), "afterend", "​", NULL);
+ if (ev) {
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMNode *node;
+
+ fragment = webkit_dom_document_create_document_fragment (document);
+ node = webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (fragment),
+ webkit_dom_node_clone_node (WEBKIT_DOM_NODE (span), TRUE),
+ NULL);
+ webkit_dom_html_element_insert_adjacent_html (
+ WEBKIT_DOM_HTML_ELEMENT (node), "afterend", "​", NULL);
+ ev->data.fragment = fragment;
+ }
+
/* Remove the text that represents the text version of smiley that was
* written into the composer. */
- if (node_text && e_html_editor_web_extension_get_is_smiley_written (extension)) {
+ if (node_text && smiley_written) {
emoticon_start = g_utf8_strrchr (
node_text, -1, g_utf8_get_char (emoticon->text_face));
/* Check if the written smiley is really the one that we inserted. */
@@ -1302,6 +1292,16 @@ emoticon_insert_span (EEmoticon *emoticon,
e_html_editor_web_extension_set_is_smiley_written (extension, FALSE);
}
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
e_html_editor_web_extension_set_content_changed (extension);
@@ -1629,6 +1629,9 @@ body_keydown_event_cb (WebKitDOMElement *element,
if (key_code == HTML_KEY_CODE_CONTROL)
dom_set_links_active (
webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element)), TRUE);
+ else if (key_code == HTML_KEY_CODE_DELETE ||
+ key_code == HTML_KEY_CODE_BACKSPACE)
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, TRUE);
}
static void
@@ -1637,6 +1640,10 @@ body_keypress_event_cb (WebKitDOMElement *element,
EHTMLEditorWebExtension *extension)
{
glong key_code;
+ WebKitDOMDocument *document;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
e_html_editor_web_extension_set_return_key_pressed (extension, FALSE);
e_html_editor_web_extension_set_space_key_pressed (extension, FALSE);
@@ -1646,6 +1653,105 @@ body_keypress_event_cb (WebKitDOMElement *element,
e_html_editor_web_extension_set_return_key_pressed (extension, TRUE);
else if (key_code == HTML_KEY_CODE_SPACE)
e_html_editor_web_extension_set_space_key_pressed (extension, TRUE);
+
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (element));
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+ if (!webkit_dom_range_get_collapsed (range, NULL)) {
+ EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMDocumentFragment *fragment;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ fragment = webkit_dom_range_clone_contents (range, 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);
+ }
+}
+
+static void
+save_history_for_input (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ if (!webkit_dom_dom_selection_get_range_count (dom_selection))
+ return;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_INPUT;
+
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ dom_selection_get_coordinates (
+ document,
+ &ev->after.start.x,
+ &ev->after.start.y,
+ &ev->after.end.x,
+ &ev->after.end.y);
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+ /* We have to specialy handle Return key press */
+ if (e_html_editor_web_extension_get_return_key_pressed (extension)) {
+ WebKitDOMNode *node;
+
+ node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+ webkit_dom_node_append_child (
+ node,
+ WEBKIT_DOM_NODE (
+ webkit_dom_document_create_element (document, "br", NULL)),
+ NULL);
+ webkit_dom_node_append_child (
+ node,
+ WEBKIT_DOM_NODE (
+ dom_create_selection_marker (document, TRUE)),
+ NULL);
+ webkit_dom_node_append_child (
+ node,
+ WEBKIT_DOM_NODE (
+ dom_create_selection_marker (document, FALSE)),
+ NULL);
+
+ remove_node (webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment)));
+ } 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);
+ }
+
+ webkit_dom_dom_selection_modify (dom_selection, "move", "right", "character");
+
+ 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);
}
static void
@@ -1653,6 +1759,7 @@ body_input_event_cb (WebKitDOMElement *element,
WebKitDOMEvent *event,
EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorUndoRedoManager *manager;
gboolean html_mode;
WebKitDOMDocument *document;
WebKitDOMNode *node;
@@ -1661,12 +1768,29 @@ body_input_event_cb (WebKitDOMElement *element,
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);
+
html_mode = e_html_editor_web_extension_get_html_mode (extension);
e_html_editor_web_extension_set_content_changed (extension);
- if (e_html_editor_web_extension_get_magic_smileys_enabled (extension))
+ if (e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ e_html_editor_undo_redo_manager_set_operation_in_progress (manager, FALSE);
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ return;
+ }
+
+ if (!e_html_editor_web_extension_get_dont_save_history_in_body_input (extension))
+ save_history_for_input (document, extension);
+ else
+ dom_force_spell_check_for_current_paragraph (document, extension);
+
+ if (e_html_editor_web_extension_get_magic_smileys_enabled (extension) &&
+ !e_html_editor_web_extension_get_dont_save_history_in_body_input (extension))
dom_check_magic_smileys (document, extension);
+ e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, FALSE);
+
if (e_html_editor_web_extension_get_return_key_pressed (extension) ||
e_html_editor_web_extension_get_space_key_pressed (extension)) {
dom_check_magic_links (document, extension, FALSE);
@@ -1811,7 +1935,7 @@ body_input_event_cb (WebKitDOMElement *element,
body = webkit_dom_document_get_body (document);
child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document,
WEBKIT_DOM_ELEMENT (child),
&selection_start_marker,
@@ -1855,21 +1979,34 @@ 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);
+ dom_remove_wrapping_from_element (block);
block = dom_wrap_paragraph_length (document, extension, block, length);
webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (block), citation_level);
selection_start_marker = webkit_dom_document_query_selector (
document, "span#-x-evo-selection-start-marker", NULL);
if (!selection_start_marker)
- add_selection_markers_into_element_end (
+ dom_add_selection_markers_into_element_end (
document,
WEBKIT_DOM_ELEMENT (block),
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);
dom_force_spell_check_for_current_paragraph (document, extension);
return;
@@ -1881,7 +2018,7 @@ body_input_event_cb (WebKitDOMElement *element,
static void
remove_input_event_listener_from_body (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension)
+ EHTMLEditorWebExtension *extension)
{
if (!e_html_editor_web_extension_get_body_input_event_removed (extension)) {
webkit_dom_event_target_remove_event_listener (
@@ -1897,7 +2034,7 @@ remove_input_event_listener_from_body (WebKitDOMDocument *document,
static void
register_input_event_listener_on_body (WebKitDOMDocument *document,
- EHTMLEditorWebExtension *extension)
+ EHTMLEditorWebExtension *extension)
{
if (e_html_editor_web_extension_get_body_input_event_removed (extension)) {
webkit_dom_event_target_add_event_listener (
@@ -2046,7 +2183,7 @@ body_keyup_event_cb (WebKitDOMElement *element,
document, extension, block, length);
webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
}
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, block, level);
}
}
@@ -2115,6 +2252,8 @@ dom_quote_and_insert_text_into_selection (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *text)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
gchar *escaped_text;
WebKitDOMElement *blockquote, *element, *selection_start;
WebKitDOMNode *sibling;
@@ -2157,6 +2296,22 @@ dom_quote_and_insert_text_into_selection (WebKitDOMDocument *document,
dom_selection_save (document);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_PASTE_QUOTED;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.string.from = NULL;
+ ev->data.string.to = g_strdup (text);
+ }
+
selection_start = 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));
@@ -2187,8 +2342,20 @@ dom_quote_and_insert_text_into_selection (WebKitDOMDocument *document,
dom_restore_caret_position (document);
+ if (ev) {
+ 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);
+ }
+
dom_force_spell_check_for_current_paragraph (document, extension);
+ e_html_editor_web_extension_set_content_changed (extension);
+
g_free (escaped_text);
}
@@ -2254,7 +2421,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
webkit_dom_element_set_id (
WEBKIT_DOM_ELEMENT (block), "-x-evo-to-remove");
- paragraph = insert_new_line_into_citation (document, extension, inner_html);
+ paragraph = dom_insert_new_line_into_citation (document, extension, inner_html);
g_free (inner_html);
if (paragraph) {
@@ -2367,7 +2534,7 @@ dom_change_quoted_block_to_normal (WebKitDOMDocument *document,
block = dom_wrap_paragraph_length (document, extension, block, length);
webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
- quote_plain_text_element_after_wrapping (document, block, citation_level - 1);
+ dom_quote_plain_text_element_after_wrapping (document, block, citation_level - 1);
}
@@ -2468,8 +2635,8 @@ insert_quote_symbols (WebKitDOMHTMLElement *element,
static void
quote_node (WebKitDOMDocument *document,
- WebKitDOMNode *node,
- gint quote_level)
+ WebKitDOMNode *node,
+ gint quote_level)
{
gboolean skip_first = FALSE;
gboolean insert_newline = FALSE;
@@ -2629,9 +2796,9 @@ quote_br_node (WebKitDOMNode *node,
static void
quote_plain_text_recursive (WebKitDOMDocument *document,
- WebKitDOMNode *node,
- WebKitDOMNode *start_node,
- gint quote_level)
+ WebKitDOMNode *node,
+ WebKitDOMNode *start_node,
+ gint quote_level)
{
gboolean skip_node = FALSE;
gboolean move_next = FALSE;
@@ -2738,7 +2905,7 @@ quote_plain_text_recursive (WebKitDOMDocument *document,
}
/* If element doesn't have children, we can quote it */
- if (is_citation_node (node)) {
+ if (dom_node_is_citation_node (node)) {
/* Citation with just text inside */
quote_node (document, node, quote_level + 1);
/* Set citation as quoted */
@@ -2757,7 +2924,7 @@ quote_plain_text_recursive (WebKitDOMDocument *document,
}
goto not_br;
} else if (element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-first-br") ||
- element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-last-br")) {
+ element_has_class (WEBKIT_DOM_ELEMENT (node), "-x-evo-last-br")) {
quote_br_node (node, quote_level);
node = next_sibling;
skip_node = TRUE;
@@ -2795,7 +2962,7 @@ quote_plain_text_recursive (WebKitDOMDocument *document,
if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (parent) ||
WEBKIT_DOM_IS_HTML_PRE_ELEMENT (parent) ||
(WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent) &&
- !is_citation_node (parent))) {
+ !dom_node_is_citation_node (parent))) {
insert_quote_symbols_before_node (
document, node, quote_level, FALSE);
@@ -2818,7 +2985,7 @@ quote_plain_text_recursive (WebKitDOMDocument *document,
g_free (text_content);
}
- if (is_citation_node (prev_sibling)) {
+ if (dom_node_is_citation_node (prev_sibling)) {
insert_quote_symbols_before_node (
document, node, quote_level, FALSE);
goto next_node;
@@ -2852,7 +3019,7 @@ quote_plain_text_recursive (WebKitDOMDocument *document,
goto next_node;
with_children:
- if (is_citation_node (node)) {
+ if (dom_node_is_citation_node (node)) {
/* Go deeper and increase level */
quote_plain_text_recursive (
document, node, start_node, quote_level + 1);
@@ -2915,7 +3082,7 @@ dom_quote_plain_text_element (WebKitDOMDocument *document,
document, element_clone, element_clone, level);
/* Set citation as quoted */
- if (is_citation_node (element_clone))
+ if (dom_node_is_citation_node (element_clone))
element_add_class (
WEBKIT_DOM_ELEMENT (element_clone),
"-x-evo-plaintext-quoted");
@@ -3037,7 +3204,7 @@ dom_dequote_plain_text (WebKitDOMDocument *document)
element = WEBKIT_DOM_ELEMENT (webkit_dom_node_list_item (paragraphs, ii));
- if (is_citation_node (WEBKIT_DOM_NODE (element))) {
+ if (dom_node_is_citation_node (WEBKIT_DOM_NODE (element))) {
element_remove_class (element, "-x-evo-plaintext-quoted");
dom_remove_quoting_from_element (element);
}
@@ -3170,7 +3337,7 @@ create_and_append_new_paragraph (WebKitDOMDocument *document,
static void
append_citation_mark (WebKitDOMDocument *document,
WebKitDOMElement *parent,
- const gchar *citation_mark_text)
+ const gchar *citation_mark_text)
{
WebKitDOMText *text;
@@ -3386,12 +3553,12 @@ parse_html_into_paragraphs (WebKitDOMDocument *document,
gchar *html;
gchar *content_to_append;
- if (!paragraph) {
- if (!block || WEBKIT_DOM_IS_HTML_DIV_ELEMENT (block))
- paragraph = dom_get_paragraph_element (document, extension,
-1, 0);
- else
- paragraph = WEBKIT_DOM_ELEMENT (webkit_dom_node_clone_node
(block, FALSE));
- }
+ if (!paragraph) {
+ if (!block || WEBKIT_DOM_IS_HTML_DIV_ELEMENT (block))
+ paragraph = dom_get_paragraph_element (document, extension,
-1, 0);
+ else
+ paragraph = WEBKIT_DOM_ELEMENT (webkit_dom_node_clone_node
(block, FALSE));
+ }
html = webkit_dom_html_element_get_inner_html (
WEBKIT_DOM_HTML_ELEMENT (paragraph));
@@ -3653,7 +3820,7 @@ quote_plain_text_elements_after_wrapping_in_document (WebKitDOMDocument *documen
child = webkit_dom_node_list_item (list, ii);
citation_level = get_citation_level (child, TRUE);
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (child), citation_level);
g_object_unref (child);
}
@@ -3966,7 +4133,7 @@ dom_convert_content (WebKitDOMDocument *document,
remove_node (WEBKIT_DOM_NODE (paragraph));
child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body));
if (child)
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document, WEBKIT_DOM_ELEMENT (child), NULL, NULL);
}
@@ -4007,6 +4174,8 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
const gchar *html,
gboolean is_html)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
gboolean has_selection;
gchar *inner_html;
gint citation_level;
@@ -4025,6 +4194,24 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (current_block))
current_block = NULL;
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_PASTE;
+/* FIXME WK2
+ ev->type = HISTORY_PASTE_AS_TEXT;*/
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.string.from = NULL;
+ ev->data.string.to = g_strdup (html);
+ }
+
element = webkit_dom_document_create_element (document, "div", NULL);
if (is_html) {
gchar *inner_text;
@@ -4087,7 +4274,7 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
dom_wrap_paragraph_length (
document, extension, WEBKIT_DOM_ELEMENT (parent), length));
webkit_dom_node_normalize (parent);
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (parent), citation_level);
goto delete;
@@ -4133,12 +4320,12 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
/* Caret will be restored on the end of pasted text */
webkit_dom_node_append_child (
last_paragraph,
- WEBKIT_DOM_NODE (create_selection_marker (document, TRUE)),
+ WEBKIT_DOM_NODE (dom_create_selection_marker (document, TRUE)),
NULL);
webkit_dom_node_append_child (
last_paragraph,
- WEBKIT_DOM_NODE (create_selection_marker (document, FALSE)),
+ WEBKIT_DOM_NODE (dom_create_selection_marker (document, FALSE)),
NULL);
/* Insert the paragraph with the end of the pasted text after
@@ -4153,7 +4340,7 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
while ((child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (element)))) {
child = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
document, extension, WEBKIT_DOM_ELEMENT (child), length));
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (child), citation_level);
webkit_dom_node_insert_before (
webkit_dom_node_get_parent_node (last_paragraph),
@@ -4167,7 +4354,7 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
last_paragraph = WEBKIT_DOM_NODE (
dom_wrap_paragraph_length (
document, extension, WEBKIT_DOM_ELEMENT (last_paragraph), length));
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (last_paragraph), citation_level);
dom_remove_quoting_from_element (WEBKIT_DOM_ELEMENT (parent));
@@ -4177,7 +4364,7 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
WEBKIT_DOM_NODE (selection_start_marker));
parent = WEBKIT_DOM_NODE (dom_wrap_paragraph_length (
document, extension, WEBKIT_DOM_ELEMENT (parent), length));
- quote_plain_text_element_after_wrapping (
+ dom_quote_plain_text_element_after_wrapping (
document, WEBKIT_DOM_ELEMENT (parent), citation_level);
/* If the pasted text begun or ended with a new line we have to
@@ -4202,11 +4389,21 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
webkit_dom_element_remove_attribute (br, "class");
}
delete:
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
/* Remove the text that was meant to be replaced by the pasted text */
if (has_selection)
dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
g_object_unref (element);
goto out;
@@ -4218,13 +4415,13 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
inner_html = webkit_dom_html_element_get_inner_html (
WEBKIT_DOM_HTML_ELEMENT (element));
dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, inner_html);
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, inner_html);
g_free (inner_html);
inner_html = webkit_dom_html_element_get_inner_text (
WEBKIT_DOM_HTML_ELEMENT (element));
if (g_str_has_suffix (inner_html, " "))
- dom_exec_command (document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, " ");
+ dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, " ");
g_free (inner_html);
@@ -4357,6 +4554,16 @@ dom_convert_and_insert_html_into_selection (WebKitDOMDocument *document,
NULL);
}
+ if (ev) {
+ 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);
+ }
+
dom_selection_restore (document);
out:
dom_force_spell_check (document, extension);
@@ -5238,7 +5445,7 @@ process_elements (EHTMLEditorWebExtension *extension,
if (webkit_dom_node_get_next_sibling (parent)) {
parent = webkit_dom_node_get_parent_node (parent);
- if (is_citation_node (parent))
+ if (dom_node_is_citation_node (parent))
g_string_append (buffer, changing_mode ? "<br>" :
"\n");
}
}
@@ -5569,7 +5776,7 @@ convert_element_from_html_to_plain_text (WebKitDOMDocument *document,
restore = input_start ? TRUE : FALSE;
if (input_start)
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document, WEBKIT_DOM_ELEMENT (input_start), NULL, NULL);
from = WEBKIT_DOM_NODE (main_blockquote);
} else {
@@ -5638,7 +5845,7 @@ convert_element_from_html_to_plain_text (WebKitDOMDocument *document,
"<br>",
NULL);
}
- add_selection_markers_into_element_start (
+ dom_add_selection_markers_into_element_start (
document, WEBKIT_DOM_ELEMENT (first_child), NULL, NULL);
}
}
@@ -6062,7 +6269,7 @@ dom_process_content_after_load (WebKitDOMDocument *document,
/* Don't use CSS when possible to preserve compatibility with older
* versions of Evolution or other MUAs */
dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_STYLE_WITH_CSS, "false");
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_STYLE_WITH_CSS, "false");
body = webkit_dom_document_get_body (document);
@@ -6234,11 +6441,30 @@ dom_insert_html (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *html_text)
{
+ EHTMLEditorHistoryEvent *ev = NULL;
+ EHTMLEditorUndoRedoManager *manager;
+
g_return_if_fail (html_text != NULL);
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ if (!e_html_editor_undo_redo_manager_is_operation_in_progress (manager)) {
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_INSERT_HTML;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->data.string.from = NULL;
+ ev->data.string.to = g_strdup (html_text);
+ }
+
if (e_html_editor_web_extension_get_html_mode (extension)) {
dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html_text);
+ document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html_text);
if (strstr (html_text, "id=\"-x-evo-selection-start-marker\""))
dom_selection_restore (document);
dom_check_magic_links (document, extension, FALSE);
@@ -6246,6 +6472,17 @@ dom_insert_html (WebKitDOMDocument *document,
dom_scroll_to_caret (document);
} else
dom_convert_and_insert_html_into_selection (document, extension, html_text, TRUE);
+
+ if (ev) {
+ 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);
+ }
}
static gboolean
@@ -6364,6 +6601,153 @@ fix_structure_after_delete_before_quoted_content (WebKitDOMDocument *document)
return FALSE;
}
+static void
+save_history_for_delete_or_backspace (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ gboolean delete_key)
+{
+ EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ if (!webkit_dom_dom_selection_get_range_count (dom_selection))
+ return;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
+
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, &ev->before.end.y);
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+ if (webkit_dom_range_get_collapsed (range, NULL)) {
+ WebKitDOMNode *node = webkit_dom_range_get_end_container (range, NULL);
+
+ if (delete_key && !webkit_dom_node_get_next_sibling (node)) {
+ g_free (ev);
+ return;
+ }
+
+ if (delete_key)
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "right", "character");
+ else
+ webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+
+ if (!webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment))) {
+ g_free (ev);
+ return;
+ }
+
+ if (delete_key) {
+ webkit_dom_dom_selection_collapse_to_start (dom_selection, NULL);
+
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x,
&ev->after.end.y);
+ } else {
+ dom_selection_get_coordinates (
+ document, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x,
&ev->after.end.y);
+
+ webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
+ }
+
+ if (!delete_key) {
+ ev->after.end.x = ev->after.start.x;
+ ev->after.end.y = ev->after.start.y;
+ }
+
+ 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);
+ } 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);
+ }
+ } else {
+ ev->after.start.x = ev->before.start.x;
+ ev->after.start.y = ev->before.start.y;
+ ev->after.end.x = ev->before.end.x;
+ ev->after.end.y = ev->before.end.y;
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+ }
+
+ 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);
+}
+
+static gboolean
+split_citation (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMElement *element;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_CITATION_SPLIT;
+
+ dom_selection_get_coordinates (
+ document, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, &ev->before.end.y);
+
+ if (!dom_selection_is_collapsed (document)) {
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMRange *range;
+
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ if (!webkit_dom_dom_selection_get_range_count (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
+ ev->data.fragment = NULL;
+
+ 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);
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+
+ return element != NULL;
+}
+
static gboolean
selection_is_in_table (WebKitDOMDocument *document,
gboolean *first_cell,
@@ -6562,18 +6946,77 @@ is_return_key (guint key_val)
(key_val == GDK_KEY_KP_Enter));
}
+static gboolean
+insert_tabulator (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ gboolean success;
+ EHTMLEditorHistoryEvent *ev;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_INPUT;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ success = dom_exec_command (document, extension, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, "\t");
+
+ if (success) {
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMElement *element;
+ WebKitDOMDocumentFragment *fragment;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->after.start.x,
+ &ev->after.start.y,
+ &ev->after.end.x,
+ &ev->after.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;
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+ }
+
+ return success;
+}
+
gboolean
dom_process_on_key_press (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
guint key_val)
{
+ 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 dom_exec_command (
- document, E_HTML_EDITOR_VIEW_COMMAND_INSERT_TEXT, "\t");
+ return insert_tabulator (document, extension);
else
return FALSE;
}
@@ -6598,7 +7041,7 @@ dom_process_on_key_press (WebKitDOMDocument *document,
WEBKIT_DOM_NODE (webkit_dom_document_create_element (
document, "br", NULL)),
NULL);
- add_selection_markers_into_element_start (
+ 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),
@@ -6615,7 +7058,7 @@ dom_process_on_key_press (WebKitDOMDocument *document,
* the special command to do it. */
if (dom_selection_is_citation (document)) {
remove_input_event_listener_from_body (document, extension);
- return (insert_new_line_into_citation (document, extension, "")) ? TRUE : FALSE;
+ return split_citation (document, extension);
}
/* When the return is pressed in a H1-6 element, WebKit doesn't
@@ -6675,6 +7118,7 @@ dom_process_on_key_press (WebKitDOMDocument *document,
if (key_val == GDK_KEY_Delete || key_val == GDK_KEY_BackSpace) {
gboolean html_mode;
+ save_history_for_delete_or_backspace (document, extension, key_val == GDK_KEY_Delete);
html_mode = e_html_editor_web_extension_get_html_mode (extension);
if (key_val == GDK_KEY_BackSpace && !html_mode) {
if (delete_character_from_quoted_line_start (document))
@@ -6717,6 +7161,7 @@ void
dom_process_content_after_mode_change (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
{
+ EHTMLEditorUndoRedoManager *manager;
gboolean html_mode;
WebKitDOMElement *blockquote;
@@ -6762,6 +7207,9 @@ dom_process_content_after_mode_change (WebKitDOMDocument *document,
g_free (plain);
}
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ e_html_editor_undo_redo_manager_clean_history (manager);
}
gint
diff --git a/web-extensions/e-html-editor-view-dom-functions.h
b/web-extensions/e-html-editor-view-dom-functions.h
index 1c44069..d0e4960 100644
--- a/web-extensions/e-html-editor-view-dom-functions.h
+++ b/web-extensions/e-html-editor-view-dom-functions.h
@@ -24,10 +24,12 @@
#include "e-html-editor-web-extension.h"
#include <e-util/e-util-enums.h>
+#include <e-util/e-emoticon.h>
G_BEGIN_DECLS
gboolean dom_exec_command (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
EHTMLEditorViewCommand command,
const gchar *value);
@@ -54,6 +56,13 @@ void dom_check_magic_links (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
gboolean include_space_by_user);
+void dom_insert_smiley (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EEmoticon *emoticon);
+
+void dom_check_magic_smileys (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension);
+
void dom_convert_content (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
const gchar *preferred_text);
@@ -64,6 +73,22 @@ void dom_convert_and_insert_html_into_selection
const gchar *html,
gboolean is_html);
+gboolean dom_node_is_citation_node (WebKitDOMNode *node);
+
+void dom_quote_plain_text_element_after_wrapping
+ (WebKitDOMDocument *document,
+ WebKitDOMElement *element,
+ gint quote_level);
+
+WebKitDOMNode * get_parent_block_node_from_child
+ (WebKitDOMNode *node);
+
+WebKitDOMElement *
+ dom_insert_new_line_into_citation
+ (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ const gchar *html_to_insert);
+
WebKitDOMElement *
dom_quote_plain_text_element (WebKitDOMDocument *document,
WebKitDOMElement *element);
diff --git a/web-extensions/e-html-editor-web-extension.c b/web-extensions/e-html-editor-web-extension.c
index ec50281..e5c065c 100644
--- a/web-extensions/e-html-editor-web-extension.c
+++ b/web-extensions/e-html-editor-web-extension.c
@@ -1,5 +1,5 @@
/*
- * e-html-editor-web-extension.h
+ * e-html-editor-web-extension.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -39,6 +39,7 @@
#include "e-html-editor-hrule-dialog-dom-functions.h"
#include "e-html-editor-image-dialog-dom-functions.h"
#include "e-html-editor-link-dialog-dom-functions.h"
+#include "e-html-editor-page-dialog-dom-functions.h"
#include "e-html-editor-selection-dom-functions.h"
#include "e-html-editor-spell-check-dialog-dom-functions.h"
#include "e-html-editor-table-dialog-dom-functions.h"
@@ -91,11 +92,14 @@ struct _EHTMLEditorWebExtensionPrivate {
gboolean is_message_from_edit_as_new;
gboolean is_message_from_selection;
gboolean remove_initial_input_line;
+ gboolean dont_save_history_in_body_input;
GHashTable *inline_images;
WebKitDOMNode *node_under_mouse_click;
guint node_under_mouse_click_flags;
+
+ EHTMLEditorUndoRedoManager *undo_redo_manager;
};
static CamelDataCache *emd_global_http_cache = NULL;
@@ -199,6 +203,9 @@ static const char introspection_xml[] =
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='element_id' direction='in'/>"
" </method>"
+" <method name='EHTMLEditorCellDialogSaveHistoryOnExit'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
" <method name='EHTMLEditorCellDialogSetElementVAlign'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='value' direction='in'/>"
@@ -246,6 +253,9 @@ static const char introspection_xml[] =
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='b' name='created_new_hr' direction='out'/>"
" </method>"
+" <method name='EHTMLEditorHRuleDialogSaveHistoryOnExit'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
" <method name='HRElementSetNoShade'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='element_id' direction='in'/>"
@@ -259,6 +269,12 @@ static const char introspection_xml[] =
"<!-- ********************************************************* -->"
"<!-- Functions that are used in EHTMLEditorImageDialog -->"
"<!-- ********************************************************* -->"
+" <method name='EHTMLEditorImageDialogMarkImage'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
+" <method name='EHTMLEditorImageDialogSaveHistoryOnExit'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
" <method name='EHTMLEditorImageDialogSetElementUrl'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='value' direction='in'/>"
@@ -326,6 +342,15 @@ static const char introspection_xml[] =
" <arg type='s' name='inner_text' direction='in'/>"
" </method>"
"<!-- ********************************************************* -->"
+"<!-- Functions that are used in EHTMLEditorPageDialog -->"
+"<!-- ********************************************************* -->"
+" <method name='EHTMLEditorPageDialogSaveHistory'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
+" <method name='EHTMLEditorPageDialogSaveHistoryOnExit'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
+"<!-- ********************************************************* -->"
"<!-- Functions that are used in EHTMLEditorSpellCheckDialog -->"
"<!-- ********************************************************* -->"
" <method name='EHTMLEditorSpellCheckDialogNext'>"
@@ -361,6 +386,12 @@ static const char introspection_xml[] =
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='b' name='created_new_table' direction='out'/>"
" </method>"
+" <method name='EHTMLEditorTableDialogSaveHistoryOnExit'>"
+" <arg type='t' name='page_id' direction='in'/>"
+" </method>"
+"<!-- ********************************************************* -->"
+"<!-- Functions that are used in EHTMLEditorActions -->"
+"<!-- ********************************************************* -->"
" <method name='TableCellElementGetNoWrap'>"
" <arg type='t' name='page_id' direction='in'/>"
" <arg type='s' name='element_id' direction='in'/>"
@@ -764,7 +795,19 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_cell_dialog_mark_current_cell_element (document, element_id);
+ e_html_editor_cell_dialog_mark_current_cell_element (document, extension, element_id);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ } else if (g_strcmp0 (method_name, "EHTMLEditorCellDialogSaveHistoryOnExit") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_cell_dialog_save_history_on_exit (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorCellDialogSetElementVAlign") == 0) {
@@ -903,6 +946,18 @@ handle_method_call (GDBusConnection *connection,
g_dbus_method_invocation_return_value (
invocation, g_variant_new_boolean (created_new_hr));
+ } else if (g_strcmp0 (method_name, "EHTMLEditorHRuleDialogSaveHistoryOnExit") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_hrule_dialog_save_history_on_exit (document, extension);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "HRElementSetNoShade") == 0) {
gboolean value = FALSE;
const gchar *element_id;
@@ -944,6 +999,31 @@ handle_method_call (GDBusConnection *connection,
g_dbus_method_invocation_return_value (
invocation, g_variant_new_boolean (value));
+ } else if (g_strcmp0 (method_name, "EHTMLEditorImageDialogMarkImage") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_image_dialog_mark_image (
+ document, extension, extension->priv->node_under_mouse_click);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ } else if (g_strcmp0 (method_name, "EHTMLEditorImageDialogSaveHistoryOnExit") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_image_dialog_save_history_on_exit (document, extension);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorImageDialogSetElementUrl") == 0) {
const gchar *value;
@@ -1191,7 +1271,31 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_link_dialog_ok (document, url, inner_text);
+ e_html_editor_link_dialog_ok (document, extension, url, inner_text);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ } else if (g_strcmp0 (method_name, "EHTMLEditorPageDialogSaveHistory") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_page_dialog_save_history (document, extension);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ } else if (g_strcmp0 (method_name, "EHTMLEditorPageDialogSaveHistoryOnExit") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_page_dialog_save_history_on_exit (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorSpellCheckDialogNext") == 0) {
@@ -1301,6 +1405,18 @@ handle_method_call (GDBusConnection *connection,
g_dbus_method_invocation_return_value (
invocation, g_variant_new_boolean (created_new_table));
+ } else if (g_strcmp0 (method_name, "EHTMLEditorTableDialogSaveHistoryOnExit") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_table_dialog_save_history_on_exit (document, extension);
+
+ g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogDeleteCellContents") == 0) {
g_variant_get (parameters, "(t)", &page_id);
@@ -1310,7 +1426,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_delete_cell_contents (document);
+ e_html_editor_dialog_delete_cell_contents (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogDeleteColumn") == 0) {
@@ -1322,7 +1438,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_delete_column (document);
+ e_html_editor_dialog_delete_column (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogDeleteRow") == 0) {
@@ -1334,7 +1450,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_delete_row (document);
+ e_html_editor_dialog_delete_row (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogDeleteTable") == 0) {
@@ -1346,7 +1462,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_delete_table (document);
+ e_html_editor_dialog_delete_table (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogDeleteTable") == 0) {
@@ -1358,7 +1474,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_delete_cell_contents (document);
+ e_html_editor_dialog_delete_cell_contents (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogInsertColumnAfter") == 0) {
@@ -1370,7 +1486,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_insert_column_after (document);
+ e_html_editor_dialog_insert_column_after (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogInsertColumnBefore") == 0) {
@@ -1382,7 +1498,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_insert_column_before (document);
+ e_html_editor_dialog_insert_column_before (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogInsertRowAbove") == 0) {
@@ -1394,7 +1510,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_insert_row_above (document);
+ e_html_editor_dialog_insert_row_above (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogInsertRowBelow") == 0) {
@@ -1406,7 +1522,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- e_html_editor_dialog_insert_row_below (document);
+ e_html_editor_dialog_insert_row_below (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "EHTMLEditorDialogDOMUnlink") == 0) {
@@ -1418,7 +1534,7 @@ handle_method_call (GDBusConnection *connection,
return;
document = webkit_web_page_get_dom_document (web_page);
- dom_unlink (document);
+ dom_selection_unlink (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "TableCellElementGetNoWrap") == 0) {
@@ -1809,6 +1925,17 @@ handle_method_call (GDBusConnection *connection,
document = webkit_web_page_get_dom_document (web_page);
dom_selection_unindent (document, extension);
g_dbus_method_invocation_return_value (invocation, NULL);
+ } else if (g_strcmp0 (method_name, "DOMSelectionWrap") == 0) {
+ g_variant_get (parameters, "(t)", &page_id);
+
+ web_page = get_webkit_web_page_or_return_dbus_error (
+ invocation, web_extension, page_id);
+ if (!web_page)
+ return;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ dom_selection_wrap (document, extension);
+ g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "DOMRemoveSignatures") == 0) {
gboolean top_signature;
gchar *active_signature;
@@ -2343,6 +2470,12 @@ e_html_editor_web_extension_dispose (GObject *object)
extension->priv->text = NULL;
}
+ if (extension->priv->undo_redo_manager != NULL) {
+ g_object_unref (extension->priv->undo_redo_manager);
+ extension->priv->undo_redo_manager = NULL;
+ extension->priv->text = NULL;
+ }
+
g_clear_object (&extension->priv->wk_extension);
g_hash_table_remove_all (extension->priv->inline_images);
@@ -2412,9 +2545,15 @@ e_html_editor_web_extension_init (EHTMLEditorWebExtension *extension)
extension->priv->is_from_new_message = FALSE;
extension->priv->is_message_from_selection = FALSE;
extension->priv->remove_initial_input_line = FALSE;
+ extension->priv->dont_save_history_in_body_input = FALSE;
extension->priv->node_under_mouse_click = NULL;
+ extension->priv->undo_redo_manager = g_object_new (
+ E_TYPE_HTML_EDITOR_UNDO_REDO_MANAGER,
+ "html-editor-web-extension", extension->priv->undo_redo_manager,
+ NULL);
+
extension->priv->inline_images = g_hash_table_new_full (
g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
@@ -2544,6 +2683,9 @@ web_page_document_loaded_cb (WebKitWebPage *web_page,
document = webkit_web_page_get_dom_document (web_page);
+ e_html_editor_undo_redo_manager_set_document (
+ web_extension->priv->undo_redo_manager, document);
+
dom_process_content_after_load (document, web_extension);
}
@@ -2809,6 +2951,12 @@ e_html_editor_web_extension_set_space_key_pressed (EHTMLEditorWebExtension *exte
}
gboolean
+e_html_editor_web_extension_get_magic_links_enabled (EHTMLEditorWebExtension *extension)
+{
+ return extension->priv->magic_links;
+}
+
+gboolean
e_html_editor_web_extension_get_magic_smileys_enabled (EHTMLEditorWebExtension *extension)
{
return extension->priv->magic_smileys;
@@ -2908,3 +3056,23 @@ e_html_editor_web_extension_set_is_smiley_written (EHTMLEditorWebExtension *exte
extension->priv->smiley_written = value;
}
+gboolean
+e_html_editor_web_extension_get_dont_save_history_in_body_input (EHTMLEditorWebExtension *extension)
+{
+ return extension->priv->dont_save_history_in_body_input;
+}
+
+void
+e_html_editor_web_extension_set_dont_save_history_in_body_input (EHTMLEditorWebExtension *extension,
+ gboolean value)
+{
+ extension->priv->dont_save_history_in_body_input = value;
+}
+
+EHTMLEditorUndoRedoManager *
+e_html_editor_web_extension_get_undo_redo_manager (EHTMLEditorWebExtension *extension)
+{
+ g_return_val_if_fail (E_IS_HTML_EDITOR_WEB_EXTENSION (extension), NULL);
+
+ return extension->priv->undo_redo_manager;
+}
diff --git a/web-extensions/e-html-editor-web-extension.h b/web-extensions/e-html-editor-web-extension.h
index ff64fa0..45a6d6f 100644
--- a/web-extensions/e-html-editor-web-extension.h
+++ b/web-extensions/e-html-editor-web-extension.h
@@ -23,6 +23,8 @@
#include "e-html-editor-web-extension-names.h"
+#include "e-html-editor-undo-redo-manager.h"
+
#include <e-util/e-util-enums.h>
#include <webkit2/webkit-web-extension.h>
#include <glib-object.h>
@@ -48,6 +50,8 @@
G_BEGIN_DECLS
+struct _EHTMLEditorUndoRedoManager;
+
typedef struct _EHTMLEditorWebExtension EHTMLEditorWebExtension;
typedef struct _EHTMLEditorWebExtensionClass EHTMLEditorWebExtensionClass;
typedef struct _EHTMLEditorWebExtensionPrivate EHTMLEditorWebExtensionPrivate;
@@ -135,6 +139,9 @@ void e_html_editor_web_extension_set_space_key_pressed
(EHTMLEditorWebExtension *extension,
gboolean value);
+gboolean e_html_editor_web_extension_get_magic_links_enabled
+ (EHTMLEditorWebExtension *extension);
+
gboolean e_html_editor_web_extension_get_magic_smileys_enabled
(EHTMLEditorWebExtension *extension);
@@ -181,6 +188,16 @@ gboolean e_html_editor_web_extension_get_is_smiley_written
void e_html_editor_web_extension_set_is_smiley_written
(EHTMLEditorWebExtension *extension,
- gboolean value);
+ gboolean value);
+gboolean e_html_editor_web_extension_get_dont_save_history_in_body_input
+ (EHTMLEditorWebExtension *extension);
+
+void e_html_editor_web_extension_set_dont_save_history_in_body_input
+ (EHTMLEditorWebExtension *extension,
+ gboolean value);
+
+struct _EHTMLEditorUndoRedoManager *
+ e_html_editor_web_extension_get_undo_redo_manager
+ (EHTMLEditorWebExtension *extension);
#endif /* E_HTML_EDITOR_WEB_EXTENSION_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]