[evolution] Bug 750299 - [regression] Hyperlinks create duplicate text, then deleting the duplicate makes the hy



commit 18c5e81b54be3f13abb2b418661ab7e6170ccee9
Author: Tomas Popela <tpopela redhat com>
Date:   Wed Jun 10 09:23:39 2015 +0200

    Bug 750299 - [regression] Hyperlinks create duplicate text, then deleting the duplicate makes the 
hyperlink blow up to the whole line
    
    Fix the EHTMLEditorLinkDialog as between showing the dialog and clicking the "OK"
    button the selection in composer was lost that later lead to creating the duplicate
    text. Also save the link under the cursor straight in the EHTMLEditor and then pass
    it to the dialog to avoid looking for it on various places again.
    
    Also it showed up that I completely forgot about this dialog when implementing the
    undo/redo in the composer, so previously doing so after working with dialog would
    lead to undefined behavior.
    
    Replace the webkit_dom_html_anchor_element_get_href with webkit_dom_element_get_attribute
    as the first one would return just "http:/" when we would previously set the "http://";
    as a value of the href attribute.
    
    Also hide the "Insert link" action from context menu if the context menu was
    activated on the link (for editing purposes there is still the
    Properties->Link.. action).

 e-util/e-html-editor-actions.c     |    7 +-
 e-util/e-html-editor-actions.h     |    2 +
 e-util/e-html-editor-link-dialog.c |  316 +++++++++++++++++++++---------------
 e-util/e-html-editor-link-dialog.h |    2 +
 e-util/e-html-editor-view.c        |   74 +++++++++
 e-util/e-html-editor-view.h        |    1 +
 e-util/e-html-editor.c             |    5 +
 7 files changed, 278 insertions(+), 129 deletions(-)
---
diff --git a/e-util/e-html-editor-actions.c b/e-util/e-html-editor-actions.c
index 0fececc..0e4cdf2 100644
--- a/e-util/e-html-editor-actions.c
+++ b/e-util/e-html-editor-actions.c
@@ -671,7 +671,8 @@ action_insert_link_cb (GtkAction *action,
                editor->priv->link_dialog =
                        e_html_editor_link_dialog_new (editor);
 
-       gtk_window_present (GTK_WINDOW (editor->priv->link_dialog));
+       e_html_editor_link_dialog_show (
+               E_HTML_EDITOR_LINK_DIALOG (editor->priv->link_dialog), NULL);
 }
 
 static void
@@ -908,7 +909,9 @@ action_properties_link_cb (GtkAction *action,
                        e_html_editor_link_dialog_new (editor);
        }
 
-       gtk_window_present (GTK_WINDOW (editor->priv->link_dialog));
+       e_html_editor_link_dialog_show (
+               E_HTML_EDITOR_LINK_DIALOG (editor->priv->link_dialog),
+               editor->priv->current_node);
 }
 
 static void
diff --git a/e-util/e-html-editor-actions.h b/e-util/e-html-editor-actions.h
index d2e80df..bce0f29 100644
--- a/e-util/e-html-editor-actions.h
+++ b/e-util/e-html-editor-actions.h
@@ -41,6 +41,8 @@
        E_HTML_EDITOR_ACTION ((editor), "context-insert-column-after")
 #define E_HTML_EDITOR_ACTION_CONTEXT_INSERT_COLUMN_BEFORE(editor) \
        E_HTML_EDITOR_ACTION ((editor), "context-insert-column-before")
+#define E_HTML_EDITOR_ACTION_CONTEXT_INSERT_LINK(editor) \
+       E_HTML_EDITOR_ACTION ((editor), "context-insert-link")
 #define E_HTML_EDITOR_ACTION_CONTEXT_INSERT_ROW_ABOVE(editor) \
        E_HTML_EDITOR_ACTION ((editor), "context-insert-row-above")
 #define E_HTML_EDITOR_ACTION_CONTEXT_INSERT_ROW_BELOW(editor) \
diff --git a/e-util/e-html-editor-link-dialog.c b/e-util/e-html-editor-link-dialog.c
index 2415868..78bc97d 100644
--- a/e-util/e-html-editor-link-dialog.c
+++ b/e-util/e-html-editor-link-dialog.c
@@ -26,6 +26,7 @@
 #include "e-html-editor-selection.h"
 #include "e-html-editor-utils.h"
 #include "e-html-editor-view.h"
+#include "e-web-view.h"
 
 #include <glib/gi18n-lib.h>
 
@@ -47,6 +48,11 @@ struct _EHTMLEditorLinkDialogPrivate {
        GtkWidget *ok_button;
 
        gboolean label_autofill;
+       gboolean unlinking;
+
+       WebKitDOMElement *link_element;
+
+       EHTMLEditorViewHistoryEvent *history_event;
 };
 
 static void
@@ -95,6 +101,7 @@ html_editor_link_dialog_remove_link (EHTMLEditorLinkDialog *dialog)
        view = e_html_editor_get_view (editor);
        selection = e_html_editor_view_get_selection (view);
        e_html_editor_selection_unlink (selection);
+       dialog->priv->unlinking = TRUE;
 
        gtk_widget_hide (GTK_WIDGET (dialog));
 }
@@ -103,105 +110,109 @@ static void
 html_editor_link_dialog_ok (EHTMLEditorLinkDialog *dialog)
 {
        EHTMLEditor *editor;
-       EHTMLEditorView *view;
        EHTMLEditorSelection *selection;
+       EHTMLEditorView *view;
        WebKitDOMDocument *document;
-       WebKitDOMDOMWindow *dom_window;
-       WebKitDOMDOMSelection *dom_selection;
-       WebKitDOMRange *range;
-       WebKitDOMElement *link;
 
        editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
        view = e_html_editor_get_view (editor);
        selection = e_html_editor_view_get_selection (view);
-
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
-       dom_window = webkit_dom_document_get_default_view (document);
-       dom_selection = webkit_dom_dom_window_get_selection (dom_window);
-       g_object_unref (dom_window);
-
-       if (!dom_selection ||
-           (webkit_dom_dom_selection_get_range_count (dom_selection) == 0)) {
-               gtk_widget_hide (GTK_WIDGET (dialog));
-               g_object_unref (dom_selection);
-               return;
-       }
 
-       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-       link = e_html_editor_dom_node_find_parent_element (
-                       webkit_dom_range_get_start_container (range, NULL), "A");
-       if (!link) {
-               if ((webkit_dom_range_get_start_container (range, NULL) !=
-                       webkit_dom_range_get_end_container (range, NULL)) ||
-                   (webkit_dom_range_get_start_offset (range, NULL) !=
-                       webkit_dom_range_get_end_offset (range, NULL))) {
-
-                       WebKitDOMDocumentFragment *fragment;
-                       fragment = webkit_dom_range_extract_contents (range, NULL);
-                       link = e_html_editor_dom_node_find_child_element (
-                               WEBKIT_DOM_NODE (fragment), "A");
-                       webkit_dom_range_insert_node (
-                               range, WEBKIT_DOM_NODE (fragment), NULL);
-
-                       webkit_dom_dom_selection_set_base_and_extent (
-                               dom_selection,
-                               webkit_dom_range_get_start_container (range, NULL),
-                               webkit_dom_range_get_start_offset (range, NULL),
-                               webkit_dom_range_get_end_container (range, NULL),
-                               webkit_dom_range_get_end_offset (range, NULL),
-                               NULL);
-               } else {
-                       WebKitDOMNode *node;
-
-                       /* get element that was clicked on */
-                       node = webkit_dom_range_get_common_ancestor_container (range, NULL);
-                       if (node && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
-                               link = e_html_editor_dom_node_find_parent_element (node, "A");
-                               if (link && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link))
-                                       link = NULL;
-                       } else
-                               link = WEBKIT_DOM_ELEMENT (node);
-               }
-       }
+       if (dialog->priv->link_element) {
+               WebKitDOMElement *element;
 
-       if (link) {
                webkit_dom_html_anchor_element_set_href (
-                       WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link),
+                       WEBKIT_DOM_HTML_ANCHOR_ELEMENT (dialog->priv->link_element),
                        gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit)));
                webkit_dom_html_element_set_inner_html (
-                       WEBKIT_DOM_HTML_ELEMENT (link),
+                       WEBKIT_DOM_HTML_ELEMENT (dialog->priv->link_element),
                        gtk_entry_get_text (GTK_ENTRY (dialog->priv->label_edit)),
                        NULL);
-       } else {
-               gchar *text;
 
-               /* Check whether a text is selected or not */
-               text = webkit_dom_range_get_text (range);
-               if (text && *text) {
-                       e_html_editor_selection_create_link (
-                               selection,
-                               gtk_entry_get_text (
-                                       GTK_ENTRY (dialog->priv->url_edit)));
-               } else {
-                       gchar *html = g_strdup_printf (
-                               "<a href=\"%s\">%s</a>",
-                               gtk_entry_get_text (
-                                       GTK_ENTRY (dialog->priv->url_edit)),
-                               gtk_entry_get_text (
-                                       GTK_ENTRY (dialog->priv->label_edit)));
+               element = webkit_dom_document_create_element (document, "SPAN", NULL);
+               webkit_dom_element_set_id (element, "-x-evo-selection-end-marker");
+               webkit_dom_node_insert_before (
+                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (dialog->priv->link_element)),
+                       WEBKIT_DOM_NODE (element),
+                       webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (dialog->priv->link_element)),
+                       NULL);
 
-                       e_html_editor_view_exec_command (
-                               view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html);
+               element = webkit_dom_document_create_element (document, "SPAN", NULL);
+               webkit_dom_element_set_id (element, "-x-evo-selection-start-marker");
+               webkit_dom_node_insert_before (
+                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (dialog->priv->link_element)),
+                       WEBKIT_DOM_NODE (element),
+                       webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (dialog->priv->link_element)),
+                       NULL);
 
-                       g_free (html);
+               e_html_editor_selection_restore (selection);
+       } else {
+               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);
+               g_object_unref (dom_window);
+
+               e_html_editor_selection_restore (selection);
+               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+               if (webkit_dom_range_get_collapsed (range, NULL)) {
+                       WebKitDOMElement *selection_marker;
+                       WebKitDOMElement *anchor;
+
+                       e_html_editor_selection_save (selection);
+                       selection_marker = webkit_dom_document_get_element_by_id (
+                               document, "-x-evo-selection-start-marker");
+                       anchor = webkit_dom_document_create_element (document, "A", NULL);
+                       webkit_dom_element_set_attribute (
+                               anchor, "href", gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit)), 
NULL);
+                       webkit_dom_html_element_set_inner_text (
+                               WEBKIT_DOM_HTML_ELEMENT (anchor),
+                               gtk_entry_get_text (
+                                       GTK_ENTRY (dialog->priv->label_edit)),
+                               NULL);
+                       dialog->priv->link_element = anchor;
 
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_parent_node (
+                                       WEBKIT_DOM_NODE (selection_marker)),
+                               WEBKIT_DOM_NODE (anchor),
+                               WEBKIT_DOM_NODE (selection_marker),
+                               NULL);
+                       e_html_editor_selection_restore (selection);
+               } else {
+                       gchar *text;
+
+                       text = webkit_dom_range_get_text (range);
+                       if (text && *text) {
+                               WebKitDOMElement *selection_marker;
+                               WebKitDOMNode *parent;
+
+                               e_html_editor_selection_create_link (
+                                       selection, gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit)));
+
+                               dialog->priv->history_event->data.dom.from =
+                                       WEBKIT_DOM_NODE (webkit_dom_document_create_text_node (document, 
text));
+
+                               e_html_editor_selection_save (selection);
+                               selection_marker = webkit_dom_document_get_element_by_id (
+                                       document, "-x-evo-selection-start-marker");
+                               parent = webkit_dom_node_get_parent_node (
+                                       WEBKIT_DOM_NODE (selection_marker));
+                               if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent))
+                                       dialog->priv->link_element = WEBKIT_DOM_ELEMENT (parent);
+                               e_html_editor_selection_restore (selection);
+                               webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
+                       }
+                       g_free (text);
                }
 
-               g_free (text);
+               g_object_unref (range);
+               g_object_unref (dom_selection);
        }
 
-       g_object_unref (range);
-       g_object_unref (dom_selection);
        gtk_widget_hide (GTK_WIDGET (dialog));
 }
 
@@ -223,22 +234,14 @@ static void
 html_editor_link_dialog_show (GtkWidget *widget)
 {
        EHTMLEditor *editor;
-       EHTMLEditorView *view;
        EHTMLEditorLinkDialog *dialog;
-       WebKitDOMDocument *document;
-       WebKitDOMDOMWindow *dom_window;
-       WebKitDOMDOMSelection *dom_selection;
-       WebKitDOMRange *range;
-       WebKitDOMElement *link;
+       EHTMLEditorSelection *selection;
+       EHTMLEditorView *view;
 
        dialog = E_HTML_EDITOR_LINK_DIALOG (widget);
        editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
        view = e_html_editor_get_view (editor);
-
-       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
-       dom_window = webkit_dom_document_get_default_view (document);
-       dom_selection = webkit_dom_dom_window_get_selection (dom_window);
-       g_object_unref (dom_window);
+       selection = e_html_editor_view_get_selection (view);
 
        /* Reset to default values */
        gtk_entry_set_text (GTK_ENTRY (dialog->priv->url_edit), "http://";);
@@ -246,47 +249,30 @@ html_editor_link_dialog_show (GtkWidget *widget)
        gtk_widget_set_sensitive (dialog->priv->label_edit, TRUE);
        gtk_widget_set_sensitive (dialog->priv->remove_link_button, TRUE);
        dialog->priv->label_autofill = TRUE;
-
-       /* No selection at all */
-       if (!dom_selection ||
-           webkit_dom_dom_selection_get_range_count (dom_selection) < 1) {
-               gtk_widget_set_sensitive (dialog->priv->remove_link_button, FALSE);
-               goto chainup;
+       dialog->priv->unlinking = FALSE;
+
+       if (!e_html_editor_view_is_undo_redo_in_progress (view)) {
+               EHTMLEditorViewHistoryEvent *ev;
+
+               ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+               ev->type = HISTORY_LINK_DIALOG;
+
+               e_html_editor_selection_get_selection_coordinates (
+                       selection, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, 
&ev->before.end.y);
+               if (dialog->priv->link_element)
+                       ev->data.dom.from = webkit_dom_node_clone_node (
+                               WEBKIT_DOM_NODE (dialog->priv->link_element), TRUE);
+               else
+                       ev->data.dom.from = NULL;
+               dialog->priv->history_event = ev;
        }
 
-       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-       link = e_html_editor_dom_node_find_parent_element (
-               webkit_dom_range_get_start_container (range, NULL), "A");
-       if (!link) {
-               if ((webkit_dom_range_get_start_container (range, NULL) !=
-                       webkit_dom_range_get_end_container (range, NULL)) ||
-                   (webkit_dom_range_get_start_offset (range, NULL) !=
-                       webkit_dom_range_get_end_offset (range, NULL))) {
-
-                       WebKitDOMDocumentFragment *fragment;
-                       fragment = webkit_dom_range_clone_contents (range, NULL);
-                       link = e_html_editor_dom_node_find_child_element (
-                                       WEBKIT_DOM_NODE (fragment), "A");
-               } else {
-                       WebKitDOMNode *node;
-
-                       node = webkit_dom_range_get_common_ancestor_container (range, NULL);
-                       if (node && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
-                               link = e_html_editor_dom_node_find_parent_element (node, "A");
-                               if (link && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link))
-                                       link = NULL;
-                       } else
-                               link = WEBKIT_DOM_ELEMENT (node);
-               }
-       }
-
-       if (link) {
+       if (dialog->priv->link_element) {
                gchar *href, *text;
 
-               href = webkit_dom_html_anchor_element_get_href (
-                               WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link));
+               href = webkit_dom_element_get_attribute (dialog->priv->link_element, "href");
                text = webkit_dom_html_element_get_inner_text (
-                               WEBKIT_DOM_HTML_ELEMENT (link));
+                       WEBKIT_DOM_HTML_ELEMENT (dialog->priv->link_element));
 
                gtk_entry_set_text (
                        GTK_ENTRY (dialog->priv->url_edit), href);
@@ -297,7 +283,21 @@ html_editor_link_dialog_show (GtkWidget *widget)
                g_free (href);
        } else {
                gchar *text;
+               WebKitDOMDocument *document;
+               WebKitDOMDOMWindow *dom_window;
+               WebKitDOMDOMSelection *dom_selection;
+               WebKitDOMRange *range;
+
+               document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+               dom_window = webkit_dom_document_get_default_view (document);
+               dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+               g_object_unref (dom_window);
+
+               /* No selection at all */
+               if (!dom_selection || webkit_dom_dom_selection_get_range_count (dom_selection) < 1)
+                       gtk_widget_set_sensitive (dialog->priv->remove_link_button, FALSE);
 
+               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
                text = webkit_dom_range_get_text (range);
                if (text && *text) {
                        gtk_entry_set_text (
@@ -308,16 +308,62 @@ html_editor_link_dialog_show (GtkWidget *widget)
                                dialog->priv->remove_link_button, FALSE);
                }
                g_free (text);
+
+               g_object_unref (range);
+               g_object_unref (dom_selection);
+
+               e_html_editor_selection_save (selection);
        }
 
-       g_object_unref (range);
- chainup:
-       g_object_unref (dom_selection);
        /* Chain up to parent implementation */
        GTK_WIDGET_CLASS (e_html_editor_link_dialog_parent_class)->show (widget);
 }
 
 static void
+html_editor_link_dialog_hide (GtkWidget *widget)
+{
+       EHTMLEditorLinkDialogPrivate *priv;
+       EHTMLEditorViewHistoryEvent *ev;
+
+       priv = E_HTML_EDITOR_LINK_DIALOG_GET_PRIVATE (widget);
+       ev = priv->history_event;
+
+       if (priv->unlinking || !priv->link_element) {
+               g_clear_object (&ev->data.dom.from);
+               g_free (ev);
+       } else if (ev) {
+               EHTMLEditorLinkDialog *dialog;
+               EHTMLEditor *editor;
+               EHTMLEditorSelection *selection;
+               EHTMLEditorView *view;
+
+               dialog = E_HTML_EDITOR_LINK_DIALOG (widget);
+               editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
+               view = e_html_editor_get_view (editor);
+               selection = e_html_editor_view_get_selection (view);
+
+               ev->data.dom.to = webkit_dom_node_clone_node (
+                       WEBKIT_DOM_NODE (priv->link_element), TRUE);
+
+               if (!webkit_dom_node_is_equal_node (ev->data.dom.from, ev->data.dom.to)) {
+                       e_html_editor_selection_get_selection_coordinates (
+                               selection, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, 
&ev->after.end.y);
+                       e_html_editor_view_insert_new_history_event (view, ev);
+                       if (!ev->data.dom.from)
+                               g_object_unref (priv->link_element);
+               } else {
+                       g_object_unref (ev->data.dom.from);
+                       g_object_unref (ev->data.dom.to);
+                       g_free (ev);
+               }
+       }
+
+       priv->link_element = NULL;
+
+       GTK_WIDGET_CLASS (e_html_editor_link_dialog_parent_class)->hide (widget);
+}
+
+static void
 e_html_editor_link_dialog_class_init (EHTMLEditorLinkDialogClass *class)
 {
        GtkWidgetClass *widget_class;
@@ -326,6 +372,7 @@ e_html_editor_link_dialog_class_init (EHTMLEditorLinkDialogClass *class)
 
        widget_class = GTK_WIDGET_CLASS (class);
        widget_class->show = html_editor_link_dialog_show;
+       widget_class->hide = html_editor_link_dialog_hide;
 }
 
 static void
@@ -336,6 +383,7 @@ e_html_editor_link_dialog_init (EHTMLEditorLinkDialog *dialog)
        GtkWidget *widget;
 
        dialog->priv = E_HTML_EDITOR_LINK_DIALOG_GET_PRIVATE (dialog);
+       dialog->priv->link_element = NULL;
 
        main_layout = e_html_editor_dialog_get_container (E_HTML_EDITOR_DIALOG (dialog));
 
@@ -406,3 +454,17 @@ e_html_editor_link_dialog_new (EHTMLEditor *editor)
                        "title", _("Link Properties"),
                        NULL));
 }
+
+void
+e_html_editor_link_dialog_show (EHTMLEditorLinkDialog *dialog,
+                                WebKitDOMNode *link)
+{
+       EHTMLEditorLinkDialogClass *class;
+
+       g_return_if_fail (E_IS_HTML_EDITOR_LINK_DIALOG (dialog));
+
+       dialog->priv->link_element = link ? WEBKIT_DOM_ELEMENT (link) : NULL;
+
+       class = E_HTML_EDITOR_LINK_DIALOG_GET_CLASS (dialog);
+       GTK_WIDGET_CLASS (class)->show (GTK_WIDGET (dialog));
+}
diff --git a/e-util/e-html-editor-link-dialog.h b/e-util/e-html-editor-link-dialog.h
index a1e426f..c3a9709 100644
--- a/e-util/e-html-editor-link-dialog.h
+++ b/e-util/e-html-editor-link-dialog.h
@@ -65,6 +65,8 @@ GType         e_html_editor_link_dialog_get_type
                                                (void) G_GNUC_CONST;
 GtkWidget *    e_html_editor_link_dialog_new   (EHTMLEditor *editor);
 
+void           e_html_editor_link_dialog_show  (EHTMLEditorLinkDialog *dialog,
+                                                WebKitDOMNode *link);
 G_END_DECLS
 
 #endif /* E_HTML_EDITOR_LINK_DIALOG_H */
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 9c709d8..9bd803d 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -266,6 +266,7 @@ print_history_event (EHTMLEditorViewHistoryEvent *event)
                        break;
                case HISTORY_HRULE_DIALOG:
                case HISTORY_IMAGE_DIALOG:
+               case HISTORY_LINK_DIALOG:
                case HISTORY_CELL_DIALOG:
                case HISTORY_TABLE_DIALOG:
                case HISTORY_TABLE_INPUT:
@@ -3531,6 +3532,7 @@ free_history_event_content (EHTMLEditorViewHistoryEvent *event)
                case HISTORY_TABLE_INPUT:
                case HISTORY_PAGE_DIALOG:
                case HISTORY_UNQUOTE:
+               case HISTORY_LINK_DIALOG:
                        if (event->data.dom.from != NULL)
                                g_object_unref (event->data.dom.from);
                        if (event->data.dom.to != NULL)
@@ -11721,6 +11723,72 @@ undo_redo_image_dialog (EHTMLEditorView *view,
 }
 
 static void
+undo_redo_link_dialog (EHTMLEditorView *view,
+                       EHTMLEditorViewHistoryEvent *event,
+                       gboolean undo)
+{
+       EHTMLEditorSelection *selection;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *anchor, *element;
+
+       selection = e_html_editor_view_get_selection (view);
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+
+       if (undo)
+               restore_selection_to_history_event_state (view, event->after);
+       else
+               restore_selection_to_history_event_state (view, event->before);
+
+       e_html_editor_selection_save (selection);
+
+       element = webkit_dom_document_get_element_by_id (document, "-x-evo-selection-start-marker");
+       if (!element)
+               return;
+
+       anchor = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (element), "A");
+       if (undo) {
+               if (anchor) {
+                       if (!event->data.dom.from)
+                               remove_node (WEBKIT_DOM_NODE (anchor));
+                       else
+                               webkit_dom_node_replace_child (
+                                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (anchor)),
+                                       webkit_dom_node_clone_node (event->data.dom.from, TRUE),
+                                       WEBKIT_DOM_NODE (anchor),
+                                       NULL);
+               }
+       } else {
+               if (!event->data.dom.to) {
+                       if (anchor)
+                               remove_node (WEBKIT_DOM_NODE (anchor));
+               } else {
+                       if (WEBKIT_DOM_IS_ELEMENT (event->data.dom.from) && anchor) {
+                               webkit_dom_node_replace_child (
+                                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (anchor)),
+                                       webkit_dom_node_clone_node (event->data.dom.to, TRUE),
+                                       WEBKIT_DOM_NODE (anchor),
+                                       NULL);
+                       } else {
+                               webkit_dom_node_insert_before (
+                                       webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+                                       webkit_dom_node_clone_node (event->data.dom.to, TRUE),
+                                       WEBKIT_DOM_NODE (element),
+                                       NULL);
+
+                               if (event->data.dom.from)
+                                       e_html_editor_view_exec_command (
+                                               view, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+                       }
+               }
+       }
+
+       if (undo)
+               restore_selection_to_history_event_state (view, event->before);
+       else
+               e_html_editor_selection_restore (selection);
+}
+
+static void
 undo_redo_table_dialog (EHTMLEditorView *view,
                         EHTMLEditorViewHistoryEvent *event,
                         gboolean undo)
@@ -12496,6 +12564,9 @@ e_html_editor_view_redo (EHTMLEditorView *view)
                case HISTORY_IMAGE_DIALOG:
                        undo_redo_image_dialog (view, event, FALSE);
                        break;
+               case HISTORY_LINK_DIALOG:
+                       undo_redo_link_dialog (view, event, FALSE);
+                       break;
                case HISTORY_TABLE_DIALOG:
                        undo_redo_table_dialog (view, event, FALSE);
                        break;
@@ -12611,6 +12682,9 @@ e_html_editor_view_undo (EHTMLEditorView *view)
                case HISTORY_IMAGE_DIALOG:
                        undo_redo_image_dialog (view, event, TRUE);
                        break;
+               case HISTORY_LINK_DIALOG:
+                       undo_redo_link_dialog (view, event, TRUE);
+                       break;
                case HISTORY_TABLE_DIALOG:
                        undo_redo_table_dialog (view, event, TRUE);
                        break;
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index d53098b..e1fc64f 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -100,6 +100,7 @@ enum EHTMLEditorViewHistoryEventType {
        HISTORY_IMAGE_DIALOG,
        HISTORY_INSERT_HTML,
        HISTORY_ITALIC,
+       HISTORY_LINK_DIALOG,
        HISTORY_MONOSPACE,
        HISTORY_PAGE_DIALOG,
        HISTORY_PASTE,
diff --git a/e-util/e-html-editor.c b/e-util/e-html-editor.c
index 8935db4..ce2d8e2 100644
--- a/e-util/e-html-editor.c
+++ b/e-util/e-html-editor.c
@@ -350,6 +350,11 @@ html_editor_update_actions (EHTMLEditor *editor,
                editor->priv->image = g_object_ref (node);
 
        visible = (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK);
+       if (visible) {
+               g_object_unref (editor->priv->current_node);
+               editor->priv->current_node = webkit_dom_node_get_parent_node (node);
+               gtk_action_set_visible (ACTION (CONTEXT_INSERT_LINK), FALSE);
+       }
        gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_LINK), visible);
 
        visible = (WEBKIT_DOM_IS_HTMLHR_ELEMENT (node));


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